Nemzetköziesítés (i18n) a React alkalmazásodban: lépésről lépésre

A digitális világban az alkalmazásoknak nincsenek határai. Akár egy kis startup, akár egy nagyvállalat részeként fejlesztesz, a célod az, hogy minél több felhasználóhoz juss el. De mi történik, ha a felhasználók nem beszélik a te nyelvedet? Itt jön képbe a nemzetköziesítés, vagy röviden i18n.

Ez a cikk egy átfogó, lépésről lépésre útmutatót nyújt arról, hogyan teheted React alkalmazásodat többnyelvűvé. Megnézzük, miért elengedhetetlen ez a lépés, és hogyan használhatjuk a piacvezető react-i18next könyvtárat az i18n implementálásához.

Miért Fontos a Nemzetköziesítés (i18n)?

A nemzetköziesítés (i18n) az a folyamat, amelynek során egy alkalmazást úgy tervezünk és fejlesztünk, hogy az képes legyen különböző nyelvek és régiók támogatására anélkül, hogy a forráskódon változtatni kellene. Ne keverjük össze a lokalizációval (l10n), ami a konkrét nyelvi és kulturális adaptációt jelenti (pl. fordítások elkészítése, dátum- és időformátumok beállítása).

Miért érdemes időt és energiát fektetni az i18n-be?

  • Szélesebb közönség elérése: Minél több nyelven elérhető az alkalmazásod, annál több felhasználó tudja hatékonyan használni és élvezni.
  • Fokozott felhasználói élmény: A felhasználók sokkal szívesebben használnak egy olyan alkalmazást, amely a saját anyanyelvükön szól hozzájuk. Ez növeli az elkötelezettséget és a lojalitást.
  • Versenyelőny: Egy többnyelvű alkalmazás kiemelkedik a tömegből, és versenyelőnyt biztosíthat a piacon.
  • Üzleti növekedés: Az új piacok megnyitása és a globális terjeszkedés kulcsa a nyelvi akadályok lebontása.

Lássunk is hozzá, hogyan valósíthatjuk meg mindezt egy React alkalmazásban!

Előkészületek és Telepítés

Mielőtt belemerülnénk a részletekbe, győződj meg róla, hogy van egy működő React projektjed. Ha nincs, gyorsan létrehozhatsz egyet a Create React App segítségével:

npx create-react-app my-i18n-app
cd my-i18n-app

A nemzetköziesítéshez a react-i18next könyvtárat fogjuk használni, amely az i18next keretrendszer React integrációját biztosítja. Ezen kívül szükségünk lesz egy fordítási adatok betöltésére szolgáló backendre, amit a i18next-http-backend fog biztosítani.

npm install i18next react-i18next i18next-http-backend --save
# vagy
yarn add i18next react-i18next i18next-http-backend

Most, hogy az alapok megvannak, kezdjük el a konfigurációt!

1. lépés: Az i18next Konfigurálása

A konfiguráció az első és legfontosabb lépés. Hozzunk létre egy src/i18n.js fájlt, amely inicializálja az i18next-et.

// src/i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import HttpBackend from 'i18next-http-backend';

i18n
  .use(HttpBackend) // Fordítások betöltése HTTP-n keresztül
  .use(initReactI18next) // A React integráció aktiválása
  .init({
    fallbackLng: 'en', // Alapértelmezett nyelv, ha a kiválasztott fordítás hiányzik
    lng: 'hu', // Kezdő nyelv
    debug: true, // Hibakereséshez hasznos
    interpolation: {
      escapeValue: false, // React biztonságosan kezeli az XSS-t, így kikapcsolhatjuk az escape-elést
    },
    backend: {
      loadPath: '/locales/{{lng}}/translation.json', // Hol találhatók a fordítási fájlok
    },
  });

export default i18n;

Ez a konfiguráció beállítja az alapvető dolgokat: meghatározza a visszaváltó nyelvet (fallbackLng), az alapértelmezett kezdő nyelvet (lng), és aktiválja a HTTP backendet, hogy a fordítási fájlokat a /locales/{{lng}}/translation.json útvonalról töltse be.

Ezután importálnunk kell ezt a konfigurációt az alkalmazásunk gyökérkomponensébe, általában az src/index.js fájlba:

// src/index.js
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import './i18n'; // Importáljuk az i18n konfigurációt

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  
    <Suspense fallback={
Loading...
}> );

Fontos, hogy az i18n konfigurációt még az App komponens renderelése előtt importáljuk. A Suspense komponensre azért van szükség, mert az i18next aszinkron módon tölti be a fordításokat, és egy „betöltés” állapotot kell biztosítanunk erre az időre.

2. lépés: Fordítások Kezelése

Most, hogy az i18next konfigurálva van, szükségünk van a fordítási fájlokra. Ezek egyszerű JSON fájlok, amelyek kulcs-érték párokat tartalmaznak.

Hozzuk létre a public mappában a következő struktúrát:

public/
├── locales/
│   ├── en/
│   │   └── translation.json
│   └── hu/
│       └── translation.json

public/locales/en/translation.json:

