Flutter

Flutter Localization (i18n): Mehrsprachige Apps entwickeln

12 Min. Lesezeit9. Februar 2026Aktualisiert 9. März 2026
Flutter localizationFlutter i18nFlutter multi languageFlutter intlFlutter ARBFlutter localeFlutter translationFlutter internationalization

Mehrsprachigkeit ist kein optionales Feature — sie ist eine grundlegende Produktanforderung fuer jede App mit globalem Anspruch. In Apps, die ich fuer mehr als 10 Maerkte ausgeliefert habe, hat eine von Anfang an saubere i18n-Architektur wochenlange Nacharbeiten erspart. Dieser Leitfaden fuehrt durch das komplette Flutter-Lokalisierungs-Setup: von der Grundkonfiguration ueber RTL-Unterstuetzung bis hin zu Uebersetzungs-Workflows fuer Teams.

Lokalisierung von Grund auf einrichten

Schritt 1: Abhaengigkeiten hinzufuegen

dart
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: ^0.19.0

flutter:
  generate: true

Das Flag generate: true weist Flutter an, aus Ihren ARB-Dateien automatisch Lokalisierungscode zu generieren.

Schritt 2: l10n-Konfiguration erstellen

Erstellen Sie l10n.yaml im Projektstammverzeichnis:

dart
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
nullable-getter: false

Schritt 3: ARB-Dateien erstellen

ARB-Dateien sind JSON-basiert und dienen als zentrale Quelle fuer alle Uebersetzungen. Erstellen Sie lib/l10n/app_en.arb:

dart
{
  "@@locale": "en",
  "appTitle": "My Application",
  "@appTitle": { "description": "The title of the application" },
  "welcomeMessage": "Welcome, {userName}!",
  "@welcomeMessage": {
    "placeholders": { "userName": { "type": "String", "example": "John" } }
  },
  "itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}",
  "@itemCount": {
    "placeholders": { "count": { "type": "num", "format": "compact" } }
  },
  "lastLogin": "Last login: {date}",
  "@lastLogin": {
    "placeholders": { "date": { "type": "DateTime", "format": "yMMMd" } }
  }
}

Dann lib/l10n/app_de.arb fuer Deutsch:

dart
{
  "@@locale": "de",
  "appTitle": "Meine Anwendung",
  "welcomeMessage": "Willkommen, {userName}!",
  "itemCount": "{count, plural, =0{Keine Eintraege} =1{1 Eintrag} other{{count} Eintraege}}",
  "lastLogin": "Letzte Anmeldung: {date}"
}

Schritt 4: MaterialApp konfigurieren

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const [Locale('en'), Locale('tr'), Locale('de')],
      locale: const Locale('de'),
      home: const HomeScreen(),
    );
  }
}

Schritt 5: Uebersetzungen in Widgets verwenden

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

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context);
    return Scaffold(
      appBar: AppBar(title: Text(l10n.appTitle)),
      body: Column(children: [
        Text(l10n.welcomeMessage('Max')),
        Text(l10n.itemCount(5)),
        Text(l10n.lastLogin(DateTime.now())),
      ]),
    );
  }
}

Dynamischer Sprachwechsel

Nutzer sollten die Sprache wechseln koennen, ohne die App neu zu starten. Ein sauberes Muster mit ChangeNotifier:

dart
class LocaleProvider extends ChangeNotifier {
  Locale _locale = const Locale('de');
  Locale get locale => _locale;
  void setLocale(Locale locale) {
    _locale = locale;
    notifyListeners();
  }
}

// In der MaterialApp:
Consumer<LocaleProvider>(
  builder: (context, provider, _) => MaterialApp(
    locale: provider.locale,
    localizationsDelegates: AppLocalizations.localizationsDelegates,
    supportedLocales: AppLocalizations.supportedLocales,
    home: const HomeScreen(),
  ),
)

Pluralisierung und Geschlecht

Das ICU-Nachrichtenformat behandelt Pluralisierung elegant. Flutter unterstuetzt plural, select und gender direkt in ARB-Dateien:

dart
{
  "notificationCount": "{count, plural, =0{Keine Benachrichtigungen} =1{1 Benachrichtigung} other{{count} Benachrichtigungen}}",
  "@notificationCount": { "placeholders": { "count": { "type": "num" } } },
  "genderGreeting": "{gender, select, male{Sehr geehrter Herr {name}} female{Sehr geehrte Frau {name}} other{Guten Tag, {name}}}",
  "@genderGreeting": {
    "placeholders": { "gender": { "type": "String" }, "name": { "type": "String" } }
  }
}

Sprachen wie Polnisch, Arabisch und Russisch haben komplexe Pluralregeln jenseits von Singular und Plural. Das ICU-Format verwaltet zero, one, two, few, many und other automatisch basierend auf dem Locale.

Datums- und Zahlenformatierung

Formatieren Sie Daten und Zahlen niemals manuell. Verwenden Sie immer intl:

dart
import 'package:intl/intl.dart';

final dateFormatter = DateFormat.yMMMd('de');
print(dateFormatter.format(DateTime.now())); // "9. Maer. 2026"

final currencyFormatter = NumberFormat.currency(locale: 'de', symbol: '\u20ac');
print(currencyFormatter.format(1234.56)); // "1.234,56 \u20ac"

final compactFormatter = NumberFormat.compact(locale: 'de');
print(compactFormatter.format(1500000)); // "1,5 Mio."

RTL-Sprachunterstuetzung

Die Unterstuetzung von Rechts-nach-links-Sprachen wie Arabisch, Hebraeisch und Persisch erfordert besondere Aufmerksamkeit beim Layout.

Flutter handhabt die Textrichtung automatisch ueber flutter_localizations. Die Grundregel: Ersetzen Sie hartcodierte left/right-Werte durch start/end:

dart
// Falsch - funktioniert nicht bei RTL
Padding(padding: EdgeInsets.only(left: 16.0))

// Richtig - respektiert die Textrichtung
Padding(padding: EdgeInsetsDirectional.only(start: 16.0))

Einige Icons muessen in RTL-Layouts gespiegelt werden:

dart
Widget buildArrowIcon(BuildContext context) {
  final isRtl = Directionality.of(context) == TextDirection.rtl;
  return Transform.flip(flipX: isRtl, child: const Icon(Icons.arrow_forward));
}

In Apps, die ich fuer mehr als 10 Maerkte ausgeliefert habe, teste ich grundsaetzlich immer mit Arabisch — auch wenn die App offiziell kein Arabisch unterstuetzt. So lassen sich richtungsabhaengige Layout-Fehler zuverlaessig aufdecken.

Uebersetzungs-Workflow fuer Teams

ARB-Dateien organisieren

Ich empfehle eine domaenbasierte Schluesselbenennnung, damit Projekte uebersichtlich bleiben:

dart
{
  "auth_loginButton": "Anmelden",
  "auth_signupButton": "Registrieren",
  "profile_editTitle": "Profil bearbeiten",
  "settings_languageLabel": "Sprache",
  "error_networkTimeout": "Verbindung abgelaufen. Bitte versuchen Sie es erneut."
}

Integration mit Uebersetzungsdiensten

In Produktions-Apps verwende ich einen dieser Workflows:

  1. Manuelle Uebersetzung: ARB-Dateien exportieren, an Uebersetzer senden, zurueckimportieren. Funktioniert bei kleinen Projekten mit weniger als 100 Texten.
  2. Localizely / Crowdin / Phrase: Vorlagen-ARB hochladen, Uebersetzer arbeiten in einer Web-Oberflaeche, fertige ARBs herunterladen. Diese Tools verwalten Pluralregeln und markieren fehlende Uebersetzungen.
  3. CI/CD-Integration: Eine GitHub Action, die bei jedem PR auf fehlende Schluessel prueft.

Fehlende Uebersetzungen erkennen

