Skip to main content

La guida completa alla localizzazione di Flutter

Dai file ARB al supporto RTL: localizzi l'app Flutter con easy_localization, gestisca i plurali per ogni lingua e automatizzi le traduzioni con l'IA.

1

Installare easy_localization

Aggiunga il pacchetto easy_localization al file pubspec.yaml. È il pacchetto i18n per Flutter più diffuso, con supporto dei file ARB/JSON, dei plurali e delle estensioni del contesto. Aggiunga inoltre flutter_localizations dall'SDK per formattare date, numeri e direzione del testo in base alla lingua.

easy_localization offre estensioni del contesto come context.tr() e 'key'.tr() per accedere in modo conciso alle traduzioni. Gestisce il caricamento e la persistenza delle lingue, oltre all'hot reload dei file di traduzione durante lo sviluppo.
pubspec.yaml
dependencies:
  easy_localization: ^3.0.7
  flutter_localizations:
    sdk: flutter
2

Creare file di traduzione ARB

I file Application Resource Bundle (ARB) sono il formato di localizzazione standard per Flutter. Ogni file contiene coppie chiave-valore e metadati facoltativi che descrivono segnaposto, regole del plurale e contesto per i traduttori. Crei un file per ogni lingua nella directory assets/translations.

assets/translations/en.arb
{
  "@@locale": "en",
  "appTitle": "My App",
  "@appTitle": {
    "description": "The title of the application"
  },
  "greeting": "Hello, {name}!",
  "@greeting": {
    "description": "Greeting with user name",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },
  "itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}",
  "@itemCount": {
    "description": "Number of items in the cart",
    "placeholders": {
      "count": {
        "type": "num",
        "format": "compact"
      }
    }
  }
}
Le chiavi con prefisso @, come @greeting, sono metadati: descrivono la stringa precedente. Includa tipi ed esempi dei segnaposto per aiutare i traduttori a produrre traduzioni accurate. Queste chiavi di metadati vengono eliminate durante l'esecuzione e non comportano alcun sovraccarico.
3

Configurare l'app

Racchiuda l'app con il widget EasyLocalization. Gestisce lo stato della lingua, carica le traduzioni dai file di risorse e fornisce i delegati necessari a MaterialApp. Le tre proprietà delegate obbligatorie sono localizationsDelegates, supportedLocales e locale, tutte disponibili tramite le estensioni del contesto.

lib/main.dart
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyLocalization.ensureInitialized();

  runApp(
    EasyLocalization(
      supportedLocales: [
        Locale('en'),
        Locale('ar'),
        Locale('ja'),
        Locale('de'),
      ],
      path: 'assets/translations',  // Path to your ARB/JSON files
      fallbackLocale: Locale('en'),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      home: HomePage(),
    );
  }
}
"Easy Localization not initialized": questo errore indica che non è stato chiamato EasyLocalization.ensureInitialized() prima di runApp(). La chiamata deve essere attesa dopo WidgetsFlutterBinding.ensureInitialized() e prima di runApp().
4

Tradurre i widget

Usi il metodo di estensione .tr() sulle chiavi stringa per ottenere testo tradotto in qualsiasi widget. Per i plurali, usi .plural() con il valore del conteggio. easy_localization offre sia la sintassi di estensione della stringa ('key'.tr()) sia quella del metodo di contesto (context.tr('key')).

lib/widgets/home_page.dart
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('appTitle'.tr()),   // Simple key
      ),
      body: Column(
        children: [
          // String with variable interpolation
          Text('greeting'.tr(args: ['Alice'])),

          // Named arguments
          Text('greeting'.tr(namedArgs: {'name': 'Alice'})),

          // Plural form
          Text('itemCount'.plural(3)),
        ],
      ),
    );
  }
}
Se le traduzioni restituiscono chiavi non elaborate anziché testo tradotto, controlli: 1) Il widget EasyLocalization racchiude MaterialApp, non il contrario. 2) I file di traduzione sono dichiarati in pubspec.yaml sotto assets. 3) Il percorso del file in EasyLocalization corrisponde alla struttura effettiva delle directory.
5

Gestire plurali e variabili

Flutter usa ICU MessageFormat per i plurali, lo stesso standard adottato da iOS, Android e dal web. Definisca le forme plurali con la sintassi {count, plural, ...} nei file ARB. Ogni lingua richiede un proprio insieme di forme basato sulle regole del plurale CLDR. L'arabo ha 6 forme, il russo 4 e il giapponese 1.

Plural forms by language
// English: 3 useful forms (=0, =1, other)
"itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}"

// Arabic: 6 forms (=0, =1, =2, few, many, other)
"itemCount": "{count, plural, =0{لا عناصر} =1{عنصر واحد} =2{عنصران} few{{count} عناصر} many{{count} عنصرًا} other{{count} عنصر}}"

