Angularjs ng - repeat outliers from different i18n files

Here is an example json i18n language file for English:

{ "project": { "SPONSORINFO": { "MAIN" : "Select the Sponsor Name", "SPONSORLIST": [ {"spons" :"SponsorName 1" }, {"spons" :"SponsorName 2" } ] } } } 

and here is my html view:

 <div class="form-group" > <label for="form-field-select-1" translate="project.SPONSORINFO.MAIN"> </label> <select class="form-control" ng-model="myModel.sponsors"> <option ng-repeat="s in projectJSON.project.SPONSORINFO.SPONSORLIST" value="{{s.spons}}">{{s.spons | translate}}</option> </select> </div> 

translate="project.SPONSORINFO.MAIN" in the label rightly displays the value "Choose sponsor name" as soon as the language switch is clicked (no update required).

Question:

I use the following function in the view controller to load a language file based on the selected language and pass it to $scope.projectJSON so that I can call it in ng-repeat in my html view:

 var lang = $translate.use(); $http.get('assets/i18n/'+lang+'.json').success(function(data) { $scope.projectJSON= data; }); 


The problem is that after switching the language, the drop-down menus do not change to the selected language unless I update or change the appearance and return. How can I fix this problem so that it works as a shortcut ?

applications:

Translate the global configuration in my main.js as follows:

 app.config(['$translateProvider', function ($translateProvider) { // prefix and suffix information is required to specify a pattern // You can simply use the static-files loader with this pattern: $translateProvider.useStaticFilesLoader({ prefix: 'assets/i18n/', suffix: '.json' }); // Since you've now registered more then one translation table, angular-translate has to know which one to use. // This is where preferredLanguage(langKey) comes in. $translateProvider.preferredLanguage('en'); // Store the language in the local storage $translateProvider.useLocalStorage(); }]); 

in my mainCtrl.js :

 app.controller('AppCtrl', ['$rootScope', '$scope', '$state', '$translate', function ($rootScope, $scope, $state, $translate) { $scope.language = { // Handles language dropdown listIsOpen: false, // list of available languages available: { 'en': 'English', //'it_IT': 'Italiano', 'de_DE': 'Deutsch' }, // display always the current ui language init: function () { var proposedLanguage = $translate.proposedLanguage() || $translate.use(); var preferredLanguage = $translate.preferredLanguage(); // we know we have set a preferred one in app.config $scope.language.selected = $scope.language.available[(proposedLanguage || preferredLanguage)]; }, set: function (localeId, ev) { $translate.use(localeId); $scope.language.selected = $scope.language.available[localeId]; $scope.language.listIsOpen = !$scope.language.listIsOpen; } }; $scope.language.init(); 
+6
source share
5 answers

You iterate an array from the json translation file. This json translation file is uploaded by the $translate service and you will not have access to the downloaded content, but you need data from this json file to iterate it, so you have to make your own request to retrieve this array. You may not want to, but you should make a call to $http.get .

In your code, a single request is executed using this line var lang = $translate.use(newLang); , and the second call is made using $http.get BUT if $http.get allowed before the call to $translate.use resolved. It will not translate the content in the drop-down menu because the request in $translate.use is not yet allowed, and the $translate service does not have these translations for translation.

What you can do is listen to the $translateChangeSuccess event (emitted by the $translate service) on $rootScope , and then make your aimax call in this handler.

I tested the following code in your example and it works great.

[UPDATED]

 $rootScope.$on('$translateChangeSuccess', function () { // Get new current new language var lang = $translate.use(); $http.get('assets/i18n/'+lang+'.json').success(function(data) { $scope.projectJSON = data; }); }); 

A detailed explanation of the events section on the angular translate module, checkout this link .

Whenever you call $translate.use(localeId) , it will internally make an ajax call, and when that call is resolved, it will throw a $translateChangeSuccess event, then you make your request, load the data and update $scope.projectJSON .
The only thing you need to trigger this event is the first time you update your browser when $translate.use not called.

To do this, you can simply call $translate.use once when you reload the page.

[UPDATED]

Put the following code at the end of your $scope.language.init function.

 $translate.use(proposedLanguage || preferredLanguage); 

This should solve your problem.

+2
source

Try using the promise template:

 $http.get(..).then(function(response){..}) 

So the problem is not ng-repeat , so I would change the name of the question. Back to the topic:

 $http.get('assets/i18n/'+lang+'.json').then(function(response) { //check what exactly are you getting in the response //console.log(response) $scope.projectJSON = response; }); 

And I would see what response , probably you need to do

 $scope.projectJSON = response.data; 
+1
source

Old

Since you are using the angular asynchronous function, you will not immediately recognize this change. After downloading the files, add

 $scope.$apply(); 

To make angular rescan all and make changes. Here you can find out more about this.

It means for you ($$ phase check by @lascort)

 $http.get('assets/i18n/'+lang+'.json').success(function(data) { $scope.projectJSON= data; $translate.use(lang); if (!$scope.$$phase) $scope.$apply(); $translate.refresh(); }); 

Edit

But official resources recommend using their downloaders and not downloading manually: Here

You are using staticFilesLoader, so install the following extension:

bower install angular-translate-loader-static-files

Then in your function change the language:

$translateProvider.preferredLanguage(lang);

This should work (says the documentation). Maybe you need to do $scope.$apply(); but I think this is already included.

0
source

Did you try to reset the state?

$state.reload();

 app.controller('AppCtrl', ['$rootScope', '$scope', '$state', '$translate', function ($rootScope, $scope, $state, $translate) { $scope.language = { // Handles language dropdown listIsOpen: false, // list of available languages available: { 'en': 'English', //'it_IT': 'Italiano', 'de_DE': 'Deutsch' }, // display always the current ui language init: function () { var proposedLanguage = $translate.proposedLanguage() || $translate.use(); var preferredLanguage = $translate.preferredLanguage(); // we know we have set a preferred one in app.config $scope.language.selected = $scope.language.available[(proposedLanguage || preferredLanguage)]; }, set: function (localeId, ev) { $translate.use(localeId); $scope.language.selected = $scope.language.available[localeId]; $scope.language.listIsOpen = !$scope.language.listIsOpen; }, uiReload: function(){ $state.reload(); } }; $scope.language.init(); $scope.language.uiReload(); //call this for ui-router 
0
source

Go step by step:
1) Translated = "project.SPONSORINFO.MAIN" on the label rightly shows the value "Choose sponsor name" without the need for updating 2) the drop-down menus will not be changed to the selected language unless you update or change the presentation and return.

So switching for translation actually works.

But why does this not work for dropdown menus? You may notice that the label for project.SPONSORINFO.MAIN is static text, and s.spons is dynamic, based on the return value.

The select parameter is compiled for the first time when you enter the page and does not recompile after switching your languages. Thus, when switching the translation, you extract the text, but the selection element is not recompiled and, therefore, is not translated "on the fly" until the next re-entry / reload of the view.

You have several ways to solve the problem:
1) programmatically update the state / route as soon as the transfer is complete. (quick fix but bad way)
2) Write an angular directive that recompiles the element after detecting language changes. (best approach)

The idea of ​​how to reach the second solution:

 var lang = $translate.use(); $http.get('assets/i18n/'+lang+'.json').success(function(data) { $scope.projectJSON= data; $scope.newLanguage = $translate.use(); }); .directive('recompileLanguage', function($compile) { return { restrict: 'E', scope: { lang: '=' }, link: function(scope, element, attr) { $compile(element.contents())(scope); scope.$watch('lang', funcion (newValue, oldvalue) { $compile(element.contents())(scope); }); } } }); <select recompile-language lang={{newLanguage}}> </select> 
0
source

Source: https://habr.com/ru/post/1011612/


All Articles