我在AngularJS应用程序中使用angular-translate for i18n .
对于每个应用程序视图,都有一个专用控制器 . 在下面的控制器中,我将值设置为页面 Headers .
代码
HTML
<h1>{{ pageTitle }}</h1>
JavaScript
.controller('FirstPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.pageTitle = $filter('translate')('HELLO_WORLD');
}])
.controller('SecondPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.pageTitle = 'Second page title';
}])
我正在使用angular-translate-loader-url扩展名加载翻译文件 .
问题
在初始页面加载时,将显示翻译键,而不是该键的翻译 . 翻译是 Hello, World!
,但我看到 HELLO_WORLD
.
我第二次去页面,一切都很好,并显示翻译版本 .
我假设该问题与控制器将值分配给 $scope.pageTitle
时可能尚未加载转换文件的事实有关 .
备注
使用 <h1>{{ pageTitle | translate }}</h1>
和 $scope.pageTitle = 'HELLO_WORLD';
时,翻译从第一次开始就完美无缺 . 这个问题是我并不总是想要使用翻译(例如,对于第二个控制器,我只想传递一个原始字符串) .
问题
这是一个已知的问题/限制吗?怎么解决这个问题?
5 回答
EDIT :请参阅PascalPrecht(angular-translate的作者)的答案,以获得更好的解决方案 .
加载的异步性质导致问题 . 你看,有了
{{ pageTitle | translate }}
,Angular会看表达;加载本地化数据时,表达式的值会更改并更新屏幕 .所以,你可以自己做:
但是,这将在每个摘要周期运行观察表达式 . 这是次优的,可能会也可能不会导致可见的性能下降 . 无论如何它是Angular所做的,所以它不能那么糟糕......
推荐:不要在控制器中翻译,在您的视图中翻译
我建议让你的控制器免于翻译逻辑,并直接在你的视图中翻译你的字符串,如下所示:
使用提供的服务
Angular Translate提供
$translate
服务,您可以在控制器中使用该服务 .$translate
服务的示例用法可以是:translate服务还有一个方法,可以使用
$translate.instant()
直接翻译字符串而无需处理承诺:使用
$translate.instant()
的缺点可能是,如果您正在加载异步,则尚未加载语言文件 .使用提供的过滤器
这是我的首选方式,因为我不必以这种方式处理承诺 . 过滤器的输出可以直接设置为范围变量 .
使用提供的指令
由于@PascalPrecht是这个令人敬畏的库的创建者,我建议使用his advise (see his answer below)并使用提供的指令,它似乎处理非常智能的翻译 .
实际上,你应该使用translate指令代替这些东西 .
该指令负责异步执行,并且在转换没有动态值的情况下也非常聪明地监视范围上的转换ID .
但是,如果没有办法,你真的在控制器中使用
$translate
服务,你应该使用$rootScope
与$translate.instant()
结合在$translateChangeSuccess
事件中包装调用,如下所示:那么为什么
$rootScope
而不是$scope
?原因在于,angular-translate的事件在$rootScope
上编辑$emit
而不是$broadcast
编辑$scope
因为我们不需要通过整个范围层次结构进行广播 .为什么
$translate.instant()
而不仅仅是async$translate()
?当$translateChangeSuccess
事件被触发时,它确定所需的转换数据在那里并且没有发生异步执行(例如异步加载器执行),因此我们可以使用同步的$translate.instant()
并且只假设转换可用 .从版本2.8.0开始,还有
$translate.onReady()
,它会返回一个在转换准备就绪后立即解析的承诺 . See the changelog .要在控制器中进行翻译,您可以使用
$translate
服务:该语句仅对控制器激活进行转换,但不检测语言的运行时更改 . 为了实现这种行为,你可以听
$rootScope
事件:$translateChangeSuccess
并做同样的翻译那里:当然,您可以将
$translate
服务封装在方法中,并在控制器和$translateChangeSucess
侦听器中调用它 .发生的事情是Angular-translate正在使用基于事件的系统观察表达式,就像在任何其他绑定或双向绑定的情况下一样,在检索数据时会触发事件,并且值会更改,显然不适用于翻译 . 当然,与页面上的其他动态数据不同,翻译数据必须立即显示给用户 . 页面加载后无法弹出 .
即使您可以成功调试此问题,更大的问题是涉及的开发工作是巨大的 . 开发人员必须手动提取站点上的每个字符串,将其放在.json文件中,通过字符串代码手动引用它(在本例中为“pageTitle”) . 大多数商业网站都有成千上万的字符串需要这样做 . 而这仅仅是个开始 . 您现在需要一个系统,当其中一些基础文本发生变化时保持翻译同步,将翻译文件发送给各个翻译器的系统,将它们重新集成到构建中,重新部署站点以便翻译人员可以看到他们在上下文中的变化,以及不断变化 .
此外,由于这是一个基于事件的“绑定”系统,因此会为页面上的每个字符串触发一个事件,这不仅是一种转换页面的较慢方式,而且可能会减慢页面上的所有操作,如果你开始向它添加大量事件 .
无论如何,使用后处理翻译平台对我来说更有意义 . 例如,使用GlobalizeIt,翻译人员可以直接访问网站上的页面并开始直接在页面上编辑文本,这就是他们的语言,就是这样:https://www.globalizeit.com/HowItWorks . 不需要编程(尽管它可以以编程方式扩展),它可以轻松地与Angular集成:https://www.globalizeit.com/Translate/Angular,页面的转换一次完成,并且它始终显示带有页面初始渲染的翻译文本 .
完全披露:我是联合创始人:)