5

Ich habe einige i18n Plugins für Angular gesehen, aber ich möchte das Rad nicht neu erfinden. i18next ist eine gute Bibliothek und ich beabsichtige sie zu benutzen.Angular und i18next

Ich habe eine Richtlinie i18n geschaffen, die nur i18n Bibliothek ruft:

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

Auf meiner Seite, ich Sprache on the fly ändern können:

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

Nun, mein Haupt-Controller auf html definiert 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; 
     }; 

    }]); 
}); 

Wie es funktioniert: watcher auf sprache initialisiert i18n objekt mit neuem locale an d dann aktualisieren Sie alle DOM mit i18n jquery Erweiterung. Außerhalb dieses speziellen Ereignisses funktioniert meine Direktive einfach perfekt für alle anderen Aufgaben (Vorlagen, die die i18n-Anweisung verwenden und zu einem späteren Zeitpunkt gerendert werden).

Während es funktioniert, weiß ich, dass ich DOM in einem Controller nicht manipulieren sollte, aber da am Ende nichts passiert, habe ich keine bessere Lösung gefunden.

Idealerweise möchte ich, dass Angular alle DOM neu kompiliert, alle Anweisungen analysiert, um die Etiketten zu aktualisieren, aber ich kann mir nicht vorstellen, wie es geht. Ich habe $ scope versucht. $ Apply(): funktioniert nicht, weil bereits im Digest zu diesem Zeitpunkt Ich habe Scope.onReady Plugin ohne bessere Ergebnisse verwendet.

Offensichtlich bin ich Angular sehr neu und es ist ziemlich schwierig für mich, genau zu verstehen, wie die Dinge funktionieren.

Antwort

7

Soweit ich sagen kann, ist es besser, jQuery überhaupt nicht zu verwenden, da es nicht erforderlich ist. Sie können i18next ohne jQuery verwenden, indem Sie einfach window.i18n.t("YourStringToTranslate") verwenden. ;)

Da Sie Ihre eigene Anweisung schreiben können, müssen Sie auch $(document).i18n(); nicht verwenden. Zu diesem Zweck habe ich eine einfache Direktive für Angular geschrieben.

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

Wie Sie sehen können, müssen Sie nicht jQuery und Sie verwenden auch besser initialisieren i18next in Ihrer Richtlinie anstelle des Controllers.

Sie können es verwenden, indem Sie einfach ein ng-i18next="" Attribut zu einem beliebigen Element hinzufügen. Übergeben Sie Ihre Optionen an eine beliebige Stelle in Ihrem Code (z. B. in Ihrem Controller) an $rootScope.i18nextOptions. Es aktualisiert dann automatisch alle übersetzten Elemente.

Ich habe Ihren Code bearbeitet, so dass es mit meiner Anweisung funktioniert.

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

    }]); 
}); 

Bitte beachten Sie, dass Sie die Richtlinie als eine Abhängigkeit Ihrer App festlegen müssen. Schließen Sie auch die i18next-Version ohne AMD + jQuery ein. Wenn Sie mehr Details benötigen, sind sie im Wesentlichen verfügbar.;)


Es gibt jetzt eine i18nextangular Modul auf GitHub: https://github.com/i18next/ng-i18next