Che cos'è i18n?

L'internazionalizzazione (i18n) è il processo di progettazione del software in modo che possa essere adattato a diverse lingue e regioni senza modificare il codice. Il soprannome "i18n" deriva dal fatto che ci sono 18 lettere tra la "i" e la "n" nell'internazionalizzazione.

Pensa a i18n come a gettare le basi per:

  • Localizzazione (l10n): Tradurre e adattare i tuoi contenuti per un mercato specifico.
  • Globalizzazione (g11n): Coordinare la prontezza e le operazioni dei prodotti in tutti i mercati.

In pratica, i18n consiste nell'assicurarsi che la tua app sia in grado di gestire:

  • Testo in qualsiasi lingua
  • Date, orari, numeri e valute nel formato corretto
  • Regole di pluralizzazione che corrispondono alla grammatica locale
  • Layout da destra a sinistra (come l'arabo o l'ebraico)

 

Perché i18n è importante

Investire in i18n in anticipo porta vantaggi tangibili ai team di progettazione e di prodotto:

  • Costi di localizzazione inferiori: L'estrazione e la sostituzione delle stringhe è più semplice quando la logica di traduzione è integrata fin dall'inizio.
  • Sviluppo più rapido: L'infrastruttura condivisa per la gestione delle stringhe riduce le rielaborazioni future.
  • Migliore UX: Gli utenti visualizzano i contenuti nella loro lingua, formattati in modo naturale.
  • Scalabilità: Le app possono essere lanciate in nuovi mercati con meno modifiche al codice.

 

Modelli di implementazione i18n nelle applicazioni moderne

Di seguito sono riportati alcuni modelli comuni per l'implementazione di i18n nelle app di produzione. Esamineremo React (frontend), iOS e Android.

Indipendentemente dalla piattaforma, le traduzioni di solito provengono da un sistema di gestione delle traduzioni (TMS) come Smartling come JSON o file di risorse. Questi file vengono quindi caricati dall'app in fase di esecuzione tramite un framework i18n o un'API di localizzazione nativa, garantendo che vengano visualizzate le stringhe corrette per la lingua o le impostazioni locali dell'utente.

 

Frontend (Reagisci)

Le moderne app React utilizzano in genere una libreria i18n dedicata. Due dei più popolari sono i18next e FormatJS, entrambi indipendenti dal framework. In React, le rispettive implementazioni sono react-i18next (basato su funzioni e hook) e react-intl (basato su componenti e hook, costruito su ICU MessageFormat). Entrambi si integrano perfettamente con le pipeline aziendali e gestiscono la pluralizzazione, le variabili e la formattazione in base alle impostazioni locali.

 

1. Reagisci con i18next + react-i18next

i18next è una delle librerie JavaScript i18n più popolari e, se abbinata ai binding react-i18next , fornisce alle app React un'API potente e facile da usare per il caricamento e il rendering delle traduzioni.

Nell'esempio seguente, esamineremo un modello i18n aziendale comune. Definiremo i file di traduzione, inizializzeremo i18next nel punto di ingresso dell'app e quindi eseguiremo il rendering delle traduzioni nei componenti. Questo approccio funziona in tutti i framework, si integra perfettamente con la maggior parte dei sistemi di gestione delle traduzioni (TMS) e si adatta perfettamente alla crescita dell'app, indipendentemente dal fatto che si visualizzino stringhe statiche o messaggi dinamici basati su variabili come counts.

 

Esempio di modello i18n: i18next + reacti18next

Probabilmente riceverai i contenuti come file JSON dal tuo sistema di gestione delle traduzioni. L'esempio di file JSON riportato di seguito mostra come vengono archiviate le traduzioni per l'inglese. Ogni voce ha una chiave univoca e le forme plurali sono definite separatamente in modo che la biblioteca possa scegliere quella giusta in base al conteggio che superi. Il TMS genererà un file corrispondente per ogni lingua supportata.

 

{

  "welcome": "Welcome",

  "visits_one": "Hai visitato {{count}} time.",

  "visits_other": "Hai visitato {{count}} volte."

}

 

Successivamente, vedrai un esempio di come configurare i18next in modo che sappia quali lingue supporta la tua app, dove trovare le traduzioni e cosa fare se manca una traduzione. Questo file di installazione viene eseguito una sola volta all'avvio dell'app (spesso nel file del punto di ingresso come index.js o main.tsx) in modo che le traduzioni siano pronte prima del rendering dell'interfaccia utente. La centralizzazione della configurazione in un'unica posizione mantiene la logica di localizzazione coerente in tutta l'app.

 

importare i18next da 'i18next';

import { initReactI18next } da 'react-i18next';

import en from './locales/en/translation.json';

importa fr da './locales/fr/translation.json';

 

