控制器中角度平移的正确用法

2022-08-30 04:44:31

我在AngularJS应用程序中对i18n使用angular-translate。

对于每个应用程序视图,都有一个专用控制器。在下面的控制器中,我将值设置为显示为页面标题。

法典

断续器

<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';

问题

这是已知问题/限制吗?如何解决这个问题?


答案 1

建议:不要在控制器中翻译,在视图中翻译

我建议让你的控制器不受转换逻辑的影响,并直接在你的视图中翻译你的字符串,如下所示:

<h1>{{ 'TITLE.HELLO_WORLD' | translate }}</h1>

使用所提供的服务

Angular Translate提供了您可以在控制器中使用的服务。$translate

该服务的用法示例可以是:$translate

.controller('TranslateMe', ['$scope', '$translate', function ($scope, $translate) {
    $translate('PAGE.TITLE')
        .then(function (translatedValue) {
            $scope.pageTitle = translatedValue;
        });
});

翻译服务还有一种直接翻译字符串而无需处理承诺的方法,使用:$translate.instant()

.controller('TranslateMe', ['$scope', '$translate', function ($scope, $translate) {
    $scope.pageTitle = $translate.instant('TITLE.DASHBOARD'); // Assuming TITLE.DASHBOARD is defined
});

using 的缺点可能是,如果异步加载语言文件,则尚未加载该文件。$translate.instant()

使用提供的过滤器

这是我首选的方式,因为我不必以这种方式处理承诺。筛选器的输出可以直接设置为作用域变量。

.controller('TranslateMe', ['$scope', '$filter', function ($scope, $filter) {
    var $translate = $filter('translate');

    $scope.pageTitle = $translate('TITLE.DASHBOARD'); // Assuming TITLE.DASHBOARD is defined
});

使用提供的指令

由于@PascalPrecht是这个令人敬畏的库的创建者,我建议遵循他的建议(请参阅下面的答案),并使用提供的指令,该指令似乎可以非常智能地处理翻译。

该指令负责异步执行,并且还足够聪明,可以在转换没有动态值的情况下取消监视作用域上的转换ID。


答案 2

实际上,您应该对此类内容使用翻译指令。

<h1 translate="{{pageTitle}}"></h1>

该指令负责异步执行,并且还足够聪明,可以在转换没有动态值的情况下取消监视作用域上的转换ID。

但是,如果没有办法,并且您确实必须在控制器中使用服务,则应将调用包装在事件中,并结合使用,如下所示:$translate$translateChangeSuccess$rootScope$translate.instant()

.controller('foo', function ($rootScope, $scope, $translate) {
  $rootScope.$on('$translateChangeSuccess', function () {
    $scope.pageTitle = $translate.instant('PAGE.TITLE');
  });
})

那么为什么,为什么不呢?这样做的原因是,在angular-translate中,事件被编辑而不是被编辑,因为我们不需要通过整个范围层次结构进行广播。$rootScope$scope$emit$rootScope$broadcast$scope

为什么而不仅仅是异步?当事件被触发时,它确保所需的翻译数据在那里并且没有发生异步执行(例如异步加载程序执行),因此我们可以只使用同步的,只是假设翻译可用。$translate.instant()$translate()$translateChangeSuccess$translate.instant()

从2.8.0版本开始,还有 ,它返回一个承诺,一旦翻译准备就绪,该承诺就会得到解决。请参阅更新日志$translate.onReady()