Skip to main content

Den komplette guide til Flutter-lokalisering

Fra ARB-filer til RTL-understøttelse: Lokaliser din Flutter-app med easy_localization, håndter flertalsformer for alle sprog og automatiser oversættelser med AI.

1

Installer easy_localization

Føj pakken easy_localization til din pubspec.yaml. Det er den mest populære Flutter i18n-pakke med understøttelse af ARB/JSON-filer, flertalsformer og context-udvidelser. Tilføj også flutter_localizations fra SDK'et for lokaletilpasset formatering af datoer, tal og tekstretning.

easy_localization leverer context-udvidelser som context.tr() og 'key'.tr(), der giver kortfattet adgang til oversættelser. Den håndterer indlæsning og lagring af lokale samt hot reload af oversættelsesfiler under udvikling.
pubspec.yaml
dependencies:
  easy_localization: ^3.0.7
  flutter_localizations:
    sdk: flutter
2

Opret ARB-oversættelsesfiler

Application Resource Bundle-filer (ARB) er standardformatet til lokalisering i Flutter. Hver fil indeholder nøgle-værdi-par med valgfri metadata, der beskriver pladsholdere, flertalsregler og kontekst til oversættere. Opret én fil pr. lokale i mappen 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"
      }
    }
  }
}
Nøglerne med præfikset @ (som @greeting) er metadata — de beskriver strengen ovenfor. Medtag pladsholdertyper og eksempler for at hjælpe oversættere med at levere præcise oversættelser. Disse metadatanøgler fjernes ved kørsel og giver ingen ekstra belastning.
3

Konfigurer appen

Pak din app ind i EasyLocalization-widgetten. Den administrerer lokalets tilstand, indlæser oversættelser fra dine assetfiler og leverer de lokalisering-delegates, som MaterialApp skal bruge. De tre påkrævede delegate-egenskaber er localizationsDelegates, supportedLocales og locale — alle er tilgængelige via context-udvidelser.

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" — denne fejl betyder, at du har glemt at kalde EasyLocalization.ensureInitialized() før runApp(). Kaldet skal afventes efter WidgetsFlutterBinding.ensureInitialized() og før runApp().
4

Oversæt widgets

Brug udvidelsesmetoden .tr() på strengnøgler for at hente oversat tekst i enhver widget. Brug .plural() med antalsværdien til flertalsformer. easy_localization understøtter både syntaksen med strengudvidelsen ('key'.tr()) og syntaksen med context-metoden (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)),
        ],
      ),
    );
  }
}
Hvis oversættelser returnerer rå nøgler i stedet for oversat tekst, skal du kontrollere følgende: 1) EasyLocalization-widgetten omslutter din MaterialApp og ikke omvendt. 2) Dine oversættelsesfiler er angivet under assets i pubspec.yaml. 3) Filstien i EasyLocalization svarer til din faktiske mappestruktur.
5

Håndter flertalsformer og variabler

Flutter bruger ICU MessageFormat til flertalsformer — samme standard som iOS, Android og internettet. Definer flertalsformer med syntaksen {count, plural, ...} i dine ARB-filer. Hvert sprog kræver sit eget sæt former baseret på CLDR's flertalsregler. Arabisk har 6 former, russisk har 4 og japansk har 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}));
Hardkod aldrig logik for ental og flertal med if (count == 1). Sprog som fransk behandler 0 som ental. Russisk, polsk og arabisk har flertalsformer, som slet ikke findes på engelsk. Brug altid ICU's flertalssyntaks og lad frameworket vælge den korrekte form.
6

Understøt RTL-sprog

Flutter spejler automatisk hele layoutet, når landestandarden bruger et sprog, der skrives fra højre mod venstre (arabisk, hebraisk, persisk eller urdu). Din kode skal dog bruge retningsbevidste widgets og egenskaber, for at spejlingen fungerer korrekt. Erstat hardkodet venstre/højre med tilsvarende start/slut-egenskaber.

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 ved midlertidigt at indstille appens lokale til arabisk (Locale('ar')). Flutter spejler hele brugergrænsefladen — navigationspaneler åbnes fra højre, tilbagepile vendes og tekst højrestilles. Brug EdgeInsetsDirectional, AlignmentDirectional og BorderRadiusDirectional for at sikre, at dine egne layout spejles korrekt.
7

