flutter-internationalization

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Flutter Internationalization

Flutter应用国际化

Overview

概述

Comprehensive guide for adding internationalization (i18n) to Flutter applications. Covers setup, configuration, message management, number/date formatting, and advanced topics like locale override and custom language support.
为Flutter应用添加国际化(i18n)的全面指南,涵盖设置、配置、消息管理、数字/日期格式化,以及Locale覆盖、自定义语言支持等高级主题。

Quick Start

快速入门

Choose approach based on app needs:
gen-l10n (Recommended) - Modern, automated, code generation
  • Best for: Most new projects, teams, complex apps
  • Uses: ARB files, automated code generation
  • See: Setup gen-l10n
intl package - Manual control, code-based
  • Best for: Simple apps, legacy projects, full control
  • Uses:
    Intl.message()
    code, manual translation files
  • See: Setup intl package
Manual/Custom - Maximum flexibility
  • Best for: Very simple apps, custom workflows
  • Uses: Direct Map-based lookups
  • See: Custom localizations
根据应用需求选择合适的方案:
gen-l10n(推荐) - 现代化、自动化的代码生成方案
  • 适用场景:大多数新项目、团队协作、复杂应用
  • 使用工具:ARB文件、自动化代码生成
  • 查看:gen-l10n设置
intl包 - 手动控制、基于代码的方案
  • 适用场景:简单应用、遗留项目、需要完全控制权的场景
  • 使用工具:
    Intl.message()
    代码、手动翻译文件
  • 查看:intl包设置
手动/自定义方案 - 最大灵活性
  • 适用场景:极简应用、自定义工作流
  • 使用工具:直接基于Map的查找
  • 查看:自定义本地化

Setup gen-l10n

gen-l10n设置

1. Add Dependencies

1. 添加依赖

Update
pubspec.yaml
:
yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any
Run:
bash
flutter pub add flutter_localizations --sdk=flutter
flutter pub add intl:any
更新
pubspec.yaml
yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any
运行以下命令:
bash
flutter pub add flutter_localizations --sdk=flutter
flutter pub add intl:any

2. Enable Code Generation

2. 启用代码生成

Add to
pubspec.yaml
:
yaml
flutter:
  generate: true
pubspec.yaml
中添加:
yaml
flutter:
  generate: true

3. Configure l10n.yaml

3. 配置l10n.yaml

Create
l10n.yaml
in project root:
yaml
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
For advanced options, see l10n-config.md.
在项目根目录创建
l10n.yaml
文件:
yaml
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
如需高级配置选项,请查看l10n-config.md

4. Create ARB Files

4. 创建ARB文件

Create directory
lib/l10n/
.
Template file
lib/l10n/app_en.arb
:
json
{
  "helloWorld": "Hello World!",
  "@helloWorld": {
    "description": "Greeting message"
  }
}
Translation file
lib/l10n/app_es.arb
:
json
{
  "helloWorld": "¡Hola Mundo!"
}
For complete ARB format, see arb-format.md.
创建目录
lib/l10n/
模板文件
lib/l10n/app_en.arb
json
{
  "helloWorld": "Hello World!",
  "@helloWorld": {
    "description": "Greeting message"
  }
}
翻译文件
lib/l10n/app_es.arb
json
{
  "helloWorld": "¡Hola Mundo!"
}
如需了解完整的ARB文件格式,请查看arb-format.md

5. Generate Code

5. 生成代码

Run:
bash
flutter gen-l10n
Or run app to trigger auto-generation:
bash
flutter run
运行以下命令:
bash
flutter gen-l10n
或运行应用触发自动生成:
bash
flutter run

6. Configure MaterialApp

6. 配置MaterialApp

Import and setup:
dart
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'l10n/app_localizations.dart';