{
  "welcome": "Welcome to our multi-language app!",
  "greeting": "Hello, {{name}}!",
  "changeLanguage": "Change Language",
  "itemCount_one": "You have {{count}} item.",
  "itemCount_other": "You have {{count}} items."
}

public/locales/hu/translation.json:

{
  "welcome": "Üdvözlünk a többnyelvű alkalmazásunkban!",
  "greeting": "Szia, {{name}}!",
  "changeLanguage": "Nyelv váltása",
  "itemCount_one": "{{count}} elemed van.",
  "itemCount_other": "{{count}} elemed van."
}

Ahogy láthatod, a kulcsok megegyeznek, de az értékek az adott nyelvnek megfelelő fordítást tartalmazzák. Később kitérünk a {{name}} típusú placeholder-ekre és a többes számú fordításokra is.

3. lépés: Fordítások Használata a Komponensekben

A react-i18next két fő módszert kínál a fordítások használatára a React komponensekben: a useTranslation hookot és a Trans komponenst.

A. useTranslation Hook

Ez a leggyakoribb és legegyszerűbb módszer. Az App.js fájlban használjuk:

// src/App.js
import React from 'react';
import { useTranslation } from 'react-i18next';

function App() {
  const { t, i18n } = useTranslation();

  const changeLanguage = (lng) => {
    i18n.changeLanguage(lng);
  };

  return (
    

{t('greeting', { name: 'Felhasználó' })}

{t('itemCount_one', { count: 1 })}

{t('itemCount_other', { count: 5 })}

{t('changeLanguage')}: {i18n.language}

); } export default App;

Amit itt látunk:

  • A useTranslation() hook visszaad egy t függvényt (amely a fordító függvény), és az i18n objektumot, amely az i18next inicializált példánya.
  • A t('welcome') egyszerűen lekéri a ‘welcome’ kulcshoz tartozó fordítást az aktuálisan kiválasztott nyelven.
  • A t('greeting', { name: 'Felhasználó' }) bemutatja az interpolációt: a {{name}} placeholder-t a megadott értékkel ('Felhasználó') helyettesíti.
  • Az i18n.changeLanguage(lng) metódussal dinamikusan megváltoztathatjuk az alkalmazás nyelvét.

B. Trans Komponens

Néha szükségünk van arra, hogy a fordítási stringekbe HTML elemeket vagy React komponenseket illesszünk. Erre a célra a Trans komponens a legalkalmasabb. Képzeljük el, hogy a „welcome” üzenetben szeretnénk egy linket megjeleníteni:

// public/locales/en/translation.json
{
  "welcome_html": "Welcome to our multi-language app! Learn more here."
}

// public/locales/hu/translation.json
{
  "welcome_html": "Üdvözlünk a többnyelvű alkalmazásunkban! Tudj meg többet itt."
}

És a komponensben:

import { useTranslation, Trans } from 'react-i18next';

// ... az App komponensen belül
return (
  // ...
  <p>
    <Trans i18nKey="welcome_html">
      Welcome to our <strong>multi-language app</strong>! Learn more <a href="/about">here</a>.
    </Trans>
  </p>
  // ...
);

A Trans komponensbe beillesztett HTML (<strong>, <a>) a fordítási stringben lévő <0>, <1> stb. tagekkel párosul. Ez lehetővé teszi, hogy a fordítók ne kelljenek a teljes HTML struktúrával foglalkozniuk, csak a szöveggel, miközben a dinamikus részeket a kódunk garantálja.

4. lépés: Nyelvváltás és Nyelv Visszaállítása

Már láttunk egy egyszerű nyelvváltó mechanizmust a changeLanguage függvénnyel. Gyakori igény, hogy a felhasználó által kiválasztott nyelvet megjegyezzük. Az i18next automatikusan kezeli ezt, ha a megfelelő language detector pluginokat telepítjük (pl. i18next-browser-languagedetector). Jelenlegi konfigurációnk a böngésző alapértelmezett beállításait használja, és emlékszik az utolsó kiválasztott nyelvre a munkameneten belül.

Ha a i18next-browser-languagedetector-t is telepítjük:

npm install i18next-browser-languagedetector --save

Majd frissítsük az src/i18n.js fájlt:

// src/i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import HttpBackend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector'; // Importáljuk

i18n
  .use(HttpBackend)
  .use(LanguageDetector) // Aktiváljuk a nyelvérzékelőt
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    // lng: 'hu', // Ez már nem szükséges, ha a detektor be van kapcsolva
    debug: true,
    interpolation: {
      escapeValue: false,
    },
    backend: {
      loadPath: '/locales/{{lng}}/translation.json',
    },
    detection: {
      order: ['queryString', 'cookie', 'localStorage', 'navigator', 'htmlTag'],
      caches: ['localStorage', 'cookie'],
    }
  });

export default i18n;

Most az i18next megpróbálja észlelni a felhasználó nyelvét a megadott sorrendben, és el is menti azt (pl. localStorage-ba), így a következő látogatáskor sem kell újra beállítani.