// Japanese: 1 form (other)
"itemCount": "{count, plural, other{{count}個のアイテム}}"

// German: 2 forms (=1, other)
"itemCount": "{count, plural, =1{1 Artikel} other{{count} Artikel}}"

// Russian: 3 forms (one, few, many)
"itemCount": "{count, plural, =0{Нет товаров} one{{count} товар} few{{count} товара} many{{count} товаров} other{{count} товаров}}"
Variables and named arguments
// Simple variable
"welcome": "Welcome, {name}!"

// Multiple variables
"orderStatus": "Order #{orderId} — {status}"

// Variable in plural context
"unreadMessages": "{count, plural, =0{No unread messages} =1{1 unread message from {sender}} other{{count} unread messages}}"

// In widgets:
Text('welcome'.tr(namedArgs: {'name': userName}));
Text('orderStatus'.tr(namedArgs: {'orderId': '1234', 'status': 'Shipped'}));
Text('unreadMessages'.plural(count, namedArgs: {'sender': senderName}));
Non codifichi mai direttamente la logica singolare/plurale con if (count == 1). Lingue come il francese considerano 0 singolare. Russo, polacco e arabo hanno forme plurali completamente assenti in inglese. Usi sempre la sintassi plurale ICU e lasci che il framework selezioni la forma corretta.
6

Supportare le lingue RTL

Flutter rispecchia automaticamente l'intero layout quando la lingua procede da destra a sinistra (arabo, ebraico, persiano, urdu). Tuttavia, il codice deve usare widget e proprietà sensibili alla direzione affinché il rispecchiamento funzioni correttamente. Sostituisca left/right codificati direttamente con gli equivalenti start/end.

lib/widgets/adaptive_layout.dart
import 'package:flutter/material.dart';

class AdaptiveLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final isRtl = Directionality.of(context) == TextDirection.rtl;

    return Scaffold(
      body: Row(
        children: [
          // Use start/end instead of left/right
          Expanded(
            child: Padding(
              padding: EdgeInsetsDirectional.only(
                start: 16.0,  // Leading edge (left in LTR, right in RTL)
                end: 8.0,     // Trailing edge
              ),
              child: Text('content'.tr()),
            ),
          ),
          // Flip icons for RTL
          Icon(
            isRtl ? Icons.arrow_back : Icons.arrow_forward,
          ),
        ],
      ),
    );
  }
}
RTL-aware widget patterns
// Use Directional widgets for RTL-aware layouts
EdgeInsetsDirectional.only(start: 16, end: 8)   // Not EdgeInsets.only(left: 16, right: 8)
AlignmentDirectional.centerStart                  // Not Alignment.centerLeft
BorderRadiusDirectional.only(topStart: Radius.circular(8))

// Automatically mirrors when locale changes to Arabic, Hebrew, etc.
// No conditional logic needed — Flutter handles text direction from locale
Testi l'RTL impostando temporaneamente l'app in arabo (Locale('ar')). Flutter rispecchia l'intera interfaccia: i cassetti di navigazione si aprono da destra, le frecce indietro si invertono e il testo si allinea a destra. Usi EdgeInsetsDirectional, AlignmentDirectional e BorderRadiusDirectional per assicurarsi che i layout personalizzati vengano rispecchiati correttamente.
7

Catene di fallback intelligenti

Per impostazione predefinita, quando manca una traduzione pt-BR, Flutter passa direttamente all'inglese, ignorando traduzioni pt-PT perfettamente valide. Il pacchetto locale_chain risolve il problema con catene di fallback configurabili. Una riga di configurazione, senza migrazione: le chiamate .tr() esistenti continuano semplicemente a funzionare.

lib/main.dart with LocaleChain
import 'package:locale_chain/locale_chain.dart';
import 'package:locale_chain/easy_localization.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyLocalization.ensureInitialized();
  LocaleChain.configure();  // Enable smart fallback chains

  runApp(
    EasyLocalization(
      supportedLocales: [
        Locale('en'),
        Locale('pt', 'BR'),
        Locale('pt', 'PT'),
        Locale('es'),
        Locale('es', 'MX'),
      ],
      path: 'assets/translations',
      assetLoader: LocaleChainAssetLoader(  // Swap in the chain loader
        baseLoader: RootBundleAssetLoader(),
      ),
      fallbackLocale: Locale('en'),
      child: MyApp(),
    ),
  );
}

// Result: pt-BR user sees pt-PT translations when pt-BR keys are missing,
// instead of falling back directly to English.
Custom fallback configuration
// Override specific chains while keeping built-in defaults
LocaleChain.configure(
  fallbacks: {
    'pt-BR': ['pt-PT', 'pt'],      // pt-BR → pt-PT → pt → en
    'es-MX': ['es-419', 'es'],     // es-MX → es-419 → es → en
    'fr-CA': ['fr'],               // fr-CA → fr → en
  },
);

