帮助中心

Flutter 本地化:ARB 文件、Intl 与自动化

Flutter 内置的本地化系统使用应用资源包(ARB)文件和 intl 包,支持任意语言的原生体验。本指南涵盖从项目设置、ARB 格式细节,到语言切换、复数形式处理及使用 l10n.dev 自动翻译的所有内容。

什么是 Flutter 本地化?

Flutter 本地化是官方推荐的多语言和多地区适配方案。它依赖 ARB 文件存储翻译字符串,并通过 flutter_gen 代码生成器生成类型安全的 Dart 访问器。运行时,Flutter 根据设备语言环境自动选择对应的 ARB 文件——切换语言时无需重启。

项目设置

Flutter 的本地化流程由两个配置文件驱动:pubspec.yaml 和 l10n.yaml。在 pubspec.yaml 中启用代码生成,并指定 ARB 文件目录。

1. 更新 pubspec.yaml

添加 flutter_localizations 和 intl 依赖,启用 generate 标志,让 Flutter 自动从 ARB 文件生成 Dart 本地化类。

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any

flutter:
  generate: true

2. 创建 l10n.yaml

在项目根目录放置 l10n.yaml 文件,配置 ARB 目录、模板文件和生成的输出文件名。

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

ARB 文件格式

ARB(应用资源包)是一种基于 JSON 的格式,专为 Flutter 国际化设计。每个键对应一个可翻译字符串,带 @ 前缀的可选元数据键包含描述、占位符定义和上下文信息,供译者参考。

  • @@locale: 声明文件的语言环境(例如 "en"、"fr"、"zh_CN")。l10n.dev 会自动更新为目标语言代码。
  • @@last_modified: 最后修改时间戳。l10n.dev 在生成翻译文件时会自动设置为当前 UTC 时间戳。
  • @key 元数据: 描述、示例和占位符等元数据默认不翻译,保持不变以保护译者上下文。若需翻译元数据,可启用 translateMetadata 设置。
  • 占位符与 ICU 消息: 字符串可包含命名占位符({name})和 ICU 消息语法,用于复数和选择,翻译时均能正确保留。

源 ARB 文件(英文)

{
  "@@locale": "en",
  "@@last_modified": "2026-01-15T10:30:00Z",

  "appTitle": "My App",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Welcome, {name}!",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{No unread messages} =1{1 unread message} other{{count} unread messages}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

翻译后的 ARB 文件(法文)

翻译后,界面字符串已本地化,元数据结构保持完整。l10n.dev 会自动更新 @@locale 和 @@last_modified。

{
  "@@locale": "fr",
  "@@last_modified": "2026-01-15T10:30:01Z",

  "appTitle": "Mon Application",
  "@appTitle": {
    "description": "The title of the application"
  },

  "welcome": "Bienvenue, {name} !",
  "@welcome": {
    "description": "Welcome message shown on the home screen",
    "placeholders": {
      "name": {
        "type": "String",
        "example": "Alice"
      }
    }
  },

  "unreadMessages": "{count, plural, =0{Aucun message non lu} =1{1 message non lu} other{{count} messages non lus}}",
  "@unreadMessages": {
    "description": "Number of unread messages",
    "placeholders": {
      "count": {
        "type": "int"
      }
    }
  }
}

文件命名规范

ARB 文件遵循简单命名规则:前缀(默认 app_)+ 语言环境代码 + .arb 后缀。Flutter 和 l10n.dev 使用下划线分隔语言和地区代码。

ARB 文件使用下划线而非连字符——写成 app_en_US.arb 和 app_zh_CN.arb,而非 app_en-US.arb 或 app_zh-CN.arb。
# Default pattern (recommended)
app_en.arb
app_fr.arb
app_en_US.arb          # Locale with region (underscore format)
app_zh_CN.arb          # Chinese Simplified

# Custom prefix patterns also supported
my_app_en.arb
my_app_fr.arb

# Note: ARB files use underscores, not hyphens
# ✓  app_en_US.arb
# ✗  app_en-US.arb

项目结构

将所有 ARB 文件放在 lib/ 目录下的专用 l10n 文件夹中。Flutter 代码生成器会根据 l10n.yaml 中的 arb-dir 设置自动识别并生成可用的 Dart 类。

lib/
├── l10n/
│   ├── app_en.arb        ← Source (English)
│   ├── app_fr.arb        ← French
│   ├── app_de.arb        ← German
│   ├── app_ja.arb        ← Japanese
│   ├── app_zh_CN.arb     ← Chinese Simplified
│   └── app_es.arb        ← Spanish
├── main.dart
└── ...

# Generated output (do not edit manually)
.dart_tool/
└── flutter_gen/
    └── gen_l10n/
        └── app_localizations.dart

初始化

将生成的 Dart 本地化类与 MaterialApp 绑定,提供 localizationsDelegates 和 supportedLocales。Flutter 会根据设备语言环境解析正确的 ARB 数据。

MaterialApp 设置

传入四个必需的委托——生成的 AppLocalizations.delegate 及 Flutter SDK 的三个委托,列出应用支持的所有语言环境。可在任何 Widget 树中通过 AppLocalizations.of(context)! 访问翻译字符串。

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',

      // Required delegates
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],

      // Supported locales
      supportedLocales: AppLocalizations.supportedLocales,

      home: const HomePage(),
    );
  }
}

// Use in a widget
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;

    return Scaffold(
      appBar: AppBar(title: Text(l10n.appTitle)),
      body: Center(child: Text(l10n.welcome('Alice'))),
    );
  }
}

运行时切换语言

Flutter 允许通过更新 MaterialApp 的 locale 属性在运行时切换语言。常见做法是在 StatefulWidget 或状态管理中保存 Locale,并提供回调修改它。Widget 树会自动使用新语言重建。