MaterialApp(
  localizationsDelegates: [
    AppLocalizations.delegate,
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: [
    Locale('en'),
    Locale('es'),
  ],
  home: MyHomePage(),
)
导入并设置:
dart
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'l10n/app_localizations.dart';

MaterialApp(
  localizationsDelegates: [
    AppLocalizations.delegate,
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: [
    Locale('en'),
    Locale('es'),
  ],
  home: MyHomePage(),
)

7. Use Localizations

7. 使用本地化内容

Access in widgets:
dart
Text(AppLocalizations.of(context)!.helloWorld)
在组件中访问:
dart
Text(AppLocalizations.of(context)!.helloWorld)

Message Types

消息类型

Simple Messages

简单消息

No parameters:
json
{
  "welcome": "Welcome to our app",
  "@welcome": {
    "description": "Welcome message"
  }
}
无参数:
json
{
  "welcome": "Welcome to our app",
  "@welcome": {
    "description": "Welcome message"
  }
}

Placeholder Messages

占位符消息

With parameters:
json
{
  "greeting": "Hello {userName}!",
  "@greeting": {
    "description": "Personalized greeting",
    "placeholders": {
      "userName": {
        "type": "String",
        "example": "Alice"
      }
    }
  }
}
Use in code:
dart
Text(AppLocalizations.of(context)!.greeting('Alice'))
带参数:
json
{
  "greeting": "Hello {userName}!",
  "@greeting": {
    "description": "Personalized greeting",
    "placeholders": {
      "userName": {
        "type": "String",
        "example": "Alice"
      }
    }
  }
}
在代码中使用:
dart
Text(AppLocalizations.of(context)!.greeting('Alice'))

Plural Messages

复数消息

Based on count:
json
{
  "itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}",
  "@itemCount": {
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}
Use in code:
dart
Text(AppLocalizations.of(context)!.itemCount(5))
基于数量:
json
{
  "itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}",
  "@itemCount": {
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}
在代码中使用:
dart
Text(AppLocalizations.of(context)!.itemCount(5))

Select Messages

选择消息

Based on string value:
json
{
  "pronoun": "{gender, select, male{he} female{she} other{they}}",
  "@pronoun": {
    "placeholders": {
      "gender": {
        "type": "String"
      }
    }
  }
}
Use in code:
dart
Text(AppLocalizations.of(context)!.pronoun('male'))
基于字符串值:
json
{
  "pronoun": "{gender, select, male{he} female{she} other{they}}",
  "@pronoun": {
    "placeholders": {
      "gender": {
        "type": "String"
      }
    }
  }
}
在代码中使用:
dart
Text(AppLocalizations.of(context)!.pronoun('male'))

Number and Date Formatting

数字与日期格式化

Numbers

数字

Format numbers automatically:
json
{
  "price": "Price: {value}",
  "@price": {
    "placeholders": {
      "value": {
        "type": "int",
        "format": "simpleCurrency"
      }
    }
  }
}
Format options:
compact
,
currency
,
simpleCurrency
,
decimalPattern
, etc.
自动格式化数字:
json
{
  "price": "Price: {value}",
  "@price": {
    "placeholders": {
      "value": {
        "type": "int",
        "format": "simpleCurrency"
      }
    }
  }
}
格式化选项包括:
compact
currency
simpleCurrency
decimalPattern
等。

Dates

日期

Format dates automatically:
json
{
  "eventDate": "Event on {date}",
  "@eventDate": {
    "placeholders": {
      "date": {
        "type": "DateTime",
        "format": "yMMMd"
      }
    }
  }
}
Format options:
yMd
,
yMMMd
,
yMMMMd
,
Hm
, etc.
For complete formatting options, see number-date-formats.md.
自动格式化日期:
json
{
  "eventDate": "Event on {date}",
  "@eventDate": {
    "placeholders": {
      "date": {
        "type": "DateTime",
        "format": "yMMMd"
      }
    }
  }
}
格式化选项包括:
yMd
yMMMd
yMMMMd
Hm
等。
如需完整的格式化选项,请查看number-date-formats.md

Advanced Topics

高级主题

Locale Override

Locale覆盖

Override locale for specific widgets:
dart
Localizations.override(
  context: context,
  locale: const Locale('es'),
  child: CalendarDatePicker(...),
)
为特定组件覆盖Locale:
dart
Localizations.override(
  context: context,
  locale: const Locale('es'),
  child: CalendarDatePicker(...),
)

Custom Locale Definitions

自定义Locale定义

For complex locales (Chinese, French regions):
dart
supportedLocales: [
  Locale.fromSubtags(languageCode: 'zh'),
  Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'),
  Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'),
]
针对复杂Locale(如中文、法语地区):
dart
supportedLocales: [
  Locale.fromSubtags(languageCode: 'zh'),
  Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'),
  Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'),
]

Locale Resolution Callback

Locale解析回调

Control locale fallback:
dart
MaterialApp(
  localeResolutionCallback: (locale, supportedLocales) {
    // Always accept user's locale
    return locale;
  },
)
控制Locale回退逻辑:
dart
MaterialApp(
  localeResolutionCallback: (locale, supportedLocales) {
    // 始终接受用户的Locale
    return locale;
  },
)

Access Current Locale

获取当前Locale

Get current app locale:
dart
Locale myLocale = Localizations.localeOf(context);
获取应用当前使用的Locale:
dart
Locale myLocale = Localizations.localeOf(context);

Setup intl Package

intl包设置

Manual Setup

手动设置

  1. Add dependencies (same as gen-l10n)
  2. Create localization class:
dart
class DemoLocalizations {
  DemoLocalizations(this.localeName);

  static Future<DemoLocalizations> load(Locale locale) {
    final String name = Intl.canonicalizedLocale(locale.toString());
    return initializeMessages(name).then((_) => DemoLocalizations(name));
  }

  static DemoLocalizations of(BuildContext context) {
    return Localizations.of<DemoLocalizations>(context, DemoLocalizations)!;
  }

  String get title {
    return Intl.message(
      'Hello World',
      name: 'title',
      desc: 'Title',
      locale: localeName,
    );
  }
}
  1. Create delegate:
dart
class DemoLocalizationsDelegate extends LocalizationsDelegate<DemoLocalizations> {
  const DemoLocalizationsDelegate();

  
  bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);

  
  Future<DemoLocalizations> load(Locale locale) => DemoLocalizations.load(locale);

  
  bool shouldReload(DemoLocalizationsDelegate old) => false;
}
  1. Generate ARB files:
bash
dart run intl_translation:extract_to_arb --output-dir=lib/l10n lib/main.dart
dart run intl_translation:generate_from_arb --output-dir=lib/l10n lib/main.dart lib/l10n/intl_*.arb
  1. 添加依赖(与gen-l10n相同)
  2. 创建本地化类:
dart
class DemoLocalizations {
  DemoLocalizations(this.localeName);

  static Future<DemoLocalizations> load(Locale locale) {
    final String name = Intl.canonicalizedLocale(locale.toString());
    return initializeMessages(name).then((_) => DemoLocalizations(name));
  }

  static DemoLocalizations of(BuildContext context) {
    return Localizations.of<DemoLocalizations>(context, DemoLocalizations)!;
  }

  String get title {
    return Intl.message(
      'Hello World',
      name: 'title',
      desc: 'Title',
      locale: localeName,
    );
  }
}
  1. 创建代理类:
dart
class DemoLocalizationsDelegate extends LocalizationsDelegate<DemoLocalizations> {
  const DemoLocalizationsDelegate();

  
  bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);

  
  Future<DemoLocalizations> load(Locale locale) => DemoLocalizations.load(locale);

  
  bool shouldReload(DemoLocalizationsDelegate old) => false;
}
  1. 生成ARB文件:
bash
dart run intl_translation:extract_to_arb --output-dir=lib/l10n lib/main.dart
dart run intl_translation:generate_from_arb --output-dir=lib/l10n lib/main.dart lib/l10n/intl_*.arb

Custom Localizations

自定义本地化

For maximum simplicity:
dart
class DemoLocalizations {
  DemoLocalizations(this.locale);

  final Locale locale;

  static DemoLocalizations of(BuildContext context) {
    return Localizations.of<DemoLocalizations>(context, DemoLocalizations)!;
  }

  static const _localizedValues = <String, Map<String, String>>{
    'en': {'title': 'Hello World'},
    'es': {'title': 'Hola Mundo'},
  };

  String get title {
    return _localizedValues[locale.languageCode]!['title']!;
  }
}
适用于极简场景:
dart
class DemoLocalizations {
  DemoLocalizations(this.locale);

  final Locale locale;

  static DemoLocalizations of(BuildContext context) {
    return Localizations.of<DemoLocalizations>(context, DemoLocalizations)!;
  }

  static const _localizedValues = <String, Map<String, String>>{
    'en': {'title': 'Hello World'},
    'es': {'title': 'Hola Mundo'},
  };

  String get title {
    return _localizedValues[locale.languageCode]!['title']!;
  }
}

Best Practices

最佳实践

  1. Use gen-l10n for new projects - simpler, safer, better tooling
  2. Add descriptions to ARB entries - provides context for translators
  3. Format numbers/dates with format types - automatic locale handling
  4. Test all locales - verify formatting, RTL, and translations
  5. Use pluralization - handle count variations correctly
  6. Keep messages short - easier to translate, more consistent
  7. Don't concatenate strings - use placeholders instead
  8. Enable nullable-getter to reduce null checks in user code
  1. 新项目使用gen-l10n - 更简单、安全,工具支持更完善
  2. 为ARB条目添加描述 - 为翻译人员提供上下文信息
  3. 使用格式类型格式化数字/日期 - 自动适配Locale
  4. 测试所有Locale - 验证格式、RTL(从右到左)布局和翻译内容
  5. 使用复数处理 - 正确处理数量变化
  6. 保持消息简短 - 更易翻译,一致性更强
  7. 不要拼接字符串 - 改用占位符
  8. 启用可空getter - 减少用户代码中的空检查

Resources

资源

references/

references/

l10n-config.md - Complete reference for
l10n.yaml
configuration options, including output directories, code generation settings, and locale handling.
arb-format.md - Comprehensive guide to ARB file format, covering simple messages, placeholders, plurals, selects, and metadata.
number-date-formats.md - Number and date formatting reference with format types, patterns, and locale-specific examples.
l10n-config.md -
l10n.yaml
配置选项的完整参考,包括输出目录、代码生成设置和Locale处理。
arb-format.md - ARB文件格式的全面指南,涵盖简单消息、占位符、复数、选择器和元数据。
number-date-formats.md - 数字和日期格式化参考,包含格式类型、模式和Locale特定示例。

assets/

assets/

Example templates and boilerplate code can be added here for common internationalization patterns.
此处可添加常见国际化模式的示例模板和样板代码。

When to Use This Skill

适用场景

Use this skill when:
  • Adding localization support to a new Flutter app
  • Translating existing Flutter app to multiple languages
  • Configuring number/date formatting for different locales
  • Setting up RTL (right-to-left) language support
  • Implementing locale-specific layouts or widgets
  • Managing ARB files and translations
  • Troubleshooting localization issues
  • Adding custom language support beyond built-in locales
  • Optimizing app bundle size with deferred loading
在以下场景中使用本指南:
  • 为新Flutter应用添加本地化支持
  • 将现有Flutter应用翻译为多语言
  • 为不同Locale配置数字/日期格式化
  • 设置RTL(从右到左)语言支持
  • 实现Locale特定的布局或组件
  • 管理ARB文件和翻译内容
  • 排查本地化问题
  • 添加内置Locale之外的自定义语言支持
  • 通过延迟加载优化应用包大小