Skip to main content

Le guide complet de la localisation Flutter

Des fichiers ARB à la prise en charge du RTL : localisez votre application Flutter avec easy_localization, gérez les pluriels pour chaque langue et automatisez les traductions avec l'IA.

1

Installer easy_localization

Ajoutez le package easy_localization à votre pubspec.yaml. Il s'agit du package i18n le plus populaire pour Flutter, avec prise en charge des fichiers ARB/JSON, des pluriels et des extensions de contexte. Ajoutez également flutter_localizations depuis le SDK pour un formatage des dates, des nombres et du sens du texte tenant compte de la locale.

easy_localization fournit des extensions de contexte telles que context.tr() et 'key'.tr() pour un accès concis aux traductions. Il gère le chargement des locales, leur persistance et le rechargement à chaud des fichiers de traduction pendant le développement.
pubspec.yaml
dependencies:
  easy_localization: ^3.0.7
  flutter_localizations:
    sdk: flutter
2

Créer des fichiers de traduction ARB

Les fichiers Application Resource Bundle (ARB) constituent le format de localisation standard pour Flutter. Chaque fichier contient des paires clé-valeur avec des métadonnées facultatives décrivant les espaces réservés, les règles de pluriel et le contexte destiné aux traducteurs. Créez un fichier par locale dans votre répertoire 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"
      }
    }
  }
}
Les clés préfixées par @ (comme @greeting) sont des métadonnées — elles décrivent la chaîne située au-dessus d'elles. Incluez les types d'espaces réservés et des exemples pour aider les traducteurs à produire des traductions précises. Ces clés de métadonnées sont supprimées à l'exécution et n'ajoutent aucun coût.
3

Configurer l'application

Enveloppez votre application avec le widget EasyLocalization. Il gère l'état de la locale, charge les traductions depuis vos fichiers d'assets et fournit les délégués de locale dont MaterialApp a besoin. Les trois propriétés de délégué requises sont localizationsDelegates, supportedLocales et locale — toutes disponibles via des extensions de contexte.

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 » — cette erreur signifie que vous avez oublié d'appeler EasyLocalization.ensureInitialized() avant runApp(). Cet appel doit être attendu (await) après WidgetsFlutterBinding.ensureInitialized() et avant runApp().
4

Traduire les widgets

Utilisez la méthode d'extension .tr() sur les clés de chaîne pour obtenir le texte traduit dans n'importe quel widget. Pour les pluriels, utilisez .plural() avec la valeur du compteur. easy_localization propose à la fois la syntaxe d'extension de chaîne ('key'.tr()) et la syntaxe de méthode de contexte (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)),
        ],
      ),
    );
  }
}
Si les traductions renvoient les clés brutes au lieu du texte traduit, vérifiez : 1) Que le widget EasyLocalization enveloppe bien votre MaterialApp, et non l'inverse. 2) Que vos fichiers de traduction sont déclarés dans pubspec.yaml sous assets. 3) Que le chemin de fichier dans EasyLocalization correspond à la structure réelle de votre répertoire.
5

Gérer les pluriels et les variables

Flutter utilise ICU MessageFormat pour les pluriels — le même standard qu'iOS, Android et le web. Définissez les formes plurielles à l'aide de la syntaxe {count, plural, ...} dans vos fichiers ARB. Chaque langue nécessite son propre jeu de formes, basé sur les règles de pluriel CLDR. L'arabe compte 6 formes, le russe 4, le japonais 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}));
Ne codez jamais en dur une logique singulier/pluriel avec if (count == 1). Des langues comme le français traitent 0 comme un singulier. Le russe, le polonais et l'arabe possèdent des formes plurielles totalement absentes en anglais. Utilisez toujours la syntaxe de pluriel ICU et laissez le framework sélectionner la forme correcte.
6

Prendre en charge les langues RTL

