Centro Assistenza

Localizzazione Flutter: File ARB, Intl e Automazione

Il sistema di localizzazione integrato di Flutter utilizza file Application Resource Bundle (ARB) e il pacchetto intl per offrire esperienze completamente native in qualsiasi lingua. Questa guida copre tutto, dalla configurazione del progetto e i dettagli del formato ARB al cambio lingua, la pluralizzazione e l’automazione delle traduzioni con l10n.dev.

Cos’è la Localizzazione Flutter?

La localizzazione Flutter è l’approccio ufficiale per adattare la tua app a più lingue e regioni. Si basa su file ARB per memorizzare le stringhe tradotte e sul generatore di codice flutter_gen per produrre accessor Dart type-safe. A runtime, Flutter seleziona il file ARB corretto in base alla localizzazione del dispositivo - senza bisogno di riavviare quando si cambia la lingua programmaticamente.

Configurazione del Progetto

La pipeline di localizzazione di Flutter è guidata da due file di configurazione: pubspec.yaml e l10n.yaml. Abilita la generazione del codice in pubspec.yaml e indica a Flutter la directory dei file ARB.

1. Aggiorna pubspec.yaml

Aggiungi flutter_localizations e intl come dipendenze, quindi abilita il flag generate affinché Flutter generi automaticamente le classi Dart di localizzazione dai tuoi file ARB.

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any

flutter:
  generate: true

2. Crea l10n.yaml

Posiziona un file l10n.yaml nella root del progetto per configurare la directory ARB, il file template e il nome del file di output generato.

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

Il Formato del File ARB

ARB (Application Resource Bundle) è un formato basato su JSON progettato specificamente per l’internazionalizzazione Flutter. Ogni chiave mappa a una stringa traducibile, e le chiavi di metadati opzionali (prefissate con @) contengono descrizioni, definizioni di segnaposto e contesto per i traduttori.

  • @@locale: Dichiara la localizzazione del file (es. "en", "fr", "zh_CN"). l10n.dev aggiorna automaticamente questo valore con il codice della lingua di destinazione.
  • @@last_modified: Timestamp dell’ultima modifica. l10n.dev imposta automaticamente questo valore con il timestamp UTC corrente durante la generazione dei file tradotti.
  • Metadati @key: Voci di metadati come description, example e placeholders NON sono tradotte di default - rimangono inalterate per preservare il contesto ai traduttori. Abilita l’impostazione translateMetadata se vuoi tradurle.
  • Segnaposto e messaggi ICU: Le stringhe possono contenere segnaposto nominati ({name}) e sintassi messaggi ICU per pluralizzazione e selezione - tutti correttamente preservati durante la traduzione.

File ARB sorgente (Inglese)

{
  "@@locale": "en",
  "@@last_modified": "2026-01-15T10:30:00Z",

  "appTitle": "My App",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Welcome, {name}!",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{No unread messages} =1{1 unread message} other{{count} unread messages}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

File ARB tradotto (Francese)

Dopo la traduzione, le stringhe UI sono localizzate mentre la struttura dei metadati resta intatta. l10n.dev aggiorna automaticamente @@locale e @@last_modified.

{
  "@@locale": "fr",
  "@@last_modified": "2026-01-15T10:30:01Z",

  "appTitle": "Mon Application",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Bienvenue, {name} !",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{Aucun message non lu} =1{1 message non lu} other{{count} messages non lus}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

Convenzioni di Nomenclatura dei File

I file ARB seguono un modello di denominazione semplice: un prefisso (di default app_) seguito dal codice locale e dall’estensione .arb. Flutter e l10n.dev usano underscore per separare codici lingua e regione.

I file ARB usano underscore, non trattini - scrivi app_en_US.arb e app_zh_CN.arb, non app_en-US.arb o app_zh-CN.arb.
# Default pattern (recommended)
app_en.arb
app_fr.arb
app_en_US.arb          # Locale with region (underscore format)
app_zh_CN.arb          # Chinese Simplified

# Custom prefix patterns also supported
my_app_en.arb
my_app_fr.arb

# Note: ARB files use underscores, not hyphens
# ✓  app_en_US.arb
# ✗  app_en-US.arb

Struttura del Progetto

Organizza tutti i tuoi file ARB dentro una cartella dedicata l10n all’interno di lib/. Il generatore di codice di Flutter li rileva automaticamente basandosi sul parametro arb-dir in l10n.yaml e produce classi Dart pronte all’uso.

lib/
├── l10n/
│   ├── app_en.arb        ← Source (English)
│   ├── app_fr.arb        ← French
│   ├── app_de.arb        ← German
│   ├── app_ja.arb        ← Japanese
│   ├── app_zh_CN.arb     ← Chinese Simplified
│   └── app_es.arb        ← Spanish
├── main.dart
└── ...

# Generated output (do not edit manually)
.dart_tool/
└── flutter_gen/
    └── gen_l10n/
        └── app_localizations.dart

Inizializzazione

Collega la classe Dart di localizzazione generata con MaterialApp fornendo localizationsDelegates e supportedLocales. Flutter risolverà così i dati ARB corretti per la localizzazione del dispositivo.

Configurazione MaterialApp

Passa i quattro delegati richiesti - il tuo AppLocalizations.delegate generato più i tre delegati del Flutter SDK - e elenca tutte le localizzazioni supportate dalla tua app. Usa AppLocalizations.of(context)! ovunque nell’albero dei widget per accedere alle stringhe tradotte.

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',

      // Required delegates
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],

      // Supported locales
      supportedLocales: AppLocalizations.supportedLocales,

      home: const HomePage(),
    );
  }
}

