After researching i18n plugins for Angular, I decided to use the i18next library instead of reinventing the wheel. To implement this, I created a directive named i18n that simply calls the i18n library:
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();
}
});
};
});
});
On my page, users can easily change the language:
<a ng-repeat="l in languages"> <img ng-src="images/{{l.id}}.png" title="{{l.label}}" ng-click="setLanguage(l.id)" /> </a>
In the main controller defined on the html tag:
define(['app', 'i18n', 'jquery'], function(app, i18n, $) {'use strict';
return app.controller('BuilderController', ['$scope', '$location',
function BuilderController($scope, $location) {
/* Listen for url changes */
$scope.$watch(function() {
return $location.path();
}, function() {
$scope.setLanguage(($location.search()).lang || 'en');
});
/* Language options */
$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;
};
}]);
});
The workflow involves a watcher on the language to initialize the i18n object with the new locale and update all DOM elements using the i18n jQuery extension. While this approach works effectively, I am aware that manipulating the DOM inside a controller is not recommended. However, as nothing untoward occurs in the end, I have not yet found a better solution.
Ideally, I would like Angular to re-compile all DOM elements, parsing all directives to update labels. Unfortunately, I haven't been able to figure out how to achieve this. I tried using $scope.$apply(), but it didn't work because it was already in digest at that point. I also experimented with the Scope.onReady plugin without any significant improvement.
Coming from a novice perspective in Angular development, I find it challenging to grasp the intricacies of how everything functions seamlessly.