Ich verwende Angular -Translate für i18n in einer AngularJS-Anwendung.
Für jede Anwendungsansicht gibt es einen dedizierten Controller. In den folgenden Controllern habe ich den Wert festgelegt, der als Seitentitel angezeigt werden soll.
Code
HTML
<h1>{{ pageTitle }}</h1>
JavaScript
.controller('FirstPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.pageTitle = $filter('translate')('HELLO_WORLD');
}])
.controller('SecondPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.pageTitle = 'Second page title';
}])
Ich lade die Übersetzungsdateien mit der Erweiterung angle-translate-loader-url .
Problem
Beim ersten Laden der Seite wird der Übersetzungsschlüssel anstelle der Übersetzung für diesen Schlüssel angezeigt. Die Übersetzung ist Hello, World!
, aber ich sehe HELLO_WORLD
.
Wenn ich zum zweiten Mal auf die Seite gehe, ist alles in Ordnung und die übersetzte Version wird angezeigt.
Ich gehe davon aus, dass das Problem damit zusammenhängt, dass die Übersetzungsdatei möglicherweise noch nicht geladen ist, wenn der Controller den Wert zuweist $scope.pageTitle
.
Anmerkung
Bei Verwendung von <h1>{{ pageTitle | translate }}</h1>
und $scope.pageTitle = 'HELLO_WORLD';
funktioniert die Übersetzung vom ersten Mal an perfekt. Das Problem dabei ist, dass ich nicht immer Übersetzungen verwenden möchte (z. B. für den zweiten Controller möchte ich nur eine rohe Zeichenfolge übergeben).
Frage
Ist dies ein bekanntes Problem / eine Einschränkung? Wie kann das gelöst werden?
quelle
$scope.$watch
ist ziemlich übertrieben, da Angular Translate einen Service anbietet, der in den Controllern verwendet werden kann. Siehe meine Antwort unten.$translate.instant()
das Gleiche wie ein Service bietet. Beachten Sie außerdem die Antwort von Pascal.Empfohlen: Nicht im Controller übersetzen, sondern in Ihrer Ansicht übersetzen
Ich würde empfehlen, Ihren Controller frei von Übersetzungslogik zu halten und Ihre Zeichenfolgen wie folgt direkt in Ihre Ansicht zu übersetzen:
Nutzung des bereitgestellten Dienstes
Angular Translate bietet den
$translate
Dienst, den Sie in Ihren Controllern verwenden können.Eine beispielhafte Verwendung des
$translate
Dienstes kann sein:Der Übersetzungsdienst verfügt auch über eine Methode zum direkten Übersetzen von Zeichenfolgen, ohne dass ein Versprechen eingegangen werden muss
$translate.instant()
.Der Nachteil bei der Verwendung
$translate.instant()
kann sein, dass die Sprachdatei noch nicht geladen ist, wenn Sie sie asynchron laden.Verwendung des mitgelieferten Filters
Dies ist mein bevorzugter Weg, da ich Versprechen nicht auf diese Weise behandeln muss. Die Ausgabe des Filters kann direkt auf eine Bereichsvariable gesetzt werden.
Verwendung der bereitgestellten Richtlinie
Da @PascalPrecht der Schöpfer dieser großartigen Bibliothek ist, würde ich empfehlen, seinen Rat zu befolgen (siehe seine Antwort unten) und die bereitgestellte Direktive zu verwenden, die Übersetzungen sehr intelligent zu handhaben scheint.
quelle
Eigentlich sollten Sie stattdessen die Übersetzungsanweisung für solche Dinge verwenden.
Die Direktive kümmert sich um die asynchrone Ausführung und ist auch clever genug, um Übersetzungs-IDs im Bereich zu entfernen, wenn die Übersetzung keine dynamischen Werte enthält.
Wenn es jedoch um keine Möglichkeit gibt , und Sie wirklich haben , um den Einsatz
$translate
Service in der Steuerung, sollten Sie den Anruf in einem Wrap -$translateChangeSuccess
Ereignis mit$rootScope
in Kombination mit$translate.instant()
wie folgt aus :Warum also
$rootScope
nicht$scope
? Der Grund dafür ist, dass in Winkel übersetzen die Ereignisse werden$emit
auf ed$rootScope
statt$broadcast
ed auf ,$scope
weil wir auf Sendung durch den gesamten Umfang Hierarchie nicht brauchen.Warum
$translate.instant()
und nicht nur asynchron$translate()
? Wenn ein$translateChangeSuccess
Ereignis ausgelöst wird, ist sicher, dass die erforderlichen Übersetzungsdaten vorhanden sind und keine asynchrone Ausführung stattfindet (z. B. asynchrone Loader-Ausführung). Daher können wir nur das verwenden,$translate.instant()
das synchron ist und nur davon ausgeht, dass Übersetzungen verfügbar sind.Seit Version 2.8.0 gibt es auch
$translate.onReady()
ein Versprechen, das aufgelöst wird, sobald die Übersetzungen fertig sind. Siehe das Änderungsprotokoll .quelle
{{::'HELLO_WORLD | translate}}'
.Um eine Übersetzung im Controller zu erstellen, können Sie den folgenden
$translate
Dienst verwenden:Diese Anweisung führt nur die Übersetzung bei der Controller-Aktivierung durch, erkennt jedoch nicht die Laufzeitänderung in der Sprache. Um dieses Verhalten zu erreichen, können Sie das
$rootScope
Ereignis anhören$translateChangeSuccess
und dort dieselbe Übersetzung durchführen:Natürlich können Sie den
$translate
Dienst in eine Methode einkapseln und im Controller und im$translateChangeSucess
Listener aufrufen .quelle
Was passiert ist, dass Angular-translate den Ausdruck mit einem ereignisbasierten System überwacht, und genau wie in jedem anderen Fall der Bindung oder bidirektionalen Bindung wird ein Ereignis ausgelöst, wenn die Daten abgerufen werden, und der Wert wird geändert funktioniert offensichtlich nicht für die Übersetzung. Übersetzungsdaten müssen im Gegensatz zu anderen dynamischen Daten auf der Seite natürlich sofort dem Benutzer angezeigt werden. Es kann nicht eingeblendet werden, nachdem die Seite geladen wurde.
Selbst wenn Sie dieses Problem erfolgreich beheben können, besteht das größere Problem darin, dass der Entwicklungsaufwand enorm ist. Ein Entwickler muss jede Zeichenfolge auf der Site manuell extrahieren, in eine JSON-Datei einfügen und manuell anhand des Zeichenfolgencodes (in diesem Fall 'pageTitle') darauf verweisen. Die meisten kommerziellen Websites haben Tausende von Zeichenfolgen, für die dies geschehen muss. Und das ist erst der Anfang. Sie benötigen jetzt ein System, um die Übersetzungen synchron zu halten, wenn sich der zugrunde liegende Text in einigen von ihnen ändert, ein System, um die Übersetzungsdateien an die verschiedenen Übersetzer zu senden, sie wieder in den Build zu integrieren und die Site erneut bereitzustellen, damit die Übersetzer sie sehen können ihre Änderungen im Kontext und so weiter und so fort.
Da es sich um ein "bindendes", ereignisbasiertes System handelt, wird für jede einzelne Zeichenfolge auf der Seite ein Ereignis ausgelöst. Dies ist nicht nur eine langsamere Methode zum Transformieren der Seite, sondern kann auch alle Aktionen auf der Seite verlangsamen. wenn Sie anfangen, eine große Anzahl von Ereignissen hinzuzufügen.
Die Verwendung einer Übersetzungsplattform für die Nachbearbeitung ist für mich jedenfalls sinnvoller. Mit GlobalizeIt kann ein Übersetzer beispielsweise einfach zu einer Seite auf der Website gehen und den Text direkt auf der Seite für seine Sprache bearbeiten. Das war's: https://www.globalizeit.com/HowItWorks . Es ist keine Programmierung erforderlich (obwohl es programmgesteuert erweiterbar sein kann), es lässt sich problemlos in Angular integrieren: https://www.globalizeit.com/Translate/Angular . Die Transformation der Seite erfolgt auf einmal und zeigt immer den übersetzten Text mit an das anfängliche Rendern der Seite.
Vollständige Offenlegung: Ich bin Mitbegründer :)
quelle