In meinem vorherigen Artikel habe ich Stimulus behandelt - ein bescheidenes JavaScript-Framework, das von Basecamp erstellt wurde. Heute spreche ich über die Internationalisierung einer Stimulus-Anwendung, da das Framework keine I18n-Werkzeuge aus der Box enthält. Die Internationalisierung ist ein wichtiger Schritt, vor allem wenn Ihre App von Menschen auf der ganzen Welt verwendet wird. Daher ist ein grundlegendes Verständnis der Vorgehensweise möglicherweise von Nutzen.
Natürlich müssen Sie entscheiden, welche Internationalisierungslösung implementiert werden soll, sei es jQuery.I18n, Polyglot oder eine andere. In diesem Tutorial möchte ich Ihnen ein beliebtes I18n-Framework namens I18next zeigen, das viele coole Funktionen bietet und viele zusätzliche Plugins von Drittanbietern enthält, um den Entwicklungsprozess noch weiter zu vereinfachen. Trotz all dieser Funktionen ist I18next kein komplexes Werkzeug, und Sie müssen nicht viel Dokumentation studieren, um zu beginnen.
In diesem Artikel erfahren Sie, wie Sie die Unterstützung von I18n in Stimulus-Anwendungen mithilfe der I18next-Bibliothek aktivieren. Konkret sprechen wir über:
Der Quellcode ist im GitHub-Repo des Tutorials verfügbar.
Um zu beginnen, klonen wir das Stimulus Starter-Projekt und installieren alle Abhängigkeiten mit dem Yarn-Paketmanager:
Git Klon https://github.com/stimulusjs/stimulus-starter.git cd Stimulus-Starter-Garn installieren
Wir werden eine einfache Webanwendung erstellen, die Informationen über die registrierten Benutzer lädt. Für jeden Benutzer zeigen wir sein Login und die Anzahl der Fotos an, die er bisher hochgeladen hat (es ist nicht wichtig, was diese Fotos sind)..
Außerdem werden wir oben auf der Seite einen Sprachumschalter präsentieren. Wenn eine Sprache ausgewählt wird, sollte die Benutzeroberfläche sofort übersetzt werden, ohne dass Seiten neu geladen werden müssen. Außerdem sollte die URL mit einem ?Gebietsschema
GET-Parameter, der angibt, welches Gebietsschema derzeit verwendet wird. Wenn die Seite bereits mit diesem Parameter geladen wurde, sollte die richtige Sprache automatisch eingestellt werden.
Okay, lass uns unsere Benutzer rendern. Fügen Sie dem folgenden Code hinzu public / index.html Datei:
Hier benutzen wir die Benutzer
Controller und Bereitstellung einer URL, von der aus unsere Benutzer geladen werden können. In einer realen Anwendung hätten wir wahrscheinlich ein serverseitiges Skript, das Benutzer aus der Datenbank abruft und mit JSON antwortet. Lassen Sie uns für dieses Tutorial jedoch einfach alle erforderlichen Daten in die public / api / users / index.json Datei:
["login": "johndoe", "photos_count": "15", "gender": "male", "login": "annsmith", "photos_count": "20", "gender": "female "]
Erstellen Sie jetzt ein neues src / controller / users_controller.js Datei:
Import Controller aus "stimulus" Export-Standardklasse erweitert Controller connect () this.loadUsers ()
Sobald der Controller mit dem DOM verbunden ist, laden wir unsere Benutzer asynchron mit Hilfe von loadUsers ()
Methode:
loadUsers () fetch (this.data.get ("url")) .then (response => response.text ()) .then (json => this.renderUsers (json))
Diese Methode sendet eine Abrufanforderung an die angegebene URL, erfasst die Antwort und rendert schließlich die Benutzer:
renderUsers (Benutzer) let content = "JSON.parse (Benutzer) .forEach ((Benutzer) => content + = 'Login: $ user.login
Hat $ user.photos_count Foto (s) hochgeladen
') this.element.innerHTML = Inhalt
Renderbenutzer ()
, wiederum analysiert JSON, erstellt einen neuen String mit dem gesamten Inhalt und zeigt diesen Inhalt schließlich auf der Seite an (this.element
wird den tatsächlichen DOM-Knoten zurückgeben, mit dem der Controller verbunden ist div
in unserem Fall).
Jetzt werden wir I18next in unsere App integrieren. Fügen Sie unserem Projekt zwei Bibliotheken hinzu: I18next selbst und ein Plugin, um das asynchrone Laden von Übersetzungsdateien vom Backend aus zu ermöglichen:
garne hinzufügen i18next i18next-xhr-backend
Wir werden alles, was mit I18next zu tun hat, separat speichern src / i18n / config.js Datei, so erstellen Sie es jetzt:
i18next aus 'i18next' importieren I18nXHR aus 'i18next-xhr-backend' importieren const i18n = i18next.use (I18nXHR). 'en', 'ru'], ns: 'users', defaultNS: 'users', fallbackNS: false, debug: true, Backend: loadPath: '/ i18n / lng / ns. json ',, function (err, t) if (err) return console.error (err)); i18n als i18n exportieren
Gehen wir von oben nach unten durch, um zu verstehen, was hier vor sich geht:
verwenden (I18nXHR)
Aktiviert das Plugin i18next-xhr-backend.fallbackLng
sagt ihm, Englisch als Ausweichsprache zu verwenden.Whitelist
Es können nur Englisch und Russisch eingestellt werden. Natürlich können Sie auch andere Sprachen wählen.Vorspannung
weist Übersetzungsdateien an, von dem Server vorgeladen zu werden, anstatt sie zu laden, wenn die entsprechende Sprache ausgewählt ist.ns
bedeutet "Namespace" und akzeptiert entweder eine Zeichenfolge oder ein Array. In diesem Beispiel haben wir nur einen Namespace, aber für größere Anwendungen können Sie andere Namespaces wie Administrator
, Wagen
, Profil
, usw. Für jeden Namespace sollte eine separate Übersetzungsdatei erstellt werden.defaultNS
setzt Benutzer
um den Standard-Namespace zu sein.FallbackNS
Deaktiviert den Namespace-Fallback.debuggen
ermöglicht die Anzeige von Debugging-Informationen in der Browserkonsole. Insbesondere wird angegeben, welche Übersetzungsdateien geladen werden, welche Sprache ausgewählt ist usw. Sie werden diese Einstellung wahrscheinlich deaktivieren, bevor Sie die Anwendung für die Produktion bereitstellen.Backend
enthält die Konfiguration für das I18nXHR-Plugin und gibt an, woher die Übersetzungen geladen werden. Beachten Sie, dass der Pfad den Titel des Gebietsschemas enthalten sollte, während die Datei nach dem Namespace benannt werden muss und das .Json ErweiterungFunktion (Err, T)
ist der Callback, der ausgeführt werden soll, wenn I18next bereit ist (oder wenn ein Fehler ausgelöst wurde).Lassen Sie uns als Nächstes Übersetzungsdateien erstellen. Übersetzungen für die russische Sprache sollten in die public / i18n / ru / users.json Datei:
"login": "Логин"
Anmeldung
Hier ist der Übersetzungsschlüssel, während Логин
ist der anzuzeigende Wert.
Englische Übersetzungen wiederum sollten in die public / i18n / de / users.json Datei:
"Einloggen Einloggen"
Um sicherzustellen, dass I18next funktioniert, können Sie dem Callback in der folgenden Zeile Code hinzufügen i18n / config.js Datei:
// config geht hier hin… function (err, t) if (err) return console.error (err) console.log (i18n.t ('login'))
Hier verwenden wir eine Methode namens t
das heißt "übersetzen". Diese Methode akzeptiert einen Übersetzungsschlüssel und gibt den entsprechenden Wert zurück.
Es kann jedoch viele Teile der Benutzeroberfläche geben, die übersetzt werden müssen, und zwar durch Verwendung der t
Methode wäre ziemlich langweilig. Stattdessen schlage ich vor, dass Sie ein anderes Plugin namens loc-i18next verwenden, mit dem Sie mehrere Elemente gleichzeitig übersetzen können.
Installieren Sie das loc-i18next-Plugin:
Garn hinzufügen loc-i18next
Importiere es oben in der src / i18n / config.js Datei:
locI18next von 'loc-i18next' importieren
Geben Sie nun die Konfiguration für das Plugin selbst an:
// other config const loci18n = locI18next.init (i18n, selectorAttr: 'data-i18n', optionsAttr: 'data-i18n-options', useOptionsAttr: true); loci18n als loci18n exportieren, i18n als i18n
Hier sind einige Dinge zu beachten:
locI18next.init (i18n)
erstellt eine neue Instanz des Plugins basierend auf der zuvor definierten Instanz von I18next.SelectorAttr
Gibt an, welches Attribut zum Erkennen von Elementen verwendet werden soll, für die eine Lokalisierung erforderlich ist. Grundsätzlich sucht loc-i18next nach solchen Elementen und verwendet den Wert von data-i18n
Attribut als Übersetzungsschlüssel.OptionenAttr
gibt an, welches Attribut zusätzliche Übersetzungsoptionen enthält.useOptionsAttr
weist das Plugin an, die zusätzlichen Optionen zu verwenden.Unsere Benutzer werden asynchron geladen. Daher müssen wir warten, bis diese Operation abgeschlossen ist, und erst dann eine Lokalisierung durchführen. Lassen Sie uns jetzt einfach einen Timer einstellen, der zwei Sekunden warten soll, bevor Sie die lokalisieren()
Methode - das ist natürlich ein temporärer Hack.
loci18n aus '… / i18n / config' importieren // anderer Code… loadUsers () fetch (this.data.get ("url")) .then (response => response.text ()) .then (json => this.renderUsers (json) setTimeout (()) => // <--- this.localize() , '2000') )
Code der lokalisieren()
Methode selbst:
localize () loci18n ('. Benutzer')
Wie Sie sehen, müssen wir nur einen Selektor an das loc-i18next-Plugin übergeben. Alle Elemente im Inneren (die die data-i18n
Attributsatz) wird automatisch lokalisiert.
Jetzt optimieren Sie die Renderbenutzer
Methode. Im Moment übersetzen wir nur das "Login" -Wort:
renderUsers (Benutzer) let content = "JSON.parse (Benutzer) .forEach ((Benutzer) => content + = 'ID: $ user.id
: $ user.login
Hat $ user.photos_count Foto (s) hochgeladen
') this.element.innerHTML = Inhalt
Nett! Laden Sie die Seite neu, warten Sie zwei Sekunden und stellen Sie sicher, dass das Wort "Login" für jeden Benutzer angezeigt wird.
Wir haben einen Teil der Schnittstelle lokalisiert, was wirklich cool ist. Jeder Benutzer hat jedoch zwei weitere Felder: die Anzahl der hochgeladenen Fotos und das Geschlecht. Da wir nicht vorhersagen können, wie viele Fotos jeder Benutzer haben wird, sollte das Wort "Foto" auf der Grundlage der angegebenen Anzahl ordnungsgemäß pluriert werden. Dazu benötigen wir eine Daten-I18N-Optionen
zuvor konfiguriertes Attribut Um die Zählung anzugeben, Daten-I18N-Optionen
sollte mit dem folgenden Objekt zugewiesen werden: "count": YOUR_COUNT
.
Die geschlechtsspezifische Information sollte ebenfalls berücksichtigt werden. Das Wort "hochgeladen" in Englisch kann sowohl für Männer als auch für Frauen verwendet werden, aber in Russisch wird es entweder "загрузил" oder "загрузила", also brauchen wir Daten-I18N-Optionen
wieder was hat "context": "GENDER"
als Wert. Beachten Sie übrigens, dass Sie diesen Kontext verwenden können, um andere Aufgaben zu erledigen, nicht nur, um Genderinformationen bereitzustellen.
renderUsers (Benutzer) let content = "JSON.parse (Benutzer) .forEach ((Benutzer) => content + = ': $ user.login
') this.element.innerHTML = Inhalt
Aktualisieren Sie nun die englischen Übersetzungen:
"login": "Login", "uploaded": "Hat hochgeladen", "photos": "ein Foto", "photos_plural": "count photos"
Nichts hier komplex. Da uns für Englisch die Gender-Informationen (also der Kontext) nicht wichtig sind, sollte der Übersetzungsschlüssel einfach sein hochgeladen
. Um korrekt pluralisierte Übersetzungen bereitzustellen, verwenden wir die Fotos
und photos_plural
Schlüssel. Das Anzahl
Teil ist Interpolation und wird durch die tatsächliche Zahl ersetzt.
In Bezug auf die russische Sprache sind die Dinge komplexer:
"login": "Логин", "uploaded_male": "Загрузил уже", "uploaded_female": "Загрузила уже", "photos_0": "одну фотографию", "photos_1" ""; photos_2 ":" count фотографий "
Beachten Sie zunächst, dass wir beides haben uploaded_male
und uploaded_female
Schlüssel für zwei mögliche Kontexte. Pluralisierungsregeln sind im Russischen auch komplexer als im Englischen, daher müssen nicht zwei, sondern drei mögliche Ausdrücke angegeben werden. I18next unterstützt viele Standardsprachen, und dieses kleine Tool kann Ihnen helfen zu verstehen, welche Pluralisierungsschlüssel für eine bestimmte Sprache angegeben werden sollten.
Wir sind mit der Übersetzung unserer Anwendung fertig, aber die Benutzer sollten zwischen den Ländereinstellungen wechseln können. Fügen Sie daher eine neue "Sprachumschalter" -Komponente hinzu public / index.html Datei:
Fertige den entsprechenden Controller in der src / controller / languages_controller.js Datei:
Controller aus "stimulus" importieren i18n, loci18n aus '… / i18n / config' importieren Standardklasse erweitert Controller initialize () let languages = [title: 'English', Code: 'en', title: 'Русский', code: 'ru'] this.element.innerHTML = languages.map ((lang) => return '
Hier benutzen wir die initialisieren()
Rückruf, um eine Liste der unterstützten Sprachen anzuzeigen. Jeder li
hat ein Datenaktion
Attribut, das die Methode angibt (switchSprache
, sollte in diesem Fall ausgelöst werden, wenn das Element angeklickt wird.
Nun füge das hinzu switchLanguage ()
Methode:
switchLanguage (e) this.currentLang = e.target.getAttribute ("data-lang")
Es nimmt einfach das Ziel des Ereignisses und erfasst den Wert der data-lang
Attribut.
Ich möchte auch einen Getter und Setter für die hinzufügen currentLang
Attribut:
get currentLang () return this.data.get ("currentLang") set currentLang (lang) if (i18n.language! == lang) i18n.changeLanguage (lang) if (this.currentLang! == lang ) this.data.set ("currentLang", lang) loci18n ('body') this.highlightCurrentLang ()
Der Getter ist sehr einfach - wir holen den Wert der aktuell verwendeten Sprache ab und geben ihn zurück.
Der Setter ist komplexer. Als erstes benutzen wir die Sprache ändern
Methode, wenn die aktuell eingestellte Sprache nicht der ausgewählten entspricht. Außerdem speichern wir das neu ausgewählte Gebietsschema unter data-current-lang
Attribut (auf das im Getter zugegriffen wird), Lokalisierung des Hauptteils der HTML-Seite mithilfe des loc-i18next-Plugins und Hervorhebung des aktuell verwendeten Gebietsschemas.
Lass uns die codieren highlightCurrentLang ()
:
highlightCurrentLang () this.switcherTargets.forEach ((el, i) => el.classList.toggle ("current", this.currentLang === el.getAttribute ("data-lang")))
Hier durchlaufen wir eine Reihe von Locale-Switchern und vergleichen deren Werte data-lang
Attribute für den Wert des aktuell verwendeten Gebietsschemas. Stimmen die Werte überein, wird dem Switcher ein zugewiesen aktuell
CSS-Klasse, sonst wird diese Klasse entfernt.
Um das zu machen this.switcherTargets
Um Arbeit zu konstruieren, müssen wir Stimulus-Ziele folgendermaßen definieren:
statische Ziele = ["Switcher"]
Auch hinzufügen Datenziel
Attribute mit Werten von Umschalter
für die li
s:
initialize () //… this.element.innerHTML = languages.map ((lang) => return '
Zu beachten ist auch, dass das Laden von Übersetzungsdateien einige Zeit dauern kann. Wir müssen warten, bis dieser Vorgang abgeschlossen ist, bevor das Gebietsschema gewechselt werden kann. Nutzen wir also die geladen
Ruf zurück:
initialize () i18n.on ('geladen', (geladen) => // <--- let languages = [ title: 'English', code: 'en', title: 'Русский', code: 'ru' ] this.element.innerHTML = languages.map((lang) => Rückkehr '
Vergessen Sie nicht zu entfernen setTimeout
von dem loadUsers ()
Methode:
loadUsers () fetch (this.data.get ("url")) .then (response => response.text ()) .then (json => this.renderUsers (json) this.localize ())
Nachdem das Gebietsschema gewechselt wurde, möchte ich eine hinzufügen ?lang
GET-Parameter an die URL, die den Code der ausgewählten Sprache enthält. Das Anfügen eines GET-Parameters ohne erneutes Laden der Seite kann mit Hilfe der History-API problemlos durchgeführt werden:
set currentLang (lang) if (i18n.language! == lang) i18n.changeLanguage (lang) window.history.pushState (null, null, '? lang = $ lang') // <--- if(this.currentLang !== lang) this.data.set("currentLang", lang) loci18n('body') this.highlightCurrentLang()
Das letzte, was wir heute implementieren werden, ist die Möglichkeit, das Gebietsschema basierend auf den Präferenzen des Benutzers festzulegen. Ein Plugin namens LanguageDetector kann uns dabei helfen, diese Aufgabe zu lösen. Fügen Sie ein neues Garnpaket hinzu:
garne addiere i18next-browser-languagedetector
Einführen SprachDetektor
in der i18n / config.js Datei:
LngDetector aus 'i18next-browser-languagedetector' importieren
Jetzt die Konfiguration anpassen:
const i18n = i18next.use (I18nXHR) .use (LngDetector) .init (// <--- // other options go here… detection: order: ['querystring', 'navigator', 'htmlTag'], lookupQuerystring: 'lang', , function(err, t) if (err) return console.error(err) );
Das Auftrag
Option listet alle Techniken (sortiert nach ihrer Wichtigkeit) auf, die das Plugin ausprobieren soll, um das bevorzugte Gebietsschema zu erraten:
Querzeichenfolge
bedeutet das Überprüfen eines GET-Parameters, der den Code des Gebietsschemas enthält.LookupQuerystring
Legt den Namen des zu verwendenden GET-Parameters fest lang
in unserem Fall.Navigator
bedeutet, aus der Benutzeranfrage Länderdaten abzurufen.htmlTag
beinhaltet das Abrufen des bevorzugten Gebietsschemas aus der lang
Attribut des html
Etikett.In diesem Artikel haben wir einen Blick auf I18next - eine beliebte Lösung zum einfachen Übersetzen von JavaScript-Anwendungen - geworfen. Sie haben gelernt, I18next in das Stimulus-Framework zu integrieren, zu konfigurieren und Übersetzungsdateien asynchron zu laden. Außerdem haben Sie gesehen, wie Sie zwischen den Gebietsschemas wechseln und die Standardsprache basierend auf den Benutzereinstellungen festlegen.
I18next bietet einige zusätzliche Konfigurationsoptionen und viele Plugins. Sehen Sie sich daher die offizielle Dokumentation an, um mehr zu erfahren. Beachten Sie auch, dass Stimulus Sie nicht zwingt, eine bestimmte Lokalisierungslösung zu verwenden. Sie können also auch etwas wie jQuery.I18n oder Polyglot verwenden.
Das ist alles für heute! Vielen Dank fürs Mitlesen und bis zum nächsten Mal.