const locale = 'fr'; in produzione, risolvi dinamicamente

 

i18successivo

  .use(initReactI18next)

  .init({

    lng: locale,

    fallbackLng: 'en',

    Risorse: {

      en: { translation: en },

      fr: { traduzione: fr }

    },

    interpolazione: { escapeValue: false }

  });

 

esportazione predefinita i18next;

 

Una volta inizializzato i18next, puoi usarlo ovunque nella tua app. Nell'esempio seguente, l'hook useTranslation recupera la funzione t , che accetta una chiave e variabili facoltative per eseguire il rendering della stringa corretta. Quando si passa count come variabile, i18next seleziona automaticamente la forma plurale corretta in base al file di traduzione.

 

import { useTranslation } da 'react-i18next';

import './i18n';

 

esporta la funzione predefinita App() {

  const { t } = useTranslation();

  conteggio const = 3;

 

  ritorno (

    <>

      <h1>{t('welcome')}</h1>

      <p>{t('visite', { conteggio })}</p>

    </>

  );

}

 

2. Reagisci con FOrmatJS + react-intl

react-intl fa parte dell'ecosistema FormatJS e fornisce un approccio basato su componenti a i18n in React. È basato sullo standard ICU MessageFormat, quindi ottieni la pluralizzazione incorporata, la formattazione di data/numero e il fallback delle impostazioni locali.

Nell'esempio seguente verranno configurati i file di traduzione, verrà eseguito il wrapping dell'app in un IntlProvider e verrà eseguito il rendering del testo localizzato usando FormattedMessage. Questo approccio è adatto per i team che desiderano uno stile dichiarativo e basato sui componenti per la gestione di i18n in React.

 

Esempio di modello i18n: FormatJS + react-intl

Il file JSON seguente contiene traduzioni utilizzando la sintassi ICU MessageFormat, che inserisce la logica plurale all'interno della stringa stessa. In questo modo tutte le regole della lingua vengono mantenute in un unico posto e i traduttori possono controllare completamente la grammatica senza l'intervento dello sviluppatore. Il TMS gestisce questi file per impostazione locale.

 

{

  "welcome": "Welcome",

{% raw %} "visite": "Hai visitato {count, plural, one {# time} other {# times}."{% end_raw %}

Successivamente, verrà visualizzato un esempio di wrapping dell'app nel componente IntlProvider . Si tratta di una configurazione una tantum, solitamente eseguita in un componente root come Root.tsx o index.jsx. Rende disponibili le impostazioni locali attive e i relativi messaggi in tutta l'app in modo che qualsiasi componente possa utilizzarli senza importazioni aggiuntive.

 

import { IntlProvider } da 'react-intl';

import en from './locales/en.json';

importa fr da './locales/fr.json';

 

const MESSAGES = { en, fr };

const locale = 'fr';

 

funzione predefinita di esportazione Root() {

  ritorno (

    <IntlProvider locale={locale} messages={MESSAGES[locale]}>

      <App />

    </IntlProvider>

  );

}



Infine, leggi di seguito per vedere come il componente FormattedMessage cerca una traduzione in base al suo ID e gestisce automaticamente la pluralizzazione. Tutto ciò che devi passare è il conteggio e la libreria applica le regole di lingua corrette dal tuo file JSON.

 

import { FormattedMessage } da 'react-intl';

 

esporta la funzione predefinita App() {

  conteggio const = 3;

 

  ritorno (

    <>

      <h1><FormattedMessage id="welcome" defaultMessage="Welcome" /></h1>

      <p><FormattedMessage id="visits" values={{ count }} /></p>

    </>

  );

}

 

Alcuni suggerimenti aggiuntivi per l'uso in produzione:

  • Fonte locale: Nelle app reali, determina le impostazioni locali centralmente (ad esempio, da un URL come /fr/*, dal profilo dell'utente o da un'impostazione fornita dal server) e passale a <IntlProvider>.
  • Organizzazione dei messaggi: Per scalabilità, suddividere i file dei messaggi in base al dominio o alla funzionalità (ad esempio, auth.json, dashboard.json) e unirli per la localizzazione attiva.
  • Operazioni di ripiego: defaultMessage è la tua rete di sicurezza durante l'implementazione: mantienilo nella tua lingua di origine.
  • Caricamento asincrono (opzionale): Per i bundle di grandi dimensioni, importare dinamicamente i file dei messaggi in base alle impostazioni locali (suddivisione del codice) prima di eseguire il rendering <IntlProvider>.



Ios

iOS offre solidi strumenti di localizzazione pronti all'uso, ma la scalabilità pulita in molte impostazioni locali richiede un'implementazione ponderata delle best practice i18n. In caso contrario, senza una struttura chiara, ci si può ritrovare con chiavi duplicate, formattazione incoerente e file di traduzione che diventano un problema da mantenere. La chiave è prendere alcune decisioni strutturali in anticipo, in modo che la localizzazione rimanga organizzata e facile da estendere man mano che vengono aggiunti nuovi mercati.

 

Suggerimento 1: organizzare le risorse in modo scalabile

Un buon punto di partenza è con i cataloghi di stringhe (.xcstrings) in Xcode 15 e versioni successive o .strings/.stringsdict file se utilizzi una configurazione precedente. Questi funzionano bene con un TMS, che di solito ti invierà traduzioni in formato XLIFF. Puoi importarli direttamente nel tuo catalogo e il sistema gestirà il lavoro pesante di unione e gestione.

Probabilmente troverai più facile mantenere le cose in ordine se organizzi i cataloghi per funzionalità o modulo. I file più piccoli e mirati semplificano la ricerca delle chiavi, la revisione delle modifiche e il passaggio del lavoro ai traduttori. Ecco un esempio di come potresti volerli organizzare:

 

Risorse

  i18n/

    Auth.xcstrings

    Checkout.xcstrings

    Profilo.xcstrings



Suggerimento 2: gestire la pluralizzazione nel catalogo, non nel codice

La pluralizzazione è un altro punto in cui la struttura paga. È meglio definire tutte le regole plurali nel catalogo invece che in Swift, in modo che il codice passi solo le variabili e la frase corretta venga scelta automaticamente per ogni lingua. Ecco come potrebbe apparire nel catalogo:

 

Chiave: unread_messages

Formato: Plurale

Uno: "%d messaggio non letto"

Altro: "%d messaggi non letti"

 

Ed ecco come potresti usarlo in Swift:

 

let unreadCount = 3

let format = String(localizzato: "unread_messages")

let message = String.localizedStringWithFormat(format, unreadCount)

"3 messaggi non letti"

 

In questo modo, non si codifica la grammatica nel codice e i traduttori possono ottenere i dettagli corretti per ogni lingua.

 

Suggerimento 3: centralizza la formattazione di numeri, date e valute

Ti consigliamo anche di centralizzare la formattazione di numeri, date e valute in modo che ogni parte dell'app sia coerente. Un'utilità o un servizio condiviso può aiutare in questo. Ecco un semplice esempio che utilizza la moderna API FormatStyle di Swift:

 

prezzo let = 19.99

let display = price.formatted(.currency(codice: "EUR"))

"19,99 €" o "19,99 €" a seconda della località

 

Mantenendo organizzate le risorse stringa, gestendo la pluralizzazione nel catalogo e centralizzando tutta la formattazione sensibile alle impostazioni locali, è possibile configurare l'app iOS per la crescita senza creare ulteriore lavoro di manutenzione. Una volta che queste pratiche sono in atto, il processo per l'aggiunta di nuove lingue diventa molto più prevedibile e molto meno stressante. Ora diamo un'occhiata ad Android, che offre i propri strumenti di localizzazione integrati.

 

Android

Il sistema di risorse di Android è già stato progettato pensando alla localizzazione, ma mantenerlo gestibile in molte lingue richiede un po' di pianificazione. Se si conserva tutto in un unico file di grandi dimensioni o si disperdono le regole grammaticali nel codice, il problema può diventare rapidamente complicato. Invece, dai la priorità all'organizzazione segmentata dei file, definisci tutte le regole grammaticali in XML e assicurati che la formattazione e i layout funzionino per ogni sistema di scrittura che prevedi di supportare.

 

Suggerimento 1: mantieni le risorse organizzate in base alla funzionalità

Per la maggior parte dei team, le traduzioni provengono da un TMS come file XLIFF. Questi vengono importati nelle directory res/values per ogni impostazione locale e Android si occupa di abbinare le stringhe corrette alla lingua dell'utente.

Suddividere le risorse in file separati per funzionalità è un modo semplice per semplificare la vita. I file più piccoli rendono più rapida la revisione delle modifiche e aiutano a evitare conflitti di unione.

 

app/src/principale/res/

  values/strings_auth.xml

  values/strings_checkout.xml

  values/plurals_checkout.xml

 

Suggerimento 2: Definire le regole grammaticali nelle risorse, non nel codice

Come in iOS, la pluralizzazione è una di quelle cose che è meglio gestire nelle risorse in modo che i traduttori possano adattarla in base alla lingua senza che tu modifichi il codice. Ecco un esempio di risorsa plurale in inglese:

 

<plurals name="checkout_cart_items_count">

    <item quantity="one">%1$d item</item>

    <item quantity="altro">%1$d articoli</item>

</plurals>

 

Ed ecco come lo useresti in Kotlin:

 

val msg = resources.getQuantityString(

    R.plurals.checkout_cart_items_count, contare, contare

)

 

In questo modo, il nostro codice rimane pulito e Android sceglie automaticamente il modulo corretto in base alle impostazioni locali.

 

Suggerimento 3: utilizzare la formattazione in base alle impostazioni locali 

Per i layout, è buona abitudine usare l'inizio e la fine invece di sinistra e destra , in modo che si adattino alle lingue da destra a sinistra come l'arabo o l'ebraico:

 

<LinearLayout

    android:paddingStart="16dp"

    android:paddingEnd="16dp"

    android:layout_width="match_parent"

    android:layout_height="wrap_content">

</LinearLayout>

 

E quando formatti numeri o valute, passa le impostazioni locali correnti dell'app in modo che tutto appaia coerente:

 

val appLocale = LocaleListCompat.getAdjustedDefault()[0] ?: Locale.getDefault()

val price = NumberFormat.getCurrencyInstance(appLocale).format(1234.56)

"$ 1.234,56" oppure "1 234,56 €"

 

Alla fine, ottenere Android i18n nel modo giusto significa principalmente lasciare che la piattaforma faccia il lavoro pesante. Mantenendo tutto il testo nelle risorse, strutturando tali risorse con cartelle specifiche per le impostazioni locali e creando una formattazione RTL e compatibile con le impostazioni locali fin dal primo giorno, si evitano le trappole comuni che rendono fragile la localizzazione. Molti di questi principi riecheggiano le best practice di iOS, ma il sistema di qualificazione delle risorse di Android significa che spesso puoi supportare nuove lingue semplicemente aggiungendo i file giusti. Se fatto bene, il ridimensionamento a nuove impostazioni locali diventa un processo prevedibile e a basso sforzo.

 

Insidie comuni i18n

Purtroppo, anche i sistemi ben costruiti a volte si imbattono in problemi evitabili. La tabella seguente evidenzia alcuni dei passi falsi più comuni, perché causano problemi e come prevenirli. Considera questo un riferimento rapido che puoi utilizzare per controllare la tua configurazione prima della spedizione.

 

Errore

Come evitarlo

Stringhe hardcoded

Estrai tutto il testo rivolto all'utente in file di risorse o chiavi di traduzione.

Supponendo che tutto il testo sia da sinistra a destra

Testa i layout con lingue da destra a sinistra come l'arabo o l'ebraico.

Trascurare la pluralizzazione

Utilizzare librerie che supportano regole plurali (ad esempio, il formato ICU, i18next).

Unità o formati non localizzati

Utilizzare la formattazione compatibile con le impostazioni locali (ad esempio, Intl.NumberFormat, Intl.DateTimeFormat).

Saltare i controlli di espansione del testo

Esegui test con pseudo-impostazioni locali per simulare traduzioni più lunghe.

Estrazione incompleta delle stringhe

Utilizzare pseudo-impostazioni locali nella gestione temporanea per visualizzare le stringhe mancanti o senza tag.

 

 

Preparazione per la localizzazione su larga scala

Una volta configurata l'app per l'internazionalizzazione, il passaggio successivo consiste nel rendere la localizzazione il più efficiente e richiesta manutenzione possibile. Alcuni strumenti di automazione e flussi di lavoro possono portarti da "possiamo tradurre" a "possiamo implementare rapidamente nuove lingue, senza ulteriore carico di sviluppo". Considerare:

  • Utilizzo di un sistema di gestione delle traduzioni (TMS) con un'API di livello aziendale, come Smartling, per sincronizzare i file di traduzione e gestire i flussi di lavoro di revisione.
  • Automazione dell'estrazione e della distribuzione delle stringhe utilizzando la pipeline CI/CD.
  • Utilizzo di strumenti di intelligenza artificiale (come l'AI Hub di Smartling) per traduzioni rapide al primo passaggio con controlli di qualità integrati come la gestione del fallback e la mitigazione delle allucinazioni.

 

Pensieri finali

L'internazionalizzazione è una pratica fondamentale per qualsiasi prodotto che diventa globale e prima la si implementa, meno problemi si avranno in seguito. Combinando solide pratiche i18n con l'automazione della traduzione e i flussi di lavoro di test, il vostro team sarà ben attrezzato per distribuire software pronto per l'uso internazionale in modo più rapido e sicuro.

Vuoi approfondire? Dai un'occhiata a Smartling's Webinar della Global Ready Conference su i18n nell'era dell'intelligenza artificiale.

Perché aspettare per tradurre in modo più intelligente?

Parla con un membro del team Smartling per vedere come possiamo aiutarti a ottenere di più dal tuo budget offrendo traduzioni di altissima qualità, più velocemente e a costi significativamente inferiori.
Cta-Card-Side-Image