Beste Internationalisierung für Gatsby (ein i18next-basierter Leitfaden)
en

Gatsby-Lokalisierung leicht gemacht mit dieser Schritt-für-Schritt-Anleitung mit i18next ✅

Sie kennen Gatsby, richtig? - Wenn nicht, hören Sie auf, diesen Artikel zu lesen und machen Sie etwas anderes.

Ja, Gatsby ist ein Open-Source-Framework, welches Funktionen von React, GraphQL und Webpack in einem einzigen Tool zum Erstellen statischer Websites und Apps kombiniert.

Aber wie sieht die Internationalisierung (i18n) in Gatsby aus?

Es gibt einige Plugins/Bibliotheken, die bei der Instrumentierung des Gatsby-Codes für die Internationalisierung helfen können. In diesem Artikel verwenden wir ein Plugin, das auf dem berühmten i18n-Framework i18next bzw. seiner grossartigen Erweiterung für React.js basiert - react-i18next.
Das von uns verwendete Gatsby-Plugin ist gatsby-plugin-react-i18next, erstellt von Dmitriy Nevzorov.

Inhaltsverzeichnis

Also erstmal: "Warum i18next?"

Wenn es um React-Lokalisierung geht, ist eines der beliebtesten Frameworks i18next mit seiner React-Erweiterung react-i18next, und das aus guten Gründen:

i18next wurde Ende 2011 erstellt. Es ist älter als die meisten Bibliotheken, die Sie heutzutage verwenden, einschliesslich Ihrer wichtigsten Frontend-Technologie (React, Angular, Vue, ...).
➡️ nachhaltig

Basierend darauf, wie lange i18next bereits Open Source verfügbar ist, gibt es keinen echten i18n-Fall, der nicht mit i18next gelöst werden könnte.
➡️ reif

i18next kann in jeder Umgebung mit Javascript (und einigen Nicht-Javascript - .net, elm, iOS, Android, Ruby, ...) verwendet werden, mit jedem UI-Framework, mit jedem i18n-Format, ... die Möglichkeiten sind endlos.
➡️ erweiterbar

Es gibt viele Funktionen und Möglichkeiten, die Sie mit i18next im Vergleich zu anderen regulären 18n-Frameworks erhalten.
➡️ reich

Hier finden Sie weitere Informationen darüber, warum i18next so besonders ist und wie es funktioniert.

Fangen wir an...

Voraussetzungen

Stellen Sie sicher, dass Sie Node.js und npm installiert haben. Am besten, wenn Sie etwas Erfahrung mit einfachem HTML, JavaScript, React.js und einfachem Gatsby haben, bevor Sie zu gatsby-plugin-react-i18next. Dieses Gatsby-Lokalisierungsbeispiel ist nicht als Gatsby- oder React-Tutorial für Anfänger gedacht.

Einstieg

Nehmen Sie Ihr eigenes Gatsby-Projekt oder erstellen Sie ein neues, z. B. mit der gatsby-cli.

npx gatsby-cli new

Wir werden einen Sprachumschalter erstellen, um den Inhalt zwischen verschiedenen Sprachen zu ändern.

Lassen Sie uns einige i18next-Abhängigkeiten installieren:

npm install gatsby-plugin-react-i18next i18next react-i18next

Erstellen Sie ein locales-Verzeichnis und fügen Sie einen Unterordner für Ihre Standard-/Referenzsprache hinzu (z. B. en für Englisch).
Dort fügen wir dann unsere Namespace-Dateien hinzu, wie:

1
2
3
|-- en
|-- common.json
|-- index.json

Lassen Sie uns eine languages.js-Datei hinzufügen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const { join } = require('path')
const { readdirSync, lstatSync } = require('fs')

const defaultLanguage = 'en';

// based on the directories get the language codes
const languages = readdirSync(join(__dirname, 'locales')).filter((fileName) => {
const joinedPath = join(join(__dirname, 'locales'), fileName)
const isDirectory = lstatSync(joinedPath).isDirectory()
return isDirectory
});
// defaultLanguage as first
languages.splice(languages.indexOf(defaultLanguage), 1);
languages.unshift(defaultLanguage);

module.exports = {
languages,
defaultLanguage,
};