// Manage locale state at the app level
class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Locale _locale = const Locale('en');

  void _changeLocale(Locale locale) {
    setState(() => _locale = locale);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      locale: _locale,
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: AppLocalizations.supportedLocales,
      home: SettingsPage(onLocaleChange: _changeLocale),
    );
  }
}

// Language selector widget
class LanguageSelector extends StatelessWidget {
  final void Function(Locale) onLocaleChange;

  const LanguageSelector({super.key, required this.onLocaleChange});

  @override
  Widget build(BuildContext context) {
    return DropdownButton<Locale>(
      value: Localizations.localeOf(context),
      items: AppLocalizations.supportedLocales
          .map((locale) => DropdownMenuItem(
                value: locale,
                child: Text(locale.toLanguageTag()),
              ))
          .toList(),
      onChanged: (locale) {
        if (locale != null) onLocaleChange(locale);
      },
    );
  }
}

复数处理

Flutter 在 ARB 文件中使用 ICU 消息语法处理复数。intl 包支持所有 CLDR 复数类别,自动根据目标语言规则应用正确形式。

  • 在 ARB 字符串值中使用 {count, plural, =0{...} =1{...} other{...}} 语法。
  • 在 @key 元数据中声明 count 占位符,类型为 int。
  • l10n.dev 为每个目标语言自动生成所有必要的复数形式,包括阿拉伯语、俄语和波兰语等复杂语言,无需手动干预。
{
  "cartItems": "{count, plural, =0{Your cart is empty} =1{1 item in your cart} other{{count} items in your cart}}",
  "@cartItems": {
    "description": "Cart item count",
    "placeholders": {
      "count": { "type": "int" }
    }
  },

  "daysLeft": "{days, plural, =1{1 day left} other{{days} days left}}",
  "@daysLeft": {
    "description": "Days remaining",
    "placeholders": {
      "days": { "type": "int" }
    }
  }
}

l10n.dev 的完整 ARB 支持

l10n.dev 专为 Flutter ARB 工作流设计。上传源 ARB 文件,即可获得准确且结构正确的翻译文件:

  • 自动元数据更新: @@locale 自动更新为目标语言代码,@@last_modified 自动设置为当前 UTC 时间戳。
  • 元数据翻译控制: 默认情况下,@key 元数据(描述、示例、上下文)不翻译,保持译者注释完整。启用 translateMetadata 设置可同步翻译这些内容。
  • 自定义文件前缀: 支持任意命名模式,如 app_en.arb、my_app_en_US.arb、strings_fr.arb 等。
  • 下划线语言环境格式: ARB 语言环境代码使用下划线(en_US、zh_CN)而非连字符,l10n.dev 正确处理,生成文件可直接用于 Flutter 项目。
  • 复数形式支持: 根据 CLDR 规则为每个目标语言生成 ICU 复数形式,翻译后无需手动调整复数。

使用 npm 自动化翻译

使用 ai-l10n npm 包可从命令行或 CI/CD 流水线翻译源 ARB 文件。安装一次,即可一键翻译任意多语言。

# Install the CLI
npm install ai-l10n

# Translate your source ARB to multiple languages
npx ai-l10n translate lib/l10n/app_en.arb \
  --languages fr,de,ja,zh_CN,es,ko

集成到 Flutter 构建流程中

您可以将 ai-l10n 直接集成到 Flutter 构建流程中,确保在应用编译前翻译始终保持最新。两种常见的方法是使用 package.json 脚本或 Makefile。

通过 package.json 脚本

添加一个翻译脚本,并利用 npm 的 prebuild 生命周期钩子,在每次构建前自动运行它。运行 npm run build:android(或 build:ios / build:web)时,ai-l10n 将首先执行翻译,然后再交给 Flutter 进行构建。

{
  "scripts": {
    "translate": "ai-l10n translate lib/l10n/app_en.arb --languages fr,de,ja,zh_CN,es,ko --update",
    "prebuild": "npm run translate",
    "build:android": "flutter build apk",
    "build:ios": "flutter build ios",
    "build:web": "flutter build web"
  }
}

通过 Makefile

如果您的团队使用 Make,请声明一个翻译目标(target),并使每个构建目标都依赖于它。运行 make build-android(或 build-ios / build-all)时,会在调用 flutter build 之前翻译所有目标语言。

LANGUAGES = fr,de,ja,zh_CN,es,ko

translate:
	npx ai-l10n translate lib/l10n/app_en.arb --languages $(LANGUAGES) --update

build-android: translate
	flutter build apk

build-ios: translate
	flutter build ios

build-web: translate
	flutter build web

build-all: translate
	flutter build apk
	flutter build ios
	flutter build web

有关 CI/CD 集成、增量更新、多文件批量翻译及 GitHub Actions 工作流示例,请参见 本地化自动化指南。

VS Code 扩展

l10n.dev VS Code 扩展将 Flutter ARB 翻译功能直接带入编辑器。右键任意 ARB 文件,即可在 VS Code 内翻译到目标语言。

VS Code 中的使用方法:

  1. 在编辑器中打开源 ARB 文件(例如 app_en.arb)。
  2. 右键编辑器,选择“Translate JSON”。
  3. 选择一个或多个目标语言(如法语、日语、德语)。
  4. 扩展会在源文件旁生成本地化 ARB 文件,自动更新 @@locale 和 @@last_modified。

演示示例

以下是在 VS Code 中将 Flutter ARB 文件翻译成乌兹别克语的实时示例:

Flutter ARB localization in VS Code

开始本地化你的 Flutter 应用

准备好面向全球用户了吗?你可以直接在 l10n.dev 工作区翻译 ARB 文件,使用 npm CLI 自动化,或在 VS Code 内完成翻译: