# Flutter Localizing Apps

> Configures a Flutter app to support multiple languages and regions. Use when preparing an application for international markets and diverse user locales.

- Skill: `conceptadev/flutter-localizing-apps` (Agent Skill)
- Install (CLI): `npx skillmds@latest add conceptadev/flutter-localizing-apps`
- Raw SKILL.md: https://api.skillmd.com/api/skills/conceptadev/flutter-localizing-apps/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: conceptadev (https://skillmd.com/u/conceptadev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/conceptadev/flutter-localizing-apps

---

# Localizing Flutter Applications

## Contents
- [Core Configuration](#core-configuration)
- [Defining ARB Resources](#defining-arb-resources)
- [App Integration](#app-integration)
- [Advanced Formatting](#advanced-formatting)
- [Workflows](#workflows)
- [Troubleshooting & Gotchas](#troubleshooting--gotchas)

## Core Configuration

Configure the project to support code generation for localizations.

1. Add required dependencies to `pubspec.yaml`:
```yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any

flutter:
  generate: true # Required for l10n code generation
```

2. Create an `l10n.yaml` file in the project root to configure the `gen-l10n` tool:
```yaml
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
# Optional: Set to false to generate files into lib/ instead of the synthetic package
# synthetic-package: false 
```

## Defining ARB Resources

Store localized strings in Application Resource Bundle (`.arb`) files within the configured `arb-dir`.

Create the template file (e.g., `lib/l10n/app_en.arb`):
```json
{
  "helloWorld": "Hello World!",
  "@helloWorld": {
    "description": "The conventional newborn programmer greeting"
  }
}
```

Create translation files (e.g., `lib/l10n/app_es.arb`):
```json
{
  "helloWorld": "¡Hola Mundo!"
}
```

## App Integration

Initialize the `Localizations` widget by configuring the root `MaterialApp` or `CupertinoApp`.

```dart
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // Adjust import if synthetic-package is false

return MaterialApp(
  title: 'Localized App',
  localizationsDelegates: const [
    AppLocalizations.delegate,
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: const [
    Locale('en'), // English
    Locale('es'), // Spanish
  ],
  home: const MyHomePage(),
);
```

Access localized values in the widget tree using the generated `AppLocalizations` class:
```dart
Text(AppLocalizations.of(context)!.helloWorld)
```

*Note: If using `WidgetsApp` instead of `MaterialApp`, omit `GlobalMaterialLocalizations.delegate`.*

## Advanced Formatting

Use placeholders, plurals, and selects for dynamic content. Define parameters in the `@key` metadata.

### Placeholders
```json
"hello": "Hello {userName}",
"@hello": {
  "description": "A message with a single parameter",
  "placeholders": {
    "userName": {
      "type": "String",
      "example": "Bob"
    }
  }
}
```

### Plurals
```json
"nWombats": "{count, plural, =0{no wombats} =1{1 wombat} other{{count} wombats}}",
"@nWombats": {
  "placeholders": {
    "count": {
      "type": "num",
      "format": "compact"
    }
  }
}
```

### Selects (Gender/Enums)
```json
"pronoun": "{gender, select, male{he} female{she} other{they}}",
"@pronoun": {
  "placeholders": {
    "gender": {
      "type": "String"
    }
  }
}
```

### Dates and Numbers
Use `format` and `optionalParameters` to leverage `intl` formatting.
```json
"dateMessage": "Date: {date}",
"@dateMessage": {
  "placeholders": {
    "date": {
      "type": "DateTime",
      "format": "yMd"
    }
  }
}
```

## Workflows

### Task Progress: Adding a New Language
Copy this checklist to track progress when introducing a new locale.

- [ ] Create a new `.arb` file in the `arb-dir` (e.g., `app_fr.arb`).
- [ ] Translate all keys present in the template `.arb` file.
- [ ] Add the new `Locale` to the `supportedLocales` list in `MaterialApp`.
- [ ] Run validator -> Execute `flutter gen-l10n` to verify ARB syntax and regenerate `AppLocalizations`.
- [ ] Review errors -> Fix any missing placeholders or malformed plural/select statements.
- [ ] If targeting iOS, complete the "Configuring iOS App Bundle" workflow.

### Task Progress: Configuring iOS App Bundle
Flutter handles runtime localization, but iOS requires bundle-level configuration for the App Store and system settings.

- [ ] Open `ios/Runner.xcodeproj` in Xcode.
- [ ] Select the `Runner` project in the Project Navigator.
- [ ] Navigate to the `Info` tab.
- [ ] Under the **Localizations** section, click the `+` button.
- [ ] Add the newly supported languages/regions.
- [ ] Run validator -> Build the iOS app to ensure `project.pbxproj` is correctly updated.

## Troubleshooting & Gotchas

### Missing Localizations Ancestor
Widgets like `TextField` and `CupertinoTabBar` require a `Localizations` ancestor with specific delegates (`MaterialLocalizations` or `CupertinoLocalizations`). 

**Error:** `No MaterialLocalizations found.` or `CupertinoTabBar requires a Localizations parent...`
**Fix:** Ensure the widget is a descendant of `MaterialApp`/`CupertinoApp`. If building a standalone widget tree (e.g., in tests or a custom `WidgetsApp`), wrap the widget in a `Localizations` widget:

```dart
Localizations(
  locale: const Locale('en', 'US'),
  delegates: const [
    DefaultWidgetsLocalizations.delegate,
    DefaultMaterialLocalizations.delegate, // Required for TextField
    DefaultCupertinoLocalizations.delegate, // Required for CupertinoTabBar
  ],
  child: child,
)
```

### Advanced Locale Definition
If supporting languages with multiple scripts (e.g., Chinese), use `Locale.fromSubtags` to explicitly define the `scriptCode` and `countryCode` to prevent Flutter from resolving to an unexpected variant.

```dart
supportedLocales: const [
  Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),
  Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'),
]
```