5. lépés: Többes Számok Kezelése (Pluralizáció)

A többes számok kezelése nyelvenként eltérő lehet. Például angolul van „one” és „other” forma, míg egyes nyelveken (pl. orosz, arab) több kategória is létezik. Az i18next beépített támogatással rendelkezik erre.

A fordítási fájljainkban már szerepeltek a kulcsok: itemCount_one és itemCount_other. Az i18next a count változó értékétől függően automatikusan kiválasztja a megfelelő kulcsot:

<p>{t('itemCount', { count: 1 })}</p>   // "You have 1 item." / "1 elemed van."
<p>{t('itemCount', { count: 5 })}</p>   // "You have 5 items." / "5 elemed van."
<p>{t('itemCount', { count: 0 })}</p>   // "You have 0 items." / "0 elemed van."

A nyelv specifikus többes szám szabályokat az i18next kezeli. Ha szükséges, további kategóriákat is használhatunk, mint például _zero, _two, _few, _many, de ezek általában csak bonyolultabb nyelveknél szükségesek.

6. lépés: Dátum, Idő és Szám Formázás (Lokalizáció)

Bár az i18next kiválóan kezeli a szöveges fordításokat, a dátumok, időpontok és számok formázása már a lokalizáció (l10n) területéhez tartozik, és az i18next alapból nem foglalkozik vele. Szerencsére a modern böngészők beépített API-kat kínálnak erre a célra: az Intl.DateTimeFormat és az Intl.NumberFormat.

Példa dátum formázására:

const formattedDate = new Intl.DateTimeFormat(i18n.language, {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
}).format(new Date());

console.log(formattedDate); // Pl. "2023. június 14." vagy "June 14, 2023"

Példa szám formázására:

const amount = 123456.789;
const formattedNumber = new Intl.NumberFormat(i18n.language, {
  style: 'currency',
  currency: 'EUR',
}).format(amount);

console.log(formattedNumber); // Pl. "123 456,79 €" vagy "€123,456.79"

Integrálhatunk külső könyvtárakat is, mint például a moment.js vagy date-fns a komplexebb dátumkezeléshez, de az Intl API-k gyakran elegendőek az alapvető formázási igényekhez.

7. lépés: Haladó Témák és Tippek

A. Névterek (Namespaces)

Egy nagyobb alkalmazásban a translation.json fájl könnyen túl naggyá válhat. A névterek segítségével logikai egységekre bonthatjuk a fordítási fájlokat (pl. common.json, products.json, profile.json).

Például, létrehozhatjuk a public/locales/hu/common.json és public/locales/hu/product.json fájlokat. Ezután a konfigurációban meg kell adni a névtereket:

// src/i18n.js
// ...
i18n.init({
  // ...
  ns: ['translation', 'common', 'product'], // Alapértelmezett névterek
  defaultNS: 'translation', // Alapértelmezett névtér
  backend: {
    loadPath: '/locales/{{lng}}/{{ns}}.json', // Most már a {{ns}} is szerepel
  },
});
// ...

A komponensben a következőképpen használhatjuk:

import { useTranslation } from 'react-i18next';

function MyProductComponent() {
  const { t } = useTranslation(['product', 'common']); // Fordítás a 'product' és 'common' névterekből

  return (
    <div>
      <h2>{t('product:title')}</h2> {/* Fordítás a 'product' névtérből */}
      <p>{t('common:currencyLabel')}</p> {/* Fordítás a 'common' névtérből */}
    </div>
  );
}

B. Fordítások Betöltési Állapota és Hiba Kezelés

Mivel a fordítások aszinkron módon töltődnek be, kezelnünk kell a betöltési állapotot. A react-i18next useTranslation hookja visszaadja az i18n.isInitialized állapotot, és a React Suspense komponensével is együttműködik, ahogy azt az index.js-ben már láttuk.

C. Tesztelés

A nemzetköziesített komponensek tesztelésekor be kell mockolni az i18next funkcionalitását. A react-i18next javasol egy react-i18next mockot, amely segít ebben a folyamatban. Például a jest.mock('react-i18next', ...) használatával.

D. Fordításkezelő Eszközök

Nagyobb projektek esetén, különösen, ha fordítókkal dolgozol, érdemes profi fordításkezelő platformokat használni, mint például a Phrase, Lokalise, Crowdin, vagy Transifex. Ezek az eszközök segítenek a fordítási munkafolyamatok automatizálásában, a minőségellenőrzésben és a fordítások szinkronizálásában.

Összegzés

A React alkalmazásod nemzetköziesítése nem egy egyszerű feladat, de a react-i18next könyvtár segítségével a folyamat meglepően gördülékeny lehet. Reméljük, ez a lépésről lépésre útmutató segített megérteni az alapokat, és felvértezett a szükséges tudással, hogy globális közönséghez juthass el.

Ne feledd, a korai nemzetköziesítés a fejlesztési ciklusban sokkal egyszerűbb, mint utólag bevezetni. Kezdd el még ma, és nyisd meg alkalmazásodat a világ előtt!

Leave a Reply

Az e-mail címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük