Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS and i18next

I have seen some i18n plugins for Angular but I don't want to re-invent the wheel. i18next is a good library and so, I intend to use it.

I have created a directive i18n which just calls 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, I can change language on the fly:

<a ng-repeat="l in languages"> <img ng-src="images/{{l.id}}.png" title="{{l.label}}" ng-click="setLanguage(l.id)" /> </a>

Now, my main controller defined on html tag:

define(['app', 'i18n', 'jquery'], function(app, i18n, $) {'use strict';

    return app.controller('BuilderController', ['$scope', '$location',
    function BuilderController($scope, $location) {

        /* Catch url changes */
        $scope.$watch(function() {
            return $location.path();
        }, function() {
            $scope.setLanguage(($location.search()).lang || 'en');
        });

        /* Language */
        $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;
        };

    }]);
});

How it works: watcher on language initialize i18n object with new locale and then update all DOM using i18n jquery extension. Outside of this special event, my directive just does the work perfectly for all other tasks (templates using i18n directive and rendered at a later moment).

While it is working fine, I know I shouldn't manipulate DOM inside a controller but since nothing happens in the end, I haven't found a better solution.

Ideally, I want Angular to re-compile all DOM, parsing all directives to update labels but I can't figure how to do it. I have tried $scope.$apply() : not working because already in digest at this point I have used Scope.onReady plugin without better results.

Obviously, I'm very new to Angular and it's quite difficult for me to understand exactly how things work.

like image 627
Arnaud Avatar asked Mar 14 '13 12:03

Arnaud


People also ask

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.

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.

Is AngularJS a programming language?

AngularJS is an open-source front-end web application framework to develop single page applications. It is solely based on the all-rounder programming language- JavaScript. That is the reason it has the name that includes JS and it is also written as Angular.

What is translate in AngularJS?

angular-translate is an AngularJS module that provides filters and directives, along with the ability to load i18n data asynchronously. It supports pluralization through MessageFormat , and is designed to be highly extensible and configurable.


1 Answers

As far as I can say, it is better not to use jQuery at all, since it isn't required. You can use i18next without jQuery, by simply using window.i18n.t("YourStringToTranslate"). ;)

Because you can write your own directive you also do not need to use $(document).i18n();. For that purpose I have written a simple directive for Angular.

https://gist.github.com/bugwelle/5239617

As you can see, you don't have to use jQuery and you also better initialize i18next in your directive instead of your controller.

You can use it by simlpy adding a ng-i18next="" attribute to any element you want. Pass your options to $rootScope.i18nextOptions anywhere in your code (for example in your controller). It then will automatically update all translated elements.

I edited your code, so it works with my directive.

define(['app', 'i18n', 'jquery'], function(app, i18n, $) {

  'use strict';

  return app.controller('BuilderController', ['$rootScope', '$scope', '$location',
    function BuilderController($rootScope, $scope, $location) {

      /* Catch url changes */
      $scope.$watch(function() {
          return $location.path();
      }, function() {
          $scope.setLanguage(($location.search()).lang || 'en');
      });

      /* Language */
      $scope.languages = [{
          id : "en",
          label : "English"
      }, {
          id : "fr",
          label : "Français"
      }];

      // This has changed
      $scope.$watch('language', function() {
        $location.search('lang', $scope.language);
        $rootScope.i18nextOptions = {
            resGetPath : 'i18n/__lng__/__ns__.json',
            lng : $scope.language,
            getAsync : false,
            sendMissing : true,
            fallbackLng : 'en',
            debug : true
        };
      });

      $scope.setLanguage = function(id) {
          $scope.language = id;
      };

  }]);
});

Please note that you have to set the directive as a dependence of your app. Also include the i18next version without AMD+jQuery. If you need more details, they are available in the gist. ;)


There is now an i18next angular module available on GitHub: https://github.com/i18next/ng-i18next

like image 97
AndreM96 Avatar answered Oct 28 '22 22:10

AndreM96