Indietro

Stai usando male l'i18n in Next.js

Team avatarTeam
Ernest McCarter avatarErnest McCarter
guideinternationalizationnextjsi18ngt-nextapp-routertutorial

L'internazionalizzazione in JavaScript si è consolidata attorno a una convenzione difettosa: estrarre ogni stringa visibile all'utente in un file JSON, assegnarle una chiave e richiamare quella chiave nei componenti. t('home.hero.title') al posto del testo vero e proprio. L'interfaccia sta da una parte, i contenuti dall'altra.

Funziona. Migliaia di app vengono rilasciate così. Ma non è una grande esperienza per chi sviluppa.

Leggere t('checkout.summary.total') durante una code review non ti dice nulla: per capire cosa è cambiato devi aprire un file JSON. Le chiavi vanno inventate, organizzate in namespace e mantenute allineate. Le traduzioni obsolete si accumulano perché nessuno sa più quali chiavi siano ancora in uso. Il problema è talmente diffuso che esistono intere categorie di strumenti solo per gestirlo: estensioni IDE che suggeriscono automaticamente le chiavi, generatori di tipi che le validano, linter che segnalano quelle inutilizzate. Questi strumenti risolvono un problema creato da un paradigma progettato male.

Il componente <T>

Il contenuto non dovrebbe essere separato dal punto in cui viene usato. Un componente che visualizza un titolo, un paragrafo e un pulsante dovrebbe essere l'unica fonte di verità di ciò che mostrano quegli elementi, non un tramite che rimanda a stringhe archiviate altrove. Quando il codice e le traduzioni sono due sistemi paralleli, finiscono per disallinearsi. Inevitabilmente.

E se la libreria funzionasse al contrario, adattandosi al tuo codice invece di chiederti di riorganizzarlo? Ecco come dovrebbe essere l'i18n.

import { T } from 'gt-next';

function Hero() {
  return (
    <T>
      <h1>Ship your product worldwide</h1>
      <p>Reach every market without rewriting your app.</p>
    </T>
  );
}

Avvolgi il tuo JSX in <T>. Il testo in inglese resta esattamente dove lo hai scritto. Quando un utente visita il sito in spagnolo o in giapponese, il contenuto all'interno di <T> viene tradotto — struttura, formattazione e tutto il resto inclusi.

Nessuna chiave. Nessun file JSON. Nessun riferimento incrociato. L'unica fonte di verità è il tuo codice.

Setup

La sintassi mostrata sopra proviene da gt-next, una libreria i18n open source per Next.js App Router. Per iniziare ti basta un solo comando:

npx gt@latest init

La procedura guidata di setup installa le dipendenze, integra la configurazione di Next.js con withGTConfig, aggiunge GTProvider al layout principale, crea un file gt.config.json con le tue impostazioni regionali, configura le chiavi API di sviluppo per l'hot reloading delle traduzioni e imposta l'archiviazione delle traduzioni sulla CDN, il tutto in modo interattivo.

Una volta completato, racchiudi i contenuti in <T>, avvia il server di sviluppo e usa il componente <LocaleSelector> per passare da una lingua all'altra:

import { LocaleSelector } from 'gt-next';

function Header() {
  return (
    <header>
      <nav>{/* ... */}</nav>
      <LocaleSelector />
    </header>
  );
}

Le traduzioni avvengono su richiesta in fase di sviluppo, così puoi vedere subito la tua app in qualsiasi lingua.

Deployment

In produzione, le traduzioni vengono pregenerate.

  1. Ottieni una chiave API di produzione da dash.generaltranslation.com. Le chiavi di produzione iniziano con gtx-api- (a differenza delle chiavi gtx-dev- usate in locale).

  2. Aggiungi il passaggio translate al processo di build:

{
  "scripts": {
    "build": "npx gt translate --publish && next build"
  }
}

Il comando translate analizza la codebase per individuare tutti gli utilizzi di <T>, genera le traduzioni e le pubblica su una CDN. Quando l'app viene compilata, ogni impostazione regionale è pronta.

Passaggi successivi