Indietro

Stai sbagliando l'i18n in Next.js

General Translation avatarGeneral Translation
Ernest McCarter avatarErnest McCarter
guideinternationalizationnextjsi18ngt-nextapp-routertutorial

L'internazionalizzazione in JavaScript si è assestata su una convenzione difettosa: estrarre ogni stringa visibile all'utente in un file JSON, assegnarle una chiave e usare quella chiave nei componenti. t('home.hero.title') invece del testo stesso. La tua UI vive in un luogo, il tuo contenuto in un altro.

Funziona. Migliaia di app vengono distribuite così. Ma non offre una buona developer experience.

Leggere t('checkout.summary.total') in una code review non ti dice nulla: devi aprire un file JSON per vedere cosa è cambiato. Le chiavi devono essere inventate, organizzate in namespace e mantenute sincronizzate. Le traduzioni obsolete si accumulano perché nessuno sa più quali chiavi sono ancora in uso. Il problema è talmente diffuso che intere categorie di strumenti esistono solo per gestirlo: estensioni per IDE che suggeriscono automaticamente le chiavi, generatori di tipi che le validano, linter che segnalano quelle inutilizzate. Questi strumenti stanno risolvendo 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 renderizza un titolo, un paragrafo e un pulsante dovrebbe essere l’unica fonte di verità per ciò che questi elementi dicono, non un proxy che punta a stringhe archiviate altrove. Quando il tuo codice e le tue traduzioni sono due sistemi paralleli, finiscono per divergere. Inevitabilmente.

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

import { T } from 'gt-next';

function Hero() {
  return (
    <T>
      <h1>Porta il tuo prodotto in tutto il mondo</h1>
      <p>Raggiungi ogni mercato senza riscrivere la tua applicazione.</p>
    </T>
  );
}

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

Niente chiavi. Niente file JSON. Niente riferimenti incrociati. L'unica fonte di verità è il tuo codice.

Configurazione

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

npx gtx-cli@latest init

La procedura guidata di configurazione installa le dipendenze, integra la configurazione Next.js con withGTConfig, aggiunge GTProvider al layout radice, crea un file gt.config.json con i tuoi locale (lingue), configura le chiavi API di sviluppo per l’hot reloading delle traduzioni e imposta l’archiviazione delle traduzioni su una Rete per la distribuzione dei contenuti (Content Delivery Network, CDN), il tutto in modo interattivo.

Una volta fatto questo, racchiudi il contenuto 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 vengono eseguite su richiesta in fase di sviluppo, così puoi vedere immediatamente la tua app in qualsiasi lingua.

Distribuzione

In produzione, le traduzioni vengono generate in anticipo.

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

  2. Aggiungi il passaggio di traduzione alla build:

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

Il comando translate analizza la codebase del tuo progetto alla ricerca di tutti i punti in cui viene utilizzato <T>, genera le traduzioni e le pubblica su una rete per la distribuzione dei contenuti (Content Delivery Network, CDN). Quando compili la tua app, ogni locale è pronto.

Prossimi passi