Skip to main content

De complete handleiding voor Flutter-lokalisatie

Van ARB-bestanden tot RTL-ondersteuning: lokaliseer je Flutter-app met easy_localization, verwerk meervoudsvormen voor elke taal en automatiseer vertalingen met AI.

1

easy_localization installeren

Voeg het pakket easy_localization aan je pubspec.yaml toe. Dit is het populairste i18n-pakket voor Flutter en ondersteunt ARB-/JSON-bestanden, meervoudsvormen en contextextensies. Voeg ook flutter_localizations uit de SDK toe voor localegevoelige opmaak van datums en getallen en voor de juiste tekstrichting.

easy_localization biedt contextextensies zoals context.tr() en 'key'.tr() voor beknopte toegang tot vertalingen. Het pakket verwerkt het laden en opslaan van de locale en ondersteunt hot reload van vertaalbestanden tijdens de ontwikkeling.
pubspec.yaml
dependencies:
  easy_localization: ^3.0.7
  flutter_localizations:
    sdk: flutter
2

ARB-vertaalbestanden maken

Application Resource Bundle-bestanden (ARB) zijn de standaardindeling voor Flutter-lokalisatie. Elk bestand bevat sleutel-waardeparen met optionele metadata over placeholders, meervoudsregels en context voor vertalers. Maak per locale één bestand in de map 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"
      }
    }
  }
}
Sleutels met een @-voorvoegsel, zoals @greeting, bevatten metadata en beschrijven de tekst erboven. Neem typen en voorbeelden van placeholders op om vertalers te helpen nauwkeurige vertalingen te maken. Deze metadatasleutels worden tijdens runtime verwijderd en veroorzaken geen overhead.
3

De app configureren

Plaats de EasyLocalization-widget rond je app. Deze beheert de localestatus, laadt vertalingen uit je assetbestanden en levert de localedelegates die MaterialApp nodig heeft. De drie vereiste delegate-eigenschappen zijn localizationsDelegates, supportedLocales en locale. Ze zijn allemaal via contextextensies beschikbaar.

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" — deze fout betekent dat je EasyLocalization.ensureInitialized() niet vóór runApp() hebt aangeroepen. Je moet erop wachten na WidgetsFlutterBinding.ensureInitialized() en vóór runApp().
4

Widgets vertalen

Gebruik de extensiemethode .tr() op tekstsleutels om in elke widget vertaalde tekst op te halen. Gebruik voor meervouden .plural() met het aantal. easy_localization biedt zowel de syntaxis van een tekstextensie ('key'.tr()) als die van een contextmethode (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)),
        ],
      ),
    );
  }
}
Controleer het volgende wanneer vertalingen onbewerkte sleutels opleveren in plaats van vertaalde tekst: 1) de EasyLocalization-widget staat rond je MaterialApp en niet andersom; 2) je vertaalbestanden zijn in pubspec.yaml onder assets gedeclareerd; 3) het bestandspad in EasyLocalization komt overeen met je werkelijke mapstructuur.
5

Meervouden en variabelen verwerken

Flutter gebruikt ICU MessageFormat voor meervouden, dezelfde standaard als iOS, Android en het web. Definieer in je ARB-bestanden meervoudsvormen met de syntaxis {count, plural, ...}. Elke taal heeft op basis van de CLDR-meervoudsregels eigen vormen nodig. Arabisch heeft 6 vormen, Russisch 4 en Japans 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}));
Codeer enkelvouds- en meervoudslogica nooit hard met if (count == 1). Talen zoals Frans behandelen 0 als enkelvoud. Russisch, Pools en Arabisch hebben meervoudsvormen die in het Engels helemaal niet bestaan. Gebruik altijd ICU-meervoudssyntaxis en laat het framework de juiste vorm kiezen.
6

RTL-talen ondersteunen

Flutter spiegelt de volledige lay-out automatisch wanneer de locale een taal van rechts naar links gebruikt, zoals Arabisch, Hebreeuws, Perzisch of Urdu. Je code moet wel richtingsbewuste widgets en eigenschappen gebruiken om correct te kunnen spiegelen. Vervang hardgecodeerde links/rechts-waarden door de equivalenten 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
Test RTL door de locale van je app tijdelijk op Arabisch in te stellen (Locale('ar')). Flutter spiegelt de volledige gebruikersinterface: navigatielades openen rechts, terugpijlen draaien om en tekst wordt rechts uitgelijnd. Gebruik EdgeInsetsDirectional, AlignmentDirectional en BorderRadiusDirectional zodat je aangepaste lay-outs correct worden gespiegeld.
7

