最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS and i18next - Stack Overflow

programmeradmin1浏览0评论

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-pile 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.

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-pile 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.

Share Improve this question edited Jun 27, 2019 at 15:35 Akshay Rana 1,48512 silver badges21 bronze badges asked Mar 14, 2013 at 12:14 ArnaudArnaud 732 silver badges6 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 7

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./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./i18next/ng-i18next

发布评论

评论列表(0)

  1. 暂无评论