// Use in a widget
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;

    return Scaffold(
      appBar: AppBar(title: Text(l10n.appTitle)),
      body: Center(child: Text(l10n.welcome('Alice'))),
    );
  }
}

Cambio Lingua a Runtime

Flutter permette di cambiare la localizzazione dell’app a runtime aggiornando la proprietà locale di MaterialApp. Un modello comune è mantenere un Locale in uno StatefulWidget o in una soluzione di state management ed esporre una callback per modificarlo. L’albero dei widget si ricostruisce automaticamente con la nuova localizzazione.

// Manage locale state at the app level
class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Locale _locale = const Locale('en');

  void _changeLocale(Locale locale) {
    setState(() => _locale = locale);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      locale: _locale,
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: AppLocalizations.supportedLocales,
      home: SettingsPage(onLocaleChange: _changeLocale),
    );
  }
}

// Language selector widget
class LanguageSelector extends StatelessWidget {
  final void Function(Locale) onLocaleChange;

  const LanguageSelector({super.key, required this.onLocaleChange});

  @override
  Widget build(BuildContext context) {
    return DropdownButton<Locale>(
      value: Localizations.localeOf(context),
      items: AppLocalizations.supportedLocales
          .map((locale) => DropdownMenuItem(
                value: locale,
                child: Text(locale.toLanguageTag()),
              ))
          .toList(),
      onChanged: (locale) {
        if (locale != null) onLocaleChange(locale);
      },
    );
  }
}

Pluralizzazione

Flutter usa la sintassi messaggi ICU per la pluralizzazione all’interno dei file ARB. Il pacchetto intl gestisce tutte le categorie plurali CLDR, applicando automaticamente la forma corretta in base alle regole della lingua di destinazione.

  • Usa la sintassi {count, plural, =0{...} =1{...} other{...}} all’interno dei valori stringa ARB.
  • Dichiara il segnaposto count di tipo int nei metadati @key.
  • l10n.dev genera tutte le forme plurali richieste per ogni lingua di destinazione - incluse lingue complesse come arabo, russo e polacco - senza intervento manuale.
{
  "cartItems": "{count, plural, =0{Your cart is empty} =1{1 item in your cart} other{{count} items in your cart}}",
  "@cartItems": {
    "description": "Cart item count",
    "placeholders": {
      "count": { "type": "int" }
    }
  },

  "daysLeft": "{days, plural, =1{1 day left} other{{days} days left}}",
  "@daysLeft": {
    "description": "Days remaining",
    "placeholders": {
      "days": { "type": "int" }
    }
  }
}

Supporto Completo ARB in l10n.dev

