一、I18n and L10n in AngularJS
1. 什么是I18n和L10n?
国际化(Internationalization),简称I18n,是让产品开发在一个他们可以简单地对产品进行语言、文化的本地化的方法的规范。本地化(Localization),简称L10n,一个使得应用、文本有适应特殊的文化或者语言市场的能力的规范。对于应用开发者,使一个程序国际化,意味着需要从程序中抽取所有字符串和其他区域较为特别的地方(例如日期和货币格式)。使一个程序本地化,意味着需要提供根据I18n抽取出来的块进行翻译和格式本地化。
2. 当前angular支持什么级别的I18n、L10n?
当前,angular对datetime、number、currency过滤器提供I18n、L10n支持。
此外,angular通过ngPluralize directive(http://docs.angularjs.org/api/ng.directive:ngPluralize
)支持多元化的本地化。
所有可本地化的控件都依赖于通过$locale服务管理的区域设定特性规则集。
为了让读者看到实际例子,官方准备了一些网页例子,展示如何通过区域规则集合变量使用angular过滤器。我们可以在Github(https://github.com/angular/angular.js/tree/master/i18n/e2e
)或者在angular开发包中的i18n/e2e中找到对应的例子。
3. 什么是区域id(locale id)?
locale是一个特定地理、政治、文化的地区。最常用的locale id 由两部分组成:语言代码和国家代码。例如,en-US,en-AU,zh-CN都是有效的locale ID,都包含语言代码和国家代码。因为在locale ID中指定的国家编码是可选的,locale ID,例如en、zh和sk都是有效的。查看网站ICU(http://userguide.icu-project.org/locale
),那里有更多关于locale ID的信息。
4. angular支持的locale
angular将数字、日期时间格式的规则集合分开放在不同的文件中,每个文件独有一个区域。我们可以在这里(https://github.com/angular/angular.js/tree/master/i18n/locale
)找到当前支持的locale列表
二、在angular
中定制locale
规则
在angular
中定制locale
有两个方式:
1. 预先绑定的规则集合(Pre-bundled rule sets
)
我们可以通过将locale-specific
的文件连接到angular.js
或者angular.min.js
之后,实现将angular
和预先绑定(pre-bundle
)期望的locale
文件。
例如,在*nix中,我们可以通过以下命令来创建一个包含德国区域本地化规则的文件的angular.js
文件:
cat angular.js i18n/angular-locale_de-ge.js > angular_de-ge.js
当从应用程序使用angular_de-ge.js
脚本代替一般的angular.js
脚本开始,angular
开始自动预先配置(pre-configured
)德国地区的本地化规则。
2. 包含locale.js
脚本到index.html
页
我们也可以包含指定区域的js文件到页面当中。例如,如果一个客户端需要德国区域文件,我们可以提供类似以下的页面:
<html ng-app>
<head>
...
<script src="angular.js">script>
<script src="i18n/angular-locale_de-ge.js">script>
...
head>
...
html>
上述两种方法,都要求我们为本地化而提供各个区域的不同的index.html页或者js文件。我们还需要配置我们的服务器提供正确的、符合期望的区域设置文件。
然而,第二种方式(包含区域设置文件到页面中)会比较慢,因为需要多加载一个脚本。(-_-!!!!)。
三、陷阱(“Gotchas”)
1. 货币符号陷阱
angular
的currency filter
允许我们从locale service
中使用默认的货币符号,我们也可以提供自定义的货币符号。如果我们的应用只在一个区域中使用,那么我们可以依赖(设置)默认货币符号。但是,如果我们预料到其他区域的用户也会使用到我们的应用的话,我们应该提供我们自定义的货币符号,确保用户能够明白实际的值。
例如,如果我们想通过绑定currency filter
来显示账户余额为1000元:{{ 1000 | currency}},我们的应用当前是使用en-US的区域设置,那么将会显示”$1000.00”。然而,如果一些其他区域(例如中国大陆)的用户访问我们的应用,用户浏览器会指定区域设置为“中国大陆”,然后余额将显示为“¥1000.00”(很悲催的错误啊,汇率…)。
在这个例子中,当我们需要设置filter
的时候,我们需要通过对currency filter
(http://docs.angularjs.org/api/ng.filter:currency
)提供货币符号作为参数来重写默认货币符号,参数如:USD 。这样,angular会忽略任何区域设置的变化,一直显示余额为“USD 1000.00”。
2. 翻译长度陷阱
记住,翻译字符串、事件格式时,长度的变化可能会很大。例如“June 3, 1977”翻译为西班牙语时变为“3 de junio de 1977”。当然,还可能会有更加极端的状况。因此,当我们对应用进行国际化时,我们需要设置相应的CSS
规则并且进行全面测试,确保UI组件不会折行(变型)。
3. 时区
记住,angular
的datetime filter
是使用浏览器端设置的时区的。所以,同一个应用将根据运行应用的计算机的时区设置而显示不同的时间信息,而不是取决于javascript
或者angular
的开发者指定的时区。
一、ngLocal就是一个模块,支持日期,数字和货币的国际化和本地化。另外,AngularJS还通过ngPluralize指令支持本地多元化。
angular.module("ngLocale", [], ["$provide",
function($provide) {
var PLURAL_CATEGORY = {
ZERO : "zero",
ONE : "one",
TWO : "two",
FEW : "few",
MANY : "many",
OTHER : "other"
};
$provide.value("$locale", {
"DATETIME_FORMATS" : {
"MONTH" : ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
"SHORTMONTH" : ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
"DAY" : ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
"SHORTDAY" : ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
"AMPMS" : ["上午", "下午"],
"medium" : "yyyy-M-d ah:mm:ss",
"short" : "yy-M-d ah:mm",
"fullDate" : "y年M月d日EEEE",
"longDate" : "y年M月d日",
"mediumDate" : "yyyy-M-d",
"shortDate" : "yy-M-d",
"mediumTime" : "ah:mm:ss",
"shortTime" : "ah:mm"
},
"NUMBER_FORMATS" : {
"DECIMAL_SEP" : ".",
"GROUP_SEP" : ",",
"PATTERNS" : [{
"minInt" : 1,
"minFrac" : 0,
"macFrac" : 0,
"posPre" : "",
"posSuf" : "",
"negPre" : "-",
"negSuf" : "",
"gSize" : 3,
"lgSize" : 3,
"maxFrac" : 3
}, {
"minInt" : 1,
"minFrac" : 2,
"macFrac" : 0,
"posPre" : "\u00A4",
"posSuf" : "",
"negPre" : "\u00A4-",
"negSuf" : "",
"gSize" : 3,
"lgSize" : 3,
"maxFrac" : 2
}],
"CURRENCY_SYM" : "¥"
},
"pluralCat" : function(n) {
return PLURAL_CATEGORY.OTHER;
},
"id" : "zh-cn"
});
}]);
});
二、还有一种方法就是自定义i18n,毕竟官方给的i18n支持的本地化仅作用于日期,数字和货币。看下面的例子
<div ng-controller="MyCtrl">
<h2>i18n Testh2>
<ul>
<li>{{'firstname' |i18n}}li>
<li>{{'lastname' |i18n}}li>
<li>{{'address' |i18n}}li>
<hr>
<li><button class="btn btn-primary" ng-click="changeLang()">Change Languagebutton>
ul>
div>
var myApp = angular.module('myApp',['localization']);
myApp.controller('MyCtrl', function($rootScope) {
// default language setting
$rootScope.language = "en_US";
$rootScope.changeLang = function () {
if ($rootScope.language === "en_US") {
$rootScope.language = "zh_CN";
} else {
$rootScope.language = "en_US";
}
};
})
// i18n filter
angular.module('localization', [])
.filter('i18n', ['localizedTexts', '$rootScope', function (localizedTexts, $rootScope) {
return function (text) {
currentLanguage = $rootScope.language || 'en_US';
if (localizedTexts[currentLanguage].hasOwnProperty(text)) {
return localizedTexts[currentLanguage][text];
}
return text;
};
}])
// separate dictionary file
angular.module('localization')
.value('localizedTexts', {
'zh_CN' : {
'firstname': '名',
'lastname': '姓',
'address': '地址'
},
'en_US' : {
'firstname': 'First Name',
'lastname': 'Last Name',
'address': 'Home Address'
}
});
http://www.bootcdn.cn/angular-i18n/