帮助中心

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

Flutter内置的本地化系统使用应用程序资源包(ARB)文件和intl软件包,以提供任何语言下的完全原生体验。本指南涵盖了从项目设置和ARB格式详情到语言切换、复数形式以及使用l10n.dev自动化翻译的所有内容。

什么是Flutter本地化?

Flutter本地化是为多种语言和地区适配应用程序的官方方法。它依赖ARB文件来存储翻译后的字符串,并使用flutter_gen代码生成器来生成类型安全的Dart访问器。在运行时,Flutter会根据设备区域设置选择正确的ARB文件——以编程方式切换区域设置时无需重启。

项目设置

Flutter的本地化管道由两个配置文件驱动:pubspec.yaml和l10n.yaml。在pubspec.yaml中启用代码生成,并将Flutter指向您的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(应用程序资源包)是一种专为Flutter国际化设计的JSON格式。每个键映射到一个可翻译的字符串,可选的元数据键(以@为前缀)包含描述、插值定义以及译员的上下文信息。

  • @@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文件(法语)

翻译后,UI字符串已本地化,而元数据结构保持完整。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

初始化

通过提供localizationsDelegates和supportedLocales,将生成的Dart本地化类与MaterialApp连接起来。Flutter随后将为设备区域设置解析正确的ARB数据。

MaterialApp设置

传入四个必需的代理——您生成的AppLocalizations.delegate加上三个Flutter SDK代理——并列出您的应用程序支持的每个区域设置。在组件树的任何位置使用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属性在运行时切换应用程序区域设置。一种常见的模式是将Locale保存在StatefulWidget或状态管理解决方案中,并公开一个回调来更改它。组件树会自动以新的区域设置重新构建。

// 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设置可将其与UI字符串一起翻译。
  • 自定义文件前缀: 支持任何命名模式——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脚本

添加一个translate脚本,并使用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,请声明一个translate目标,并使每个构建目标都依赖于它。运行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操作工作流程示例,请参阅本地化自动化指南。

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命令行界面进行自动化,或者直接在VS Code内进行翻译: