更新 : 2017-06-17
<h1 i18n="site header|An introduction header for this sample">Hello {{ name }} world</h1>
<source>Hello <x id="INTERPOLATION"/> world</source> <target>哈嘍 <x id="INTERPOLATION"/> 世界</target>
angular 支持 interpolation {{ }}
你要在 target 去掉 interpolation 也是 ok 的.
說說真實項目中的場景. 除了這種能寫在模板上的翻譯,我們通常還有一些動態的翻譯比如 sql 資料.
比如 :
class Member
{
name_en : string;
name_cn : string;
}
我的做法是為每一個 member 對象添加一個 name 屬性, getter(){ if( this.locale == 'zh-CN'...) { return this.... } }
import { LOCALE_ID, Inject } from '@angular/core';
constructor( @Inject(LOCALE_ID) private locale: string) { }
locale 如果沒有使用 i18n 的話,會拿 user-agent 的哦
日期 : 2017-04-24
refer :
https://v2.angular.io/docs/ts/latest/cookbook/i18n.html#!#aot
https://github.com/angular/angular-cli/issues/2201
http://blog.danieleghidoli.it/2017/01/15/i18n-angular-cli-aot/
針對翻譯, ng 提供了一個解決方案.
流程大概是這樣的.
在寫模板的時候我們通過一些記號, 標識出要翻譯的部分
<h1 i18n="User welcome|An introduction header for this sample">Hello i18n!</h1>
類似上面這樣, i18n 是個標識, 內容是一些描述
所有模板都寫好了以后
windows cmd 運行 "./node_modules/.bin/ng-xi18n" --i18nFormat=xlf
這時 ng 會從我們的模板中提取這些標識的內容創建出一個 messages.xlf 的 file.
<?xml version="1.0" encoding="UTF-8" ?> <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> <file source-language="en" datatype="plaintext" original="ng2.template"> <body> <trans-unit id="af2ccf4b5dba59616e92cf1531505af02da8f6d2" datatype="html"> <source>Hello i18n!</source> <target>我愛你媽</target> <note priority="1" from="description">An introduction header for this sample</note> <note priority="1" from="meaning">User welcome</note> </trans-unit> </body> </file> </xliff>
大致上長這樣, <target> 一開始是空着的, 我們把翻譯寫進去.
如果你支持很多語言,那么就 copy paste 這個 file 給每個 file 一個特別的名字比如 : messages.cn.xlf, messages.en.xlf
翻譯完成了以后
cmd : ng build --prod --i18nFile=./src/locale/messages.zh-cn.xlf --locale=zh-CN --i18nFormat=xlf --bh=/cn/ --output-path=cn
ng serve --aot --i18nFile=./src/locale/messages.zh-cn.xlf --locale=zh-CN --i18nFormat=xlf (只有 aot 可以跑 ng serve 哦)
bh 是 base href, output-path 默認是 dist, 因為我們有很多版本語言, 所以我們需要重復 build 很多個版本出來.
最后就是 publish to server 咯.
整個流程看完. 我們可以了解到, ng 的做法是讓每個語言獨立一個 index.html 版本.
好處是快咯,隔離的好咯
壞處是, 如果要改視乎 rebuild 的工作量不少. 當然我覺得這個應該是最后的環節了. 不太可能一直改.
網頁中除了一般的靜態資料需要翻譯,動態資料也是需要翻譯的,比如 sql 的 data, alert error message. 這些不在 ng 包含的范圍內, 我們得自己處理哦。
外傳 :
refer : https://github.com/googlei18n/libphonenumber
介紹一下 google i18n/ libphonenumber
做國際站, 電話號碼也是需要處理好的.
npm install google-libphonenumber --save
npm install @types/google-libphonenumber --save-dev ( 版本可能不夠新哦, 比如目前是 7.4 但是 lib 已經 8.4 了, getSupportRegions 方法就沒找着 /.\ )
import { PhoneNumberUtil, PhoneNumberFormat } from 'google-libphonenumber'; let sg = '+65 9026 9356'; let phoneUtil = PhoneNumberUtil.getInstance(); let number = phoneUtil.parse(sg, ''); let code = phoneUtil.getRegionCodeForNumber(number); //SG let ok = phoneUtil.isValidNumber(number); let formatA = phoneUtil.format(number, PhoneNumberFormat.INTERNATIONAL); //+65 9026 9356 let formatB = phoneUtil.format(number, PhoneNumberFormat.NATIONAL); // 9026 9356
需要注意的是,任何操作都是使用 phone number 對象, 所以記得要 parse.
主要用途是驗證是不是 phone number, 還有轉換格式.
除了 js 還有其它版本的哦,比如 c#.
public ActionResult Index() { var sg = "+65 9026 9356"; var phoneUtil = PhoneNumberUtil.GetInstance(); var number = phoneUtil.Parse(sg, ""); var code = phoneUtil.GetRegionCodeForNumber(number); //SG var ok = phoneUtil.IsValidNumber(number); var formatA = phoneUtil.Format(number, PhoneNumberFormat.INTERNATIONAL); //+65 9026 9356 var formatB = phoneUtil.Format(number, PhoneNumberFormat.NATIONAL); // 9026 9356 List<string> x = phoneUtil.GetSupportedRegions().ToList(); int codex = phoneUtil.GetCountryCodeForRegion(x[0]); return View(); }