5

我见过一些 Angular 的 i18n 插件,但我不想重新发明轮子。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 对象,然后使用 i18n jquery 扩展更新所有 DOM。在这个特殊事件之外,我的指令完美地完成了所有其他任务(使用 i18n 指令并在稍后呈现的模板)。

虽然它工作正常,但我知道我不应该在控制器内操作 DOM,但由于最终什么都没有发生,我还没有找到更好的解决方案。

理想情况下,我希望 Angular 重新编译所有 DOM,解析所有指令以更新标签,但我不知道该怎么做。我试过 $scope.$apply() :不工作,因为此时我已经在摘要中使用了 Scope.onReady 插件,但没有更好的结果。

显然,我对 Angular 很陌生,而且我很难准确地理解事情是如何工作的。

4

1 回答 1

7

据我所知,最好不要使用 jQuery,因为它不是必需的。您可以在没有 jQuery 的情况下使用 i18next,只需使用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;
      };

  }]);
});

请注意,您必须将指令设置为您的应用程序的依赖项。还包括没有 AMD+jQuery 的 i18next 版本。如果您需要更多详细信息,可以在 gist 中找到它们。;)


现在i18next angularGitHub 上有一个可用的模块:https ://github.com/i18next/ng-i18next

于 2013-03-27T11:27:37.057 回答