Flutter met automatiquement en miroir l'intégralité de la mise en page lorsque la locale est une langue s'écrivant de droite à gauche (arabe, hébreu, persan, ourdou). Mais votre code doit utiliser des widgets et des propriétés tenant compte du sens d'écriture pour que la mise en miroir fonctionne correctement. Remplacez les valeurs gauche/droite codées en dur par leurs équivalents 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
Testez le RTL en définissant temporairement la locale de votre application sur l'arabe (Locale('ar')). Flutter met en miroir l'intégralité de l'interface — les tiroirs de navigation s'ouvrent depuis la droite, les flèches de retour s'inversent et le texte s'aligne à droite. Utilisez EdgeInsetsDirectional, AlignmentDirectional et BorderRadiusDirectional pour garantir que vos mises en page personnalisées se reflètent correctement.
7

Chaînes de repli de locale intelligentes

Par défaut, lorsqu'une traduction pt-BR est manquante, Flutter revient directement à l'anglais — en ignorant des traductions pt-PT parfaitement valables. Le package locale_chain corrige ce problème grâce à des chaînes de repli configurables. Une seule ligne de configuration, aucune migration — vos appels .tr() existants fonctionnent tels quels.

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 inclut des chaînes de repli intégrées pour les variantes régionales du portugais, de l'espagnol, du français, de l'allemand, de l'italien, du néerlandais, du norvégien et du malais. Un utilisateur pt-BR verra le contenu pt-PT avant l'anglais. Un utilisateur es-MX verra es-419 puis es avant la locale par défaut.
8

Automatiser les traductions

Une fois votre configuration de localisation terminée, traduisez vos fichiers ARB à l'aide de l'IA. Dans votre IDE, demandez à votre assistant IA de traduire votre fichier ARB source, ou utilisez la CLI i18n Agent dans votre pipeline CI/CD. Les métadonnées ARB (espaces réservés, descriptions) fournissent un contexte qui améliore la qualité de la traduction.

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
Traduisez de manière incrémentale — lorsque vous ajoutez de nouvelles clés à votre fichier ARB source, traduisez uniquement les différences plutôt que de régénérer tous les fichiers. Cela préserve les traductions révisées manuellement et conserve vos métadonnées ARB intactes.

Automatiser la qualité des traductions

Détectez les clés manquantes et les espaces réservés cassés avant leur mise en production grâce à i18n-validate. Testez votre interface avec des pseudo-traductions grâce à i18n-pseudo avant l'arrivée des traductions réelles.

Pièges courants

Fichiers de traduction introuvables à l'exécution

Vos fichiers ARB/JSON doivent être déclarés dans pubspec.yaml sous la section assets. Si vous omettez cette étape, Flutter ne pourra pas trouver les fichiers à l'exécution, même s'ils existent sur le disque. Ajoutez : assets: - assets/translations/

Syntaxe de fichier ARB non valide

Les fichiers ARB sont du JSON strict — pas de virgules finales, pas de guillemets simples, pas de commentaires. Une seule erreur de syntaxe empêche silencieusement le chargement de l'intégralité du fichier. Validez vos fichiers ARB avec un linter JSON avant de déboguer des problèmes de traduction.

Les modifications de traduction n'apparaissent pas lors du hot reload

easy_localization met les traductions en cache en mémoire. L'ajout de nouvelles clés ou la modification de traductions existantes peut nécessiter un hot restart complet (et non un hot reload) pour prendre effet. Pendant le développement, utilisez le hot restart (Shift+R) après avoir modifié les fichiers de traduction.

Valeurs gauche/droite codées en dur cassant le RTL

Utiliser EdgeInsets.only(left: 16) au lieu de EdgeInsetsDirectional.only(start: 16) empêche Flutter de mettre en miroir votre mise en page pour les langues RTL. Recherchez dans votre code EdgeInsets, Alignment et BorderRadius sans le suffixe Directional.

Structure de fichiers recommandée

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

Essayez i18n Agent maintenant

Déposez votre fichier de traduction ici

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

ou cliquez pour parcourir

Langues cibles

Aucune inscription requiseEstimation instantanée

Repli de locale avec locale_chain

Lorsqu'une clé de traduction est absente dans une locale régionale comme pt-BR, Flutter passe directement à la langue modèle au lieu de vérifier d'abord la locale parente 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());

Consultez notre guide de repli de locale pour découvrir la liste complète des frameworks pris en charge et les 75 chaînes intégrées. Learn more →

Questions fréquentes