Slimme locale-fallbackketens

Wanneer een pt-BR-vertaling ontbreekt, valt Flutter standaard direct terug op Engels en worden prima pt-PT-vertalingen overgeslagen. Het pakket locale_chain lost dit op met configureerbare fallbackketens. Eén configuratieregel, geen migratie: je bestaande .tr()-aanroepen blijven gewoon werken.

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 bevat ingebouwde fallbackketens voor regionale varianten van het Portugees, Spaans, Frans, Duits, Italiaans, Nederlands, Noors en Maleis. Een pt-BR-gebruiker ziet pt-PT-inhoud vóór Engels. Een es-MX-gebruiker ziet eerst es-419 en daarna es vóór de standaardlocale.
8

Vertalingen automatiseren

Wanneer je lokalisatieconfiguratie gereed is, vertaal je ARB-bestanden met AI. Vraag je AI-assistent in je ontwikkelomgeving om het ARB-bronbestand te vertalen of gebruik de CLI van i18n Agent in je CI/CD-pipeline. ARB-metadata, zoals placeholders en beschrijvingen, biedt context die de vertaalkwaliteit verbetert.

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
Vertaal stapsgewijs. Wanneer je nieuwe sleutels aan het ARB-bronbestand toevoegt, vertaal je alleen het verschil in plaats van alle bestanden opnieuw te genereren. Zo blijven door mensen beoordeelde vertalingen en je ARB-metadata behouden.

Vertaalkwaliteit automatisch bewaken

Vind ontbrekende sleutels en beschadigde placeholders vóór de release met i18n-validate. Test je gebruikersinterface met pseudovertalingen via i18n-pseudo voordat de echte vertalingen beschikbaar zijn.

Veelvoorkomende valkuilen

Vertaalbestanden niet gevonden tijdens runtime

Je ARB-/JSON-bestanden moeten in pubspec.yaml onder assets zijn gedeclareerd. Zonder deze stap kan Flutter de bestanden tijdens runtime niet vinden, ook al staan ze op de schijf. Voeg toe: assets: - assets/translations/

Ongeldige syntaxis in ARB-bestand

ARB-bestanden zijn strikte JSON: geen afsluitende komma's, enkele aanhalingstekens of opmerkingen. Eén syntaxisfout voorkomt ongemerkt dat het volledige bestand wordt geladen. Valideer ARB-bestanden met een JSON-linter voordat je vertaalproblemen onderzoekt.

Vertaalwijzigingen verschijnen niet na hot reload

easy_localization bewaart vertalingen in het geheugen. Nadat je nieuwe sleutels hebt toegevoegd of bestaande vertalingen hebt gewijzigd, is mogelijk een volledige hot restart nodig in plaats van hot reload. Gebruik tijdens de ontwikkeling hot restart (Shift+R) nadat je vertaalbestanden hebt bewerkt.

Hardgecodeerd links/rechts verstoort RTL

Als je EdgeInsets.only(left: 16) gebruikt in plaats van EdgeInsetsDirectional.only(start: 16), kan Flutter je lay-out niet voor RTL-talen spiegelen. Zoek in je codebase naar EdgeInsets, Alignment en BorderRadius zonder het achtervoegsel Directional.

Aanbevolen bestandsstructuur

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

Probeer i18n Agent nu

Zet je vertaalbestand hier neer

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

of klik om een bestand te selecteren

Doeltalen

Geen registratie nodigDirecte prijsindicatie

Locale-fallback met locale_chain

Wanneer een vertaalsleutel ontbreekt in een regionale locale zoals pt-BR, springt Flutter direct naar de sjabloontaal in plaats van eerst de bovenliggende locale pt te controleren.

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());

Bekijk onze handleiding voor locale-fallback voor de volledige lijst met ondersteunde frameworks en 75 ingebouwde ketens. Learn more →

Veelgestelde vragen