Nextrp [CPP] RU + Many GEOs Игра на карте России | NEXTRP

AngularJS и i18next

javascript internationalization angularjs angularjs-directive

6738 просмотра

1 ответ

33 Репутация автора

Я видел несколько плагинов i18n для Angular, но я не хочу заново изобретать колесо. i18next - хорошая библиотека, и я собираюсь ее использовать.

Я создал директиву i18n, которая просто вызывает библиотеку i18n:

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

На своей странице я могу изменить язык на лету:

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

Теперь мой основной контроллер определен в теге html:

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

    }]);
});

Как это работает: наблюдатель на языке инициализирует объект i18n с новой локалью, а затем обновляет весь DOM, используя расширение jquery i18n. Вне этого специального события моя директива просто отлично работает для всех других задач (шаблоны используют директиву i18n и отрисовываются позднее).

Хотя он работает нормально, я знаю, что не должен манипулировать DOM внутри контроллера, но так как в итоге ничего не происходит, лучшего решения я не нашел.

В идеале я хочу, чтобы Angular перекомпилировал все DOM, проанализировал все директивы для обновления меток, но я не могу понять, как это сделать. Я пробовал $ scope. $ Apply (): не работает, потому что уже в дайджесте к этому моменту я использовал плагин Scope.onReady без лучших результатов.

Очевидно, я очень плохо знаком с Angular, и мне довольно сложно понять, как именно все работает.

Автор: Arnaud Источник Размещён: 14.03.2013 12:14

Ответы (1)


7 плюса

1070 Репутация автора

Насколько я могу сказать, лучше вообще не использовать jQuery, так как это не требуется. Вы можете использовать i18next без jQuery, просто используя window.i18n.t("YourStringToTranslate"). ;)

Поскольку вы можете написать свою собственную директиву, вам также не нужно ее использовать $(document).i18n();. Для этого я написал простую директиву для Angular.

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

Как видите, вам не нужно использовать jQuery, и вам лучше инициализировать i18next в вашей директиве, а не в контроллере.

Вы можете использовать его, просто добавив ng-i18next=""атрибут к любому элементу. Передайте ваши параметры в $rootScope.i18nextOptionsлюбое место вашего кода (например, в вашем контроллере). Затем он автоматически обновит все переведенные элементы.

Я отредактировал ваш код, так что он работает с моей директивой.

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

  }]);
});

Обратите внимание, что вы должны установить директиву как зависимость вашего приложения. Также включите версию i18next без AMD + jQuery. Если вам нужно больше деталей, они доступны в суть. ;)


Теперь i18next angularна GitHub доступен модуль: https://github.com/i18next/ng-i18next

Автор: AndreM96 Размещён: 27.03.2013 11:27
Вопросы из категории :
32x32