Actually, you should use the translate directive for such stuff instead.
<h1 translate="{{pageTitle}}"></h1>
The directive takes care of asynchronous execution and is also clever enough to unwatch translation ids on the scope if the translation has no dynamic values.
However, if there's no way around and you really have to use $translate
service in the controller, you should wrap the call in a $translateChangeSuccess
event using $rootScope
in combination with $translate.instant()
like this:
.controller('foo', function ($rootScope, $scope, $translate) {
$rootScope.$on('$translateChangeSuccess', function () {
$scope.pageTitle = $translate.instant('PAGE.TITLE');
});
})
So why $rootScope
and not $scope
? The reason for that is, that in angular-translate's events are $emit
ed on $rootScope
rather than $broadcast
ed on $scope
because we don't need to broadcast through the entire scope hierarchy.
Why $translate.instant()
and not just async $translate()
? When $translateChangeSuccess
event is fired, it is sure that the needed translation data is there and no asynchronous execution is happening (for example asynchronous loader execution), therefore we can just use $translate.instant()
which is synchronous and just assumes that translations are available.
Since version 2.8.0 there is also $translate.onReady()
, which returns a promise that is resolved as soon as translations are ready. See the changelog.