最近在业余兼职中碰到网站有国际化,之前听说过,但确实没做过,经过几天网上查资料和摸索,最终实现了基于angular-translate的国际化。
要实现网站国际化,主要分为两部分,第一部分是html上静态数据的国际化,比如按钮的文本;第二部分就是接口返回数据的国际化。
我们先来分析第一部分的国际化。
静态
首先,编写前端静态文本的国际化文件,包含英语、日语和中文三个。
静态文本多语言编写
en.js
var LocaleEn = {
home:"Home",
about:"About Us",
cooperation:"Cooperation",
login:"Login",
register:"Register"
}
ja.js
var LocaleJa = {
home:"トップページ",
about:"私たちについて",
cooperation:"レストラン提携",
login:"登録",
register:"登記"
}
zh.js
var LocaleZh = {
home:"首页",
about:"关于我们",
cooperation:"餐厅合作",
login:"登录",
register:"注册"
}
angular-translate初始化
$translateProvider
.translations('en', LocaleEn)
.translations('zh', LocaleZh)
.translations('ja', LocaleJa)
.preferredLanguage(Utils.getLanguage());
# Utils.getLanguage()主要是根据缓存语言或当前浏览器语言返回en、ja或者zh
静态文本展示
<a class="nav_link" href="">{{ 'home' | translate }}</a>
语言更换
$scope.changeLanguage = function () {
Utils.setStorage("language", $scope.lang); # 缓存语言选择
$translate.use($scope.lang);
}
经过如上处理,语言切换已经将页面静态文本根据对应的语言翻译正确了,接下来就需要处理接口数据中的国际化。
动态
通过上面的代码,要实现接口数据的国际化,需要在LocaleEn、LocaleZh、LocaleJa中增加相应的翻译对照。
笔者通过新增一个后端接口,将所有页面会用到的多语言文本对照返回,同时经过数据量的统计,因为主要是返回一些基础数据的多语言,对服务器和数据库的压力比较小。
当然,写这个接口前,你需要保证每个基础数据在库中包含有相应的多语言文本。
接下来看看接口返回
后端接口
{
"code": "200",
"data": [
{
"en": "Sichuan Province",
"id": "agentarea_name_8",
"ja": "四川省",
"zh": "四川省"
},
{
"en": "Japan",
"id": "agentarea_name_10",
"ja": "日本",
"zh": "日本"
}
],
"message": "success",
"success": true
}
接口返回中主要涉及id和相应的多语言文本,id的生成规则为"类型_属性_实例id",下面需要更改angular-translate初始化,保证使用LoacleJa之前已经加载了接口返回的多语言文本。
加载后端多语言文本
Utils.initResourceTranslate(); # 增加加载多语言后端接口返回数据
$translateProvider
.translations('en', LocaleEn)
.translations('zh', LocaleZh)
.translations('ja', LocaleJa)
.preferredLanguage(Utils.getLanguage());
initResourceTranslate: function () {
console.log("document.domain;", document.domain)
$.ajax({
headers: {
'tourcandy-browser-type': "web"
},
type: "GET",
url: "/tourcandy/api/locale/translate",
async: false, #将ajax调用修改为同步,保证正确的执行顺序
success: function (data) {
console.log("resource translate", data)
if (data.success) {
for (var i = 0; i < data.data.length; i++) {
var tranlate = data.data[i];
LocaleZh[tranlate.id] = tranlate.zh;
LocaleEn[tranlate.id] = tranlate.en;
LocaleJa[tranlate.id] = tranlate.ja;
}
}
}
});
}
接下来就是如何使用后端多语言,要实现文本的正确翻译,就必须传入相应的id.
<a class="nav_link" href="">{{ 'home' | translate }}</a>
这种方式是没办法传入id的,因此要自定义filter。
自定义filter
App.filter('translateResource', ["$parse", "$translate",function ($parse, $translate) {
var translateResourceFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {
console.log("translateResource filter", translationId, interpolateParams, interpolation, forceLanguage, angular.isObject(interpolateParams))
if (!angular.isObject(interpolateParams)) {
var ctx = this || {
'__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'
};
interpolateParams = $parse(interpolateParams)(ctx);
}
if (interpolateParams && interpolateParams._id) {
translationId += interpolateParams._id
}
return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);
};
if ($translate.statefulFilter()) {
translateResourceFilter.$stateful = true;
}
return translateResourceFilter;
}]);
基本是将translate这个filter代码拷贝过来,增加
if (interpolateParams && interpolateParams._id) {
translationId += interpolateParams._id
}
使用
<a class="condition_menu" ng-repeat="city in citys">{{ 'agentarea_name_' | translateResource:{_id:city.id} }}</a>