第一節:初識Angular-CLI
第二節:登入元件的構建
第三節:建立一個待辦事項應用
第四節:進化!模組化你的應用
第五節:多使用者版本的待辦事項應用
第六節:使用第三方樣式庫及模組優化用
第七節:給元件帶來活力
Rx--隱藏在Angular 2.x中利劍
Redux你的Angular 2應用
第八節:查缺補漏大合集(上)
第九節:查缺補漏大合集(下)
使用Angular-CLI釋出一個i18n(國際化)應用
原文作者:Philippe Martin
譯者:王芃
在這篇文章中我將會解釋如何使用angular-cli從頭建立一個國際化的Angular2應用以及如何把這個應用部署到Apache伺服器。
文中涉及到的軟體依賴版本如下:
- angular-cli:1.0.0-beta.24
- angular: 2.4.1
- Apache 2.4
文中描述的樣例App已經放在github上了:github.com/feloy/angul…
新鮮出爐的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>複製程式碼