我见过一些 Angular 的 i18n 插件,但我不想重新发明轮子。i18next 是一个很好的库,所以我打算使用它。
我创建了一个指令 i18n,它只调用 i18n 库:
define(['app', 'jquery', 'i18n'], function(app, $, i18n) {'use strict';
app.directive('i18n', function() {
return function($scope, elm, attrs) {
attrs.$observe('i18n', function(value) {
if ($.fn.i18n) {// for some reason, it isn't loaded quickly enough and first directives process fails
$(elm).i18n();
}
});
};
});
});
在我的页面上,我可以即时更改语言:
<a ng-repeat="l in languages"> <img ng-src="images/{{l.id}}.png" title="{{l.label}}" ng-click="setLanguage(l.id)" /> </a>
现在,我在 html 标签上定义的主控制器:
define(['app', 'i18n', 'jquery'], function(app, i18n, $) {'use strict';
return app.controller('BuilderController', ['$scope', '$location',
function BuilderController($scope, $location) {
/* Catch url changes */
$scope.$watch(function() {
return $location.path();
}, function() {
$scope.setLanguage(($location.search()).lang || 'en');
});
/* Language */
$scope.languages = [{
id : "en",
label : "English"
}, {
id : "fr",
label : "Français"
}];
$scope.$watch('language', function() {
$location.search('lang', $scope.language);
i18n.init({
resGetPath : 'i18n/__lng__/__ns__.json',
lng : $scope.language,
getAsync : false,
sendMissing : true,
fallbackLng : 'en',
debug : true
});
$(document).i18n();
});
$scope.setLanguage = function(id) {
$scope.language = id;
};
}]);
});
工作原理:语言观察者使用新的语言环境初始化 i18n 对象,然后使用 i18n jquery 扩展更新所有 DOM。在这个特殊事件之外,我的指令完美地完成了所有其他任务(使用 i18n 指令并在稍后呈现的模板)。
虽然它工作正常,但我知道我不应该在控制器内操作 DOM,但由于最终什么都没有发生,我还没有找到更好的解决方案。
理想情况下,我希望 Angular 重新编译所有 DOM,解析所有指令以更新标签,但我不知道该怎么做。我试过 $scope.$apply() :不工作,因为此时我已经在摘要中使用了 Scope.onReady 插件,但没有更好的结果。
显然,我对 Angular 很陌生,而且我很难准确地理解事情是如何工作的。