// Or replace all defaults with your own chains
LocaleChain.configure(
  fallbacks: {
    'zh-Hant-HK': ['zh-Hant-TW', 'zh-Hans'],
    'pt-BR': ['pt-PT', 'pt'],
  },
  mergeDefaults: false,  // Only your chains, no built-in defaults
);
locale_chain include catene di fallback integrate per le varianti regionali di portoghese, spagnolo, francese, tedesco, italiano, olandese, norvegese e malese. Un utente pt-BR vedrà i contenuti pt-PT prima dell'inglese. Un utente es-MX vedrà prima es-419 e poi es, prima della lingua predefinita.
8

Automatizzare le traduzioni

Dopo aver completato la configurazione della localizzazione, traduca i file ARB con l'IA. Nell'IDE, chieda all'assistente IA di tradurre il file ARB di origine oppure usi la CLI di i18n Agent nella pipeline CI/CD. I metadati ARB, come segnaposto e descrizioni, forniscono un contesto che migliora la qualità della traduzione.

Terminal
# In your IDE, ask your AI assistant:
> Translate assets/translations/en.arb to Arabic, Japanese, and German

✓ ar.arb created (1.4s)
✓ ja.arb created (1.2s)
✓ de.arb created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate assets/translations/en.arb --lang ar,ja,de
Traduca in modo incrementale: quando aggiunge nuove chiavi al file ARB di origine, traduca soltanto il diff anziché rigenerare tutti i file. In questo modo preserva le traduzioni revisionate da persone e mantiene intatti i metadati ARB.

Automatizzare la qualità

Con i18n-validate, rilevi chiavi mancanti e segnaposto non validi prima del rilascio. Testi l'interfaccia con le pseudotraduzioni di i18n-pseudo prima che arrivino le traduzioni reali.

Problemi comuni

File di traduzione non trovati durante l'esecuzione

I file ARB/JSON devono essere dichiarati in pubspec.yaml nella sezione assets. Se omette questo passaggio, Flutter non trova i file durante l'esecuzione anche se sono presenti sul disco. Aggiunga: assets: - assets/translations/

Sintassi del file ARB non valida

I file ARB sono JSON rigorosi: niente virgole finali, virgolette singole o commenti. Un solo errore di sintassi impedisce il caricamento dell'intero file senza alcuna segnalazione. Convalidi i file ARB con un linter JSON prima di analizzare i problemi di traduzione.

Le modifiche alle traduzioni non appaiono con l'hot reload

easy_localization memorizza le traduzioni nella cache. Per applicare nuove chiavi o modifiche alle traduzioni esistenti potrebbe servire un hot restart completo, non un semplice hot reload. Durante lo sviluppo, usi l'hot restart (Shift+R) dopo aver modificato i file di traduzione.

Left/right codificati direttamente impediscono l'RTL

Usare EdgeInsets.only(left: 16) anziché EdgeInsetsDirectional.only(start: 16) impedisce a Flutter di rispecchiare il layout per le lingue RTL. Cerchi nella codebase EdgeInsets, Alignment e BorderRadius privi del suffisso Directional.

Struttura dei file consigliata

Project Structure
my_flutter_app/
├── assets/
│   └── translations/
│       ├── en.arb          # Source language (English)
│       ├── ar.arb          # Arabic (with 6 plural forms)
│       ├── de.arb          # German
│       ├── ja.arb          # Japanese
│       ├── pt-BR.arb       # Brazilian Portuguese
│       └── pt-PT.arb       # European Portuguese
├── lib/
│   ├── main.dart           # App entry with EasyLocalization
│   ├── app.dart            # MaterialApp with locale delegates
│   └── widgets/
│       └── language_switcher.dart
├── pubspec.yaml            # Dependencies
└── analysis_options.yaml

Provi subito i18n Agent

Trascinare qui il file di traduzione

JSON, YAML, PO, XML, CSV, Markdown, Properties

oppure fare clic per selezionarlo

Lingue di destinazione

Nessuna registrazione richiestaPreventivo immediato

Fallback della lingua con locale_chain

Quando manca una chiave di traduzione in una lingua regionale come pt-BR, Flutter passa direttamente alla lingua del modello anziché controllare prima la lingua principale pt.

Terminal
flutter pub add locale_chain
Configuration
import 'package:locale_chain/locale_chain.dart';

LocaleChain.configure(fallbacks: {
  'pt-BR': ['pt', 'en'],
  'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
});

LocaleChainAssetLoader(baseLoader: RootBundleAssetLoader());

Consultare la Guida al fallback delle lingue per l'elenco completo dei framework supportati e delle 75 catene integrate. Learn more →

Domande frequenti