Intelligente lokale fallbackkæder

Når en pt-BR-oversættelse mangler, går Flutter som standard direkte tilbage til engelsk og springer velfungerende pt-PT-oversættelser over. Pakken locale_chain løser dette med konfigurerbare fallbackkæder. Én opsætningslinje, ingen migrering — dine eksisterende .tr()-kald fungerer med det samme.

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 indeholder indbyggede fallbackkæder til regionale varianter af portugisisk, spansk, fransk, tysk, italiensk, nederlandsk, norsk og malajisk. En pt-BR-bruger får vist pt-PT-indhold før engelsk. En es-MX-bruger får vist es-419 og derefter es før standardlokalet.
8

Automatiser oversættelser

Når lokaliseringsopsætningen er færdig, kan du oversætte dine ARB-filer med AI. Bed din AI-assistent i IDE'et om at oversætte ARB-kildefilen eller brug i18n Agent CLI i din CI/CD-pipeline. ARB-metadata (pladsholdere og beskrivelser) giver kontekst, der forbedrer oversættelseskvaliteten.

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
Oversæt trinvist — når du føjer nye nøgler til din ARB-kildefil, skal du kun oversætte forskellen i stedet for at generere alle filer igen. Dermed bevares eventuelle oversættelser, som mennesker har gennemgået, mens dine ARB-metadata forbliver intakte.

Automatiser oversættelseskvaliteten

Find manglende nøgler og defekte pladsholdere med i18n-validate, før de udgives. Test brugergrænsefladen med pseudooversættelser ved hjælp af i18n-pseudo, før de rigtige oversættelser er klar.

Almindelige faldgruber

Oversættelsesfiler blev ikke fundet ved kørsel

Dine ARB/JSON-filer skal angives i pubspec.yaml under sektionen assets. Hvis du springer dette trin over, kan Flutter ikke finde filerne ved kørsel, selvom de findes på disken. Tilføj: assets: - assets/translations/

Ugyldig syntaks i ARB-filen

ARB-filer er streng JSON — ingen afsluttende kommaer, enkelte anførselstegn eller kommentarer. En enkelt syntaksfejl kan uden fejlmeddelelse forhindre hele filen i at blive indlæst. Valider dine ARB-filer med en JSON-linter, før du fejlsøger oversættelsesproblemer.

Oversættelsesændringer vises ikke efter hot reload

easy_localization cachelagrer oversættelser i hukommelsen. Når du tilføjer nye nøgler eller ændrer eksisterende oversættelser, kan en fuld hot restart (ikke hot reload) være nødvendig, før ændringerne træder i kraft. Brug hot restart (Shift+R), når du har redigeret oversættelsesfiler under udvikling.

Hardkodet venstre/højre ødelægger RTL

Hvis du bruger EdgeInsets.only(left: 16) i stedet for EdgeInsetsDirectional.only(start: 16), kan Flutter ikke spejle dit layout til RTL-sprog. Søg i kodebasen efter EdgeInsets, Alignment og BorderRadius uden suffikset Directional.

Anbefalet filstruktur

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

Prøv i18n Agent nu

Slip din oversættelsesfil her

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

eller klik for at vælge en fil

Målsprog

Kræver ingen tilmeldingEstimat med det samme

Lokale fallback med locale_chain

Når en oversættelsesnøgle mangler i et regionalt lokale som pt-BR, går Flutter direkte til skabelonsproget i stedet for først at kontrollere det overordnede lokale 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());

Se vores guide til lokale fallback for at få den komplette liste over understøttede frameworks og 75 indbyggede kæder. Learn more →

Ofte stillede spørgsmål