Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angularjs ng-repeat the dropdown values 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>

The translate="project.SPONSORINFO.MAIN" in the label is rightly showing the value "Select the Sponsor Name" as soon as the language toggle is clicked (no refresh is needed).

Question:

I am using the following function in my view controller to load the language file based on the selected language and pass it into $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 toggling the language, the dropdown menus don't get changed to the selected language unless I refresh or change view and come back. How can I fix this issue so that it works like the label?

annex:

Translation global config in my main.js like the following:

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();

}]);

translation config 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();
like image 927
cplus Avatar asked Oct 23 '16 01:10

cplus


People also ask

What is difference between ng-repeat and Ng options?

ng-repeat creates a new scope for each iteration so will not perform as well as ng-options. For small lists, it will not matter, but larger lists should use ng-options. Apart from that, It provides lot of flexibility in specifying iterator and offers performance benefits over ng-repeat.

What is ng-repeat in AngularJS?

AngularJS ng-repeat Directive The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.

How does i18n work in AngularJS?

AngularJS supports i18n/l10n for date, number and currency filters. Localizable pluralization is supported via the ngPluralize directive. Additionally, you can use MessageFormat extensions to $interpolate for localizable pluralization and gender support in all interpolations via the ngMessageFormat module.

Does AngularJS support Internationlization?

AngularJS supports inbuilt internationalization for three types of filters currency, date and numbers. We only need to incorporate corresponding js according to locale of the country. By default it handles the locale of the browser.


1 Answers

You are iterating array from translation json file. This translation json file is loaded by $translate service and you will not have access on loaded content, but you need the data from this json file to iterate it, thus you have to make your own request to fetch this array. Maybe you do not want but you have to make $http.get call.

In your code one request is made by executing this line var lang = $translate.use(newLang); and second call is done by $http.get BUT in case if $http.get is resolved before call in $translate.use is resolved It will not translate content in dropdown because request in $translate.use is not resolved yet and $translate service does not have these translations to translate.

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

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

[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;
  });
});

For detailed explanation about events section on angular translate module, checkout this link.

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

For this you can just call $translate.use one time on page reload.

[UPDATED]

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

$translate.use(proposedLanguage || preferredLanguage);

This should solve your problem.

like image 66
Zura Sekhniashvili Avatar answered Sep 20 '22 17:09

Zura Sekhniashvili