使用Angular-CLI发布一个i18n(国际化)应用
原文作者:Philippe Martin
译者:王芃
原文地址:https://medium.com/@feloy/deploying-an-i18n-angular-app-with-angular-cli-fc788f17e358#.gkkec7fkt
在这篇文章中我将会解释如何使用angular-cli从头创建一个国际化的Angular2应用以及如何把这个应用部署到Apache服务器。
文中涉及到的软件依赖版本如下:
- angular-cli:1.0.0-beta.24
- angular: 2.4.1
- Apache 2.4
文中描述的样例App已经放在github上了:https://github.com/feloy/angular-cli-i18n-sample
新鲜出炉的i18n App
我们首先使用angular-cli创建一个Angular App:
$ ng new angular-cli-i18n-sample
在 app.component.html
中,我们做一点小改动,加入一些用于i18n的文本:
<h1 i18n>Hello world!</h1>
接下来,我们需要创建一个 xlf
文件。但在创建之前,我们需要对 src/tsconfig.json
做一些小改动:
{
"compilerOptions": {
[...]
},
"exclude": [ "test.ts" ],
"angularCompilerOptions": { "genDir": "i18n" }
}
在 package.json
中我们也需要加入一个脚本定义,使用 ng-xi18n
这个工具来生成一个可翻译的文本文件:
{
[...]
"scripts": {
[...]
"extract-i18n": "cd src && ng-xi18n"
}
[...]
}
现在,我们可以使用下面的命令来生成 src/i18n/messages.xlf
了:
$ npm run extract-i18n
我们现在要创建不同的语言翻译文件了,首先是英文翻译,拷贝 src/i18n/messages.xlf
成 src/i18n/messages.en.xlf
:
[...]
<trans-unit id="[...]" datatype="html">
<source>Hello World!</source>
<target>Hello World!</target>
</trans-unit>
[...]
同样创建法语的 src/i18n/messages.fr.xlf
:
[...]
<trans-unit id="[...]" datatype="html">
<source>Hello World!</source>
<target>Salut la foule !</target>
</trans-unit>
[...]
再来创建一个西班牙版本 src/i18n/messages.es.xlf
:
[...]
<trans-unit id="[...]" datatype="html">
<source>Hello World!</source>
<target>¿hola, qué tal?</target>
</trans-unit>
[...]
现在我们可以使用 angular-cli
在启动应用时使用你的语言偏好,以西班牙语为例:
$ ng serve --aot \
--i18n-file=src/i18n/messages.es.xlf \
--locale=es \
--i18n-format=xlf
现在你可以打开浏览器访问 http://localhost:4200
,然后就应该可以看到西班牙语版本的应用了。
发布到生产环境的准备工作
在生产环境,我们希望依照不同语言,以不同的子目录的形式呈现不同语言版本的app。例如西班牙语版本可以通过 http://myapp.com/es/
来访问;而法语版本通过 http://myapp.com/fr/
来访问。当然我们还希望根URL http://myapp.com/
可以重定向到我们选择的语言选项。
要这么做的话,我猜我们需要根据不同的语言来改变 base href
,比如改成 es
, en
和 fr
。幸运的是,angular-cli
有一个特殊的命令行开关:--bh,这个开关允许我们在编译时声明 base href
。
下面给出一个命令行脚本(译者注:*nix版本可用,windows版本需要改写一下),这个脚本可以帮我们为不同语言创建不同的bundle
$ for lang in es en fr; do \
ng build -o dist/$lang \
--aot \
-prod \
--bh /$lang/ \
--i18n-file=src/i18n/messages.$lang.xlf \
--i18n-format=xlf \
--locale=$lang; \
done
当然我们可以在 package.json
中给出这个命令的脚本定义,这样我们就可以使用npm脚本来执行了:npm run build-i18n
{
[...]
"scripts": {
[...]
"build-i18n": "for lang in en es fr; do ng build -o dist/$lang --aot -prod --bh /$lang/ --i18n-file=src/i18n/messages.$lang.xlf --i18n-format=xlf --locale=$lang; done"
}
[...]
}
现在,我们在dist目录下有了3个子目录: es/
, fr/
和 en/
,里面有对应不同语言的bundle。
Apache配置
下面是一个虚拟主机配置,这个配置在 /var/www
目录来启动我们的不同版本的bundle文件,所以我们得把刚刚生成的3个目录 es/
, fr/
和 en/
拷贝到这里。
有这样一个配置后,访问 http://www.myapp.com
会根据浏览器优选的语言首选项来重定向到不同的子目录(如果没有匹配的语言时 en
作为fallback)。当然你可以通过改动url来访问其他语言版本。
<VirtualHost *:80>
ServerName www.myapp.com
DocumentRoot /var/www
<Directory "/var/www">
RewriteEngine on
RewriteBase /
RewriteRule ^../index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (..) $1/index.html [L]
RewriteCond %{HTTP:Accept-Language} ^fr [NC]
RewriteRule ^$ /fr/ [R]
RewriteCond %{HTTP:Accept-Language} ^es [NC]
RewriteRule ^$ /es/ [R]
RewriteCond %{HTTP:Accept-Language} !^es [NC]
RewriteCond %{HTTP:Accept-Language} !^fr [NC]
RewriteRule ^$ /en/ [R]
</Directory>
</VirtualHost>
加餐:为不同语言增加链接
如果在应用中有不同语言的选项链接,用户可以点击这些链接来访问不同语言版本,那就太好了(译者注:汗,这不是标配需求吗?)。
在Angular2中,需要知道一个小技巧:当前语言是可以通过 LOCALE_ID
取得的。
下面我们演示一下如何取得 LOCALE_ID
、显示不同语言的列表:
// app.component.ts
import { Component, LOCALE_ID, Inject } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
languages = [
{ code: 'en', label: 'English'},
{ code: 'es', label: 'Español'},
{ code: 'fr', label: 'Français'}
];
constructor(@Inject(LOCALE_ID) protected localeId) {}
}
<!-- app.component.html -->
<h1 i18n>Hello World!</h1>
<template ngFor let-lang [ngForOf]="languages">
<span *ngIf="lang.code !== localeId">
<a href="/{{lang.code}}/">{{lang.label}}</a> </span>
<span *ngIf="lang.code === localeId">{{lang.label}} </span>
</template>