Importieren Sie die Datei languages.js in die Datei gatsby-config.js und konfigurieren Sie einige Plugins:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const { languages, defaultLanguage } = require('./languages');
// somewhere in your plugins add:
module.exports = {
// ...
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/locales`,
name: `locale`
}
},
{
resolve: 'gatsby-plugin-react-i18next',
options: {
languages,
defaultLanguage,
siteUrl,
i18nextOptions: {
// debug: true,
fallbackLng: defaultLanguage,
supportedLngs: languages,
defaultNS: 'common',
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
}
},
},
},
// ...
]
}

Beginnen wir nun mit der Instrumentierung unseres ersten internationalisierten Textes.
Da gatsby-plugin-react-i18next alle Methoden und Komponenten von react-i18next exportiert, können wir dies tun:
In einer "page"-Datei:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import { Trans, useTranslation } from 'gatsby-plugin-react-i18next';
import { graphql } from 'gatsby';
import React from 'react';
// ...

const IndexPage = () => {
const { t } = useTranslation();
return (
<Layout>
<Seo title={t('seo')} />
<h1>
<Trans i18nKey="title">Hi people</Trans>
</h1>
{ /* ... */}
</Layout>
)
}

export default IndexPage;

export const query = graphql`
query ($language: String!) {
locales: allLocale(
filter: { ns: { in: ["index"] }, language: { eq: $language } }
) {
edges {
node {
ns
data
language
}
}
}
}
`;

Definieren Sie jetzt auch eine locales/en/index.json-Namespace-Datei, wie folgt:

1
2
3
4
{
"seo": "Home",
"title": "Hi people"
}

Und vielleicht auch noch eine für Deutsch?

locales/de/index.json:

1
2
3
4
{
"seo": "Startseite",
"title": "Hallo Leute"
}

Sprachumschalter

Um zwischen verschiedenen Sprachen wechseln zu können, benötigen wir einen Sprachumschalter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { Link, useI18next } from 'gatsby-plugin-react-i18next';
import React from 'react';

const Header = ({ siteTitle }) => {
const { languages, originalPath, t, i18n } = useI18next();
return (
<header className="main-header">
{/* ... */}
<ul className="languages">
{languages.map((lng) => (
<li key={lng}>
<Link to={originalPath} language={lng} style={{ textDecoration: i18n.resolvedLanguage === lng ? 'underline' : 'none' }}>
{lng}
</Link>
</li>
))}
</ul>
</header>
);
};

export default Header;

Sie sollten jetzt so etwas sehen:

gatsby Sprachumschalter

Standardmässig wird gatsby-plugin-react-i18next beim ersten Laden auf die defaultLanguage zurückfallen, wenn die erkannte Sprache des Browsers im languages-Array nicht verfügbar ist.

Wenn Sie im languages-Array auf eine andere Sprache zurückgreifen möchten, können Sie die Option fallbackLanguage definieren.

Jetzt sollte auch das Umschalten auf de (Deutsch) funktionieren:

gatsby Sprachumschalter

🥳 Toll, Sie haben gerade Ihren ersten Sprachumschalter erstellt!

Lassen Sie uns eine zweite Seite erstellen ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { graphql } from 'gatsby';
import React, { useState } from 'react';
import Layout from '../components/layout';
import { useTranslation } from 'gatsby-plugin-react-i18next';

const SecondPage = (props) => {
const { t } = useTranslation();
const [count, setCounter] = useState(0);
return (
<Layout>
<Seo title={t('title')} />
<h1>
<Trans i18nKey="title">Page two</Trans>
</h1>
<p>
<Trans i18nKey="welcome">Welcome to page 2</Trans> ({props.path})
</p>
{/* ... */}
</Layout>
);
};

export default SecondPage;

export const query = graphql`
query ($language: String!) {
locales: allLocale(
filter: { ns: { in: ["page-2"] }, language: { eq: $language } }
) {
edges {
node {
ns
data
language
}
}
}
}
`;

Ein neuer Namensraum:
locales/en/page-2.json

1
2
3
4
{
"title": "Page two",
"welcome": "Welcome to page 2"
}

locales/de/page-2.json

1
2
3
4
{
"title": "Seite zwei",
"welcome": "Willkommen auf Seite 2"
}

...und verweisen Sie von der ersten Seite auf diese Seite:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { Link, Trans, useTranslation } from 'gatsby-plugin-react-i18next';
import { graphql } from 'gatsby';
import React from 'react';
// ...

const IndexPage = () => {
const { t } = useTranslation();
return (
<Layout>
<Seo title={t('seo')} />
<h1>
<Trans i18nKey="title">Hi people</Trans>
</h1>
{ /* ... */}
<p>
<Link to="/page-2/">
<Trans i18nKey="goToPage2">Go to page 2</Trans>
</Link>
</p>
</Layout>
)
}

export default IndexPage;

export const query = graphql`
query ($language: String!) {
locales: allLocale(
filter: { ns: { in: ["index"] }, language: { eq: $language } }
) {
edges {
node {
ns
data
language
}
}
}
}
`;

Ein neuer Übersetzungsschlüssel für locales/en/index.json:

1
2
3
4
5
{
"seo": "Home",
"title": "Hi people",
"goToPage2": "Go to page 2"
}

locales/de/index.json:

1
2
3
4
5
{
"seo": "Startseite",
"title": "Hallo Leute",
"goToPage2": "Gehen Sie zu Seite 2"
}

Die aus gatsby-plugin-react-i18next exportierte Link-Komponente verlinkt automatisch auf die richtige Sprache.
Die Link-Komponente ist identisch mit der Gatsby-Link-Komponente, ausser dass Sie die zusätzliche Sprach-prop bereitstellen können, um einen Link zu einer Seite mit einer anderen Sprache zu erstellen.

Interpolation und Pluralisierung

i18next geht über die Bereitstellung der standardmässigen i18n-Funktionen hinaus. Aber sicher ist es in der Lage, Plurale und Interpolation zu verarbeiten.

Zählen wir jedes Mal, wenn auf eine Schaltfläche geklickt wird:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { graphql } from 'gatsby';
import React, { useState } from 'react';
import Layout from '../components/layout';
import { useTranslation } from 'gatsby-plugin-react-i18next';

const SecondPage = (props) => {
const { t } = useTranslation();
const [count, setCounter] = useState(0);
return (
<Layout>
<Seo title={t('title')} />
<h1>
<Trans i18nKey="title">Page two</Trans>
</h1>
<p>
<Trans i18nKey="welcome">Welcome to page 2</Trans> ({props.path})
</p>
<p>
<button onClick={() => {
setCounter(count + 1);
}}>{
t('counter', { count })
}</button>
</p>
{/* ... */}
</Layout>
);
};

export default SecondPage;

export const query = graphql`
query ($language: String!) {
locales: allLocale(
filter: { ns: { in: ["page-2"] }, language: { eq: $language } }
) {
edges {
node {
ns
data
language
}
}
}
}
`;

...und erweitern die Übersetzungsressourcen:
locales/en/page-2.json

1
2
3
4
5
6
7
{
"title": "Page two",
"welcome": "Welcome to page 2",
"counter_one": "clicked one time",
"counter_other": "clicked {{count}} time",
"counter_zero": "Click me!"
}

locales/de/page-2.json

1
2
3
4
5
6
7
{
"title": "Seite zwei",
"welcome": "Willkommen auf Seite 2",
"counter_one": "einmal angeklickt",
"counter_other": "{{count}} Mal geklickt",
"counter_zero": "Klick mich!"
}

Basierend auf dem Zählwert wählt i18next die korrekte Pluralform aus.

i18next bietet auch die Möglichkeit, eine spezielle Übersetzung für {count: 0} zu haben, sodass eine natürlichere Sprache verwendet werden kann. Wenn der count Wert 0 ist und ein _zero-Eintrag vorhanden ist, dann wird er anstelle des Plural-Suffix der regulären Sprache (_other) verwendet.

Lesen Sie mehr über Pluralisierung und Interpolation in der offiziellen i18next-Dokumentation.

gatsby Pluralisierung

💡 i18next ist auch in der Lage, Sprachen mit mehreren Pluralformen zu verarbeiten, wie Arabisch:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// translation resources:
{
"key_zero": "zero",
"key_one": "singular",
"key_two": "two",
"key_few": "few",
"key_many": "many",
"key_other": "other"
}

// usage:
t('key', {count: 0}); // -> "zero"
t('key', {count: 1}); // -> "singular"
t('key', {count: 2}); // -> "two"
t('key', {count: 3}); // -> "few"
t('key', {count: 4}); // -> "few"
t('key', {count: 5}); // -> "few"
t('key', {count: 11}); // -> "many"
t('key', {count: 99}); // -> "many"
t('key', {count: 100}); // -> "other"

Warum funktionieren meine Pluralformen nicht?

Sehen Sie diese Warnung in der Entwicklungskonsole (debug: true)?

i18next::pluralResolver: Your environment seems not to be Intl API compatible, use an Intl.PluralRules polyfill. Will fallback to the compatibilityJSON v3 format handling.

Mit v21 hat i18next das Suffix mit dem in der Intl API. In Umgebungen, in denen die API Intl.PluralRules nicht verfügbar ist (wie bei älteren Android-Geräten), müssen Sie möglicherweise zu polyfill die Intl.PluralRules-API. Falls es nicht verfügbar ist, wird auf die Pluralbehandlung von i18next JSON format v3 zurückgegriffen. Und wenn Ihr json bereits die neuen Suffixe verwendet, werden Ihre Pluralschlüssel wahrscheinlich nicht angezeigt.

tldr;

npm install intl-pluralrules

1
import 'intl-pluralrules'

Formatierung

Sehen wir uns nun an, wie wir verschiedene Datumsformate mit Hilfe von i18next und Luxon verwenden können, um das Datum zu verarbeiten und Zeit.

npm install luxon

Wir möchten eine Fusszeile haben, die das aktuelle Datum anzeigt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import React from 'react';
import { DateTime } from 'luxon';
import { useI18next } from 'gatsby-plugin-react-i18next';
// ...

const Layout = ({ children }) => {
const { t, i18n } = useI18next();

// defining custom formatters is normally done immediately after the i18next.init call, but with gatsby-plugin-react-i18next is not possible, so let's add it here
if (!i18n.services.formatter.date_huge) {
i18n.services.formatter.add('date_huge', (value, lng, options) => {
return DateTime.fromJSDate(value).setLocale(lng).toLocaleString(DateTime.DATE_HUGE)
});
}

return (
<>
<Header />
<div
style={{
margin: '0 auto',
maxWidth: 960,
padding: '0 1.0875rem 1.45rem',
}}
>
<main>{children}</main>
<footer style={{ marginTop: 50 }}>
<i>
{
t('footer', { date: new Date() })
}
</i>
</footer>
</div>
</>
);
};

export default Layout;

Importieren Sie Luxon und definieren Sie eine Formatfunktion, wie in der Dokumentation dokumentiert, und fügen Sie den neuen Übersetzungsschlüssel hinzu:

locales/en/common.json

1
2
3
{
"footer": "Today is {{date, date_huge}}"
}

locales/de/common.json

1
2
3
{
"footer": "Heute ist {{date, date_huge}}"
}

😎 Cool, jetzt haben wir eine sprachspezifische Datumsformatierung!

Englisch: gatsby english

Deutsch: gatsby german

Kontext

Was ist mit einer bestimmten Begrüssungsnachricht basierend auf der aktuellen Tageszeit? also morgens, abends usw. Dies ist dank der Funktion context von i18next möglich.

Lassen Sie uns eine getGreetingTime-Funktion erstellen und das Ergebnis als Kontextinformationen für unsere Fusszeilenübersetzung verwenden:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import React from 'react';
import { DateTime } from 'luxon';
import { useI18next } from 'gatsby-plugin-react-i18next';
// ...

const getGreetingTime = (d = DateTime.now()) => {
const split_afternoon = 12; // 24hr time to split the afternoon
const split_evening = 17; // 24hr time to split the evening
const currentHour = parseFloat(d.toFormat('hh'));

if (currentHour >= split_afternoon && currentHour <= split_evening) {
return 'afternoon';
} else if (currentHour >= split_evening) {
return 'evening';
}
return 'morning';
}

const Layout = ({ children }) => {
const { t, i18n } = useI18next();

// defining custom formatters is normally done immediately after the i18next.init call, but with gatsby-plugin-react-i18next is not possible, so let's add it here
if (!i18n.services.formatter.date_huge) {
i18n.services.formatter.add('date_huge', (value, lng, options) => {
return DateTime.fromJSDate(value).setLocale(lng).toLocaleString(DateTime.DATE_HUGE)
});
}

return (
<>
<Header />
<div
style={{
margin: '0 auto',
maxWidth: 960,
padding: '0 1.0875rem 1.45rem',
}}
>
<main>{children}</main>
<footer style={{ marginTop: 50 }}>
<i>
{
t('footer', { date: new Date(), context: getGreetingTime() })
}
</i>
</footer>
</div>
</>
);
};

export default Layout;

Und fügen Sie einige kontextspezifische Übersetzungsschlüssel hinzu:

locales/en/common.json

1
2
3
4
5
6
{
"footer": "Today is {{date, date_huge}}",
"footer_afternoon": "Good afternoon! It's {{date, date_huge}}",
"footer_evening": "Good evening! Today was the {{date, date_huge}}",
"footer_morning": "Good morning! Today is {{date, date_huge}} | Have a nice day!"
}

locales/de/common.json

1
2
3
4
5
6
{
"footer": "Heute ist {{date, date_huge}}",
"footer_afternoon": "Guten Nachmittag! Es ist {{date, date_huge}}",
"footer_evening": "Guten Abend! Heute war der {{date, date_huge}}",
"footer_morning": "Guten Morgen! Heute ist {{date, date_huge}} | Einen schönen Tag noch!"
}

😁 Ja, es funktioniert!

gatsby Übersetzungen

Schlüsselextraktion

Dank babel-plugin-i18next-extract können Sie automatisch Übersetzungen innerhalb der t-Funktion und der Trans-Komponente aus Ihren Seiten extrahieren und in den Namespace-Dateien speichern.

Es funktioniert so:
Installieren Sie zuerst die erforderlichen Abhängigkeiten:

npm install @babel/cli @babel/plugin-transform-typescript babel-plugin-i18next-extract

Erstellen oder aktualisieren Sie die Datei babel-extract.config.js (nennen Sie sie NICHT babel.config.js, sonst wird sie von Gatsby verwendet):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const { defaultLanguage } = require('./languages');
process.env.NODE_ENV = 'test';
module.exports = {
presets: ['babel-preset-gatsby'],
plugins: [
[
'i18next-extract',
{
keyAsDefaultValue: [defaultLanguage],
useI18nextDefaultValue: [defaultLanguage],
// discardOldKeys: true,
defaultNS: 'common',
outputPath: 'locales/{{locale}}/{{ns}}.json',
customTransComponents: [['gatsby-plugin-react-i18next', 'Trans']],
compatibilityJSON: 'v4',
}
]
],
overrides: [
{
test: [`**/*.ts`, `**/*.tsx`],
plugins: [[`@babel/plugin-transform-typescript`, {isTSX: true}]]
}
]
};

Fügen Sie Ihrer package.json ein Skript hinzu:

1
2
3
"scripts": {
"extract": "babel --config-file ./babel-extract.config.js -o tmp/chunk.js 'src/**/*.{js,jsx,ts,tsx}' && rm -rf tmp"
}

Wenn Sie Übersetzungen pro Seite für einen bestimmten Namensraum extrahieren möchten, können Sie am Anfang der Seite einen speziellen Kommentar hinzufügen:

1
2
3
4
// i18next-extract-mark-ns-start index

import React from 'react';
// ...

zu Info: Es gibt auch andere Kommentarhinweise, die Sie verwenden können.

Alle Ihre Seiten vorbereitet? Schön, also versuchen wir das:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// i18next-extract-mark-ns-start index

import React from 'react';
import { Link, Trans, useTranslation } from 'gatsby-plugin-react-i18next';
import { graphql, Link as GatsbyLink } from 'gatsby';
import { StaticImage } from 'gatsby-plugin-image';
import Layout from '../components/layout';
import Seo from '../components/seo';

const IndexPage = () => {
const { t } = useTranslation();
return (
<Layout>
<Seo title={t('seo')} />
<h1>
<Trans i18nKey="title">Hi people</Trans>
</h1>
<p>
<Trans i18nKey="welcome">Welcome to your new Gatsby site.</Trans>
</p>
<p>
<Trans i18nKey="cta">Now go build something great.</Trans>
</p>
<p>
<Link to="/page-2/">
<Trans i18nKey="goToPage2">Go to page 2</Trans>
</Link>
</p>
</Layout>
);
};

export default IndexPage;

export const query = graphql`
query ($language: String!) {
locales: allLocale(
filter: { ns: { in: ["common", "index"] }, language: { eq: $language } }
) {
edges {
node {
ns
data
language
}
}
}
}
`;

Das Ausführen von npm run extract fügt nun diesen neuen cta-Schlüssel zur Namespace-Datei hinzu:

1
2
3
4
5
6
7
{
"cta": "Now go build something great.",
"goToPage2": "Go to page 2",
"seo": "Home",
"title": "Hi people",
"welcome": "Welcome to your new Gatsby site."
}

Extra-Power

Das ist alles schon toll, aber wir können noch mehr!

Schön wäre eine Übersicht, welche Übersetzungen fehlen und welche Dateien komplett übersetzt sind...
Und was, wenn Sie neue Schlüssel extrahiert haben, und dieser würde automatisch übersetzt werden?
Um dies wahr werden zu lassen, benötigen wir ein Übersetzungsmanagement-System...

Indem Sie die Übersetzungen an einige Übersetzer oder Übersetzungsagenturen senden, haben Sie mehr Kontrolle und einen direkten Kontakt mit ihnen. Das bedeutet aber auch mehr Arbeit für Sie. Dies ist ein traditioneller Weg. Beachten Sie jedoch, dass das Versenden von Dateien immer einen Overhead verursacht.

Gibt es eine bessere Option?

Auf jeden Fall!

i18next hilft dabei, die Anwendung zu übersetzen, und das ist grossartig – aber es steckt noch mehr dahinter.

  • Wie integrieren Sie eventuelle Übersetzungsdienste/-agenturen?
  • Wie behalten Sie den Überblick über neue oder entfernte Inhalte?
  • Wie gehen Sie mit der richtigen Versionierung um?
  • und vieles mehr...

Suche Sie nach sowas❓

transformiere den Lokalisierungsprozess

Wie sieht das aus?

Zuerst müssen Sie sich bei locize registrieren und anmelden. Dann erstellen Sie ein neues Projekt in locize und fügen Ihre Übersetzungen hinzu. Sie können Ihre Übersetzungen entweder über die CLI oder durch Importieren der einzelnen json-Dateien oder über die API bewerkstelligen.

Lassen Sie uns nun die locize-cli installieren:

npm install -g locize-cli

Wir bereiten ein neues Skript vor, das unsere lokalen Änderungen mit locize synchronisiert. Und auch ein optionales zweites Skript, das nur die neuesten Übersetzungen von locize herunterlädt. Stellen Sie sicher, dass Sie Ihre Projekt-ID und Ihren API-Schlüssel verwenden:

1
2
3
4
"scripts": {
"syncLocales": "locize sync --project-id=5d47a999-5c34-4161-a389-bc2189507a50 --ver=latest --api-key=42ca9d58-18da-44c7-8dd3-8f59b8c35bda --path=./locales",
"downloadLocales": "locize download --project-id=5d47a999-5c34-4161-a389-bc2189507a50 --ver=latest --clean=true --path=./locales"
}

Verwenden Sie das Skript npm run syncLocales, um Ihr lokales Repository mit dem zu synchronisieren, was auf locize veröffentlicht wurde.

Alternativ können Sie auch das Skript npm run downloadLocales verwenden, um die veröffentlichten Lokalisierungsübersetzungen immer in Ihr lokales Repository herunterzuladen, bevor Sie Ihre App bündeln.

Wenn wir jetzt einen neuen Übersetzungsschlüssel hinzufügen, etwa so:

1
<Trans i18nKey="newKey">this will be added automatically after "extract" and "syncLocales"</Trans>

und anschliessend npm run export und dann npm run syncLocales ausführen, erhalten wir Folgendes:

locales/en/page-2.json:

1
2
3
4
5
6
7
8
9
{
"back": "Go back to the homepage",
"counter_one": "clicked one time",
"counter_other": "clicked {{count}} time",
"counter_zero": "Click me!",
"title": "Page two",
"welcome": "Welcome to page 2",
"newKey": "this will be added automatically after \"extract\" and \"syncLocales\""
}

locales/de/page-2.json:

1
2
3
4
5
6
7
8
9
{
"back": "Gehen Sie zurück zur Startseite",
"counter_one": "einmal angeklickt",
"counter_other": "{{count}} Mal geklickt",
"counter_zero": "Klick mich!",
"title": "Seite zwei",
"welcome": "Willkommen auf Seite 2",
"newKey": "dies wird automatisch nach \"extract\" und \"syncLocales\" hinzugefügt"
}

neuer Schlüssel

Dank der optional aktivierten automatische maschinelle Übersetzung Option werden während der Entwicklung der App nicht nur neue Schlüssel zu locize hinzugefügt, sondern auch automatisch mittels maschineller Übersetzung in die Zielsprachen übersetzt.

gatsby Übersetzungen

👀 aber es gibt noch mehr... (In-Kontext-Editor)

Mit Hilfe des Plugins locize können Sie Ihre App im locize InContext Editor verwenden.

Neugierig zu sehen, wie das aussieht?

Ok, installieren Sie zuerst die locize-Abhängigkeit:

npm install locize

Fügen Sie dann im Code (wir wählen unsere Datei layout.js aus) Folgendes hinzu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import React from 'react';
import { useI18next } from 'gatsby-plugin-react-i18next';
import { locizePlugin, setEditorLng } from 'locize';
// ...

const Layout = ({ children }) => {
const { t, i18n } = useI18next();

// defining custom formatters is normally done immediately after the i18next.init call, but with gatsby-plugin-react-i18next is not possible, so let's add it here
if (!i18n.services.formatter.date_huge) {
i18n.services.formatter.add('date_huge', (value, lng, options) => {
return DateTime.fromJSDate(value).setLocale(lng).toLocaleString(DateTime.DATE_HUGE)
});
// also the locize plugin normally is automatically configured, but here we need to do it that way
locizePlugin.init(i18n);
setEditorLng(i18n.resolvedLanguage);
}

return (
<>
<Header />
<div
style={{
margin: '0 auto',
maxWidth: 960,
padding: '0 1.0875rem 1.45rem',
}}
>
<main>{children}</main>
<footer style={{ marginTop: 50 }}>
<i>
{
t('footer', { date: new Date(), context: getGreetingTime() })
}
</i>
</footer>
</div>
</>
);
};

export default Layout;

Und in der gatsby-config.js fügen Sie einige neue React-Optionen hinzu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const { languages, defaultLanguage } = require('./languages');
module.exports = {
// ...
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/locales`,
name: `locale`
}
},
{
resolve: 'gatsby-plugin-react-i18next',
options: {
languages,
defaultLanguage,
siteUrl,
i18nextOptions: {
// debug: true,
fallbackLng: defaultLanguage,
supportedLngs: languages,
defaultNS: 'common',
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
react: {
bindI18n: 'languageChanged editorSaved', // the editorSaved event will trigger a rerender
}
},
},
},
// ...
]
}

Gehen Sie dann zu Ihrem Locize-Projekt und definieren Sie Ihre Kontext-Editor-URLs, wie hier beschrieben.

Das Ergebnis wird wie folgt aussehen: i18next In-Kontext

Ist das nicht toll?

🧑‍💻 Den vollständigen Code finden Sie hier.

Wenn Sie mehr Grundlagen über i18next erfahren möchten, gibt es auch ein i18next-Crashkurs-Video.

🎉🥳 Herzlichen Glückwunsch 🎊🎁

Ich hoffe, Sie haben ein paar neue Dinge über gatsby-plugin-react-i18next, i18next, React.js-Lokalisierung und moderne Lokalisierungs-Workflows gelernt.

Wenn Sie also Ihr i18n-Thema auf die nächste Ebene bringen möchten, lohnt es sich, die Übersetzungs-Management Platform - locize auszuprobieren.

Die Gründer von locize sind auch die Schöpfer von i18next. Mit der Nutzung von locize unterstützen Sie also direkt die Zukunft von i18next.

👍

Share