Voles Voles - 5 months ago 97
Javascript Question

Correct use for angular-translate in controllers

I'm using angular-translate for i18n in an AngularJS application.

For every application view, there is a dedicated controller. In the controllers below, I set the value to be shown as the page title.

Code



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';
}])


I'm loading the translation files using the angular-translate-loader-url extension.

Problem



On the initial page load, the translation key is shown instead of the translation for that key. The translation is
Hello, World!
, but I'm seeing
HELLO_WORLD
.

The second time I go to the page, all is well and the translated version is shown.

I assume the issue has to do with the fact that maybe the translation file is not yet loaded when the controller is assigning the value to
$scope.pageTitle
.

Remark



When using
<h1>{{ pageTitle | translate }}</h1>
and
$scope.pageTitle = 'HELLO_WORLD';
, the translation works perfect from the first time. The problem with this is that I don't always want to use translations (eg. for the second controller I just want to pass a raw string).

Question



Is this a known issue / limitation? How can this be solved?

Answer

EDIT: Please see the answer from PascalPrecht (the author of angular-translate) for a better solution.


The asynchronous nature of the loading causes the problem. You see, with {{ pageTitle | translate }}, Angular will watch the expression; when the localization data is loaded, the value of the expression changes and the screen is updated.

So, you can do that yourself:

.controller('FirstPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
    $scope.$watch(
        function() { return $filter('translate')('HELLO_WORLD'); },
        function(newval) { $scope.pageTitle = newval; }
    );
});

However, this will run the watched expression on every digest cycle. This is suboptimal and may or may not cause a visible performance degradation. Anyway it is what Angular does, so it cant be that bad...