Ein einfaches Dart-Skript kann alle ARB-Dateien parsen, die Schluessel mit der Vorlage abgleichen und die CI fehlschlagen lassen, wenn Uebersetzungen fehlen. In jedem Projekt halte ich ein scripts/check_translations.dart bereit, das app_en.arb als Referenz nimmt und alle anderen ARB-Dateien dagegen prueft.

Haeufige i18n-Fehler

Fehler 1: Hartcodierte Texte

Jeder nutzersichtbare Text muss durch das Lokalisierungssystem laufen — einschliesslich Fehlermeldungen, Tooltips und Barrierefreiheits-Labels.

dart
// Falsch
Text('Willkommen zurueck!')
// Richtig
Text(AppLocalizations.of(context).welcomeBack)

Fehler 2: String-Verkettung

Bauen Sie Saetze niemals durch Verkettung uebersetzter Fragmente zusammen. Die Wortstellung variiert zwischen Sprachen erheblich.

dart
// Falsch - Wortstellung funktioniert in anderen Sprachen nicht
Text(l10n.sie + ' ' + l10n.haben + ' ' + count.toString() + ' ' + l10n.nachrichten)
// Richtig - einen parametrisierten Text verwenden
Text(l10n.messageCount(count))

Fehler 3: Kein Fallback-Locale

Wenn eine Uebersetzung fehlt und es kein Fallback gibt, kann die App abstuerzen oder rohe Schluessel anzeigen. Flutter faellt automatisch auf das erste Locale in supportedLocales zurueck — platzieren Sie daher Ihre Hauptsprache immer an erster Stelle.

Fehler 4: Textexpansion ignorieren

Deutsche Texte sind typischerweise 30 % laenger als englische. Arabisch kann noch breiter sein. Testen Sie Ihre Oberflaeche immer mit langen Uebersetzungen. Waehrend der Entwicklung verwende ich Pseudo-Lokalisierung, um die Expansion zu simulieren.

Fehler 5: Hartcodierte Datums- und Zahlenformate

dart
// Falsch - nur ein bestimmtes Format
Text('${date.day}.${date.month}.${date.year}')
// Richtig - locale-bewusst
Text(DateFormat.yMd(Localizations.localeOf(context).toString()).format(date))

Fehler 6: Barrierefreiheit vergessen

Screenreader sind auf lokalisierte Semantics-Labels angewiesen. Wenn Sie nur sichtbaren Text lokalisieren, erhalten sehbehinderte Nutzer in anderen Sprachen eine fehlerhafte Erfahrung:

dart
Semantics(
  label: AppLocalizations.of(context).closeButtonLabel,
  child: IconButton(icon: const Icon(Icons.close), onPressed: () => Navigator.pop(context)),
)

Lokalisierung testen

dart
testWidgets('zeigt deutsche Willkommensnachricht an', (tester) async {
  await tester.pumpWidget(MaterialApp(
    locale: const Locale('de'),
    localizationsDelegates: AppLocalizations.localizationsDelegates,
    supportedLocales: AppLocalizations.supportedLocales,
    home: const HomeScreen(),
  ));
  expect(find.text('Willkommen, Max!'), findsOneWidget);
});

Fazit

Ein solides i18n-Setup reduziert den Aufwand bei der Erschliessung neuer Maerkte erheblich. Die fruehe Investition in eine saubere ARB-Struktur, locale-bewusste Formatierung und einen durchdachten Uebersetzungs-Workflow zahlt sich vielfach aus. In Apps, die ich fuer mehr als 10 Maerkte ausgeliefert habe, waren es die Teams, die Lokalisierung als erstklassiges Architekturthema behandelten, die problemlos in neue Regionen skalieren konnten — ohne Notfall-Hotfixes.

Gerne unterstuetze ich Sie bei der Umsetzung einer skalierbaren Lokalisierungs-Pipeline — vom ARB-Setup bis zum CI-integrierten Uebersetzungs-Workflow.

Verwandte Artikel

Haben Sie ein Flutter-Projekt?

Ich entwickle hochleistungsfähige Flutter-Anwendungen für iOS, Android und Web.

Kontakt aufnehmen