l10n.dev è progettato per integrarsi perfettamente con il flusso di lavoro ARB di Flutter. Carica il tuo file ARB sorgente e ricevi traduzioni accurate e strutturate correttamente:

  • Aggiornamenti Automatici dei Metadati: @@locale viene aggiornato con il codice lingua di destinazione e @@last_modified impostato automaticamente al timestamp UTC corrente.
  • Controllo della Traduzione dei Metadati: Di default, le voci di metadati @key (description, example, context) NON sono tradotte e rimangono invariate, mantenendo intatte le note per i traduttori. Abilita translateMetadata per tradurle insieme alle stringhe UI.
  • Prefissi Personalizzati per i File: Qualsiasi schema di denominazione è supportato - app_en.arb, my_app_en_US.arb, strings_fr.arb e altri.
  • Formato Locale con Underscore: I codici locale ARB usano underscore (en_US, zh_CN) invece di trattini - l10n.dev gestisce correttamente questo aspetto così i file generati si integrano direttamente nel progetto Flutter.
  • Consapevolezza della Pluralizzazione: Le forme plurali ICU sono generate per ogni lingua di destinazione secondo le regole CLDR, quindi non serve modificare manualmente i plurali dopo la traduzione.

Automatizza le Traduzioni con npm

Usa il pacchetto npm ai-l10n per tradurre il tuo file ARB sorgente da linea di comando o come parte di una pipeline CI/CD. Installa una volta, poi traduci in qualsiasi numero di lingue con un solo comando.

# Install the CLI
npm install ai-l10n

# Translate your source ARB to multiple languages
npx ai-l10n translate lib/l10n/app_en.arb \
  --languages fr,de,ja,zh_CN,es,ko

Integrazione in una build di Flutter

Puoi integrare ai-l10n direttamente nel processo di build di Flutter in modo che le traduzioni siano sempre aggiornate prima che l'app venga compilata. Due approcci comuni sono uno script package.json o un Makefile.

Tramite script package.json

Aggiungi uno script di traduzione e usa l'hook del ciclo di vita prebuild di npm per eseguirlo automaticamente prima di ogni build. Esegui npm run build:android (o build:ios / build:web) e ai-l10n tradurrà per primo, per poi passare il controllo a Flutter.

{
  "scripts": {
    "translate": "ai-l10n translate lib/l10n/app_en.arb --languages fr,de,ja,zh_CN,es,ko --update",
    "prebuild": "npm run translate",
    "build:android": "flutter build apk",
    "build:ios": "flutter build ios",
    "build:web": "flutter build web"
  }
}

Tramite Makefile

Se il tuo team usa Make, dichiara un target di traduzione e rendi ogni target di build dipendente da esso. L'esecuzione di make build-android (o build-ios / build-all) tradurrà tutte le lingue di destinazione prima di richiamare flutter build.

LANGUAGES = fr,de,ja,zh_CN,es,ko

translate:
	npx ai-l10n translate lib/l10n/app_en.arb --languages $(LANGUAGES) --update

build-android: translate
	flutter build apk

build-ios: translate
	flutter build ios

build-web: translate
	flutter build web

build-all: translate
	flutter build apk
	flutter build ios
	flutter build web

Per integrazione CI/CD, aggiornamenti incrementali, traduzione batch su più file ed esempi di workflow GitHub Actions, consulta la Guida all’Automazione della Localizzazione.

Estensione VS Code

L’estensione l10n.dev per VS Code porta la traduzione Flutter ARB direttamente nel tuo editor. Clicca col tasto destro su un file ARB e traducilo nelle lingue di destinazione senza uscire da VS Code.

Come Funziona in VS Code:

  1. Apri il file ARB sorgente (es. app_en.arb) nell’editor.
  2. Clicca col tasto destro nell’editor e seleziona "Translate JSON".
  3. Scegli una o più lingue di destinazione (es. francese, giapponese, tedesco).
  4. L’estensione crea file ARB localizzati accanto al sorgente, aggiornando automaticamente @@locale e @@last_modified.

Vedi in Azione

Ecco un esempio live di traduzione di un file Flutter ARB in uzbeko dentro VS Code:

Flutter ARB localization in VS Code

Inizia a Localizzare la Tua App Flutter

Pronto a raggiungere utenti globali? Puoi tradurre i file ARB direttamente nello spazio di lavoro l10n.dev, automatizzare con la CLI npm o tradurre direttamente dentro VS Code: