JINMUSOFTWARE

Flutterアプリの国際化

Translation

flutterアプリの国際化について

flutterは国際化に対応できる仕組みがあるようです。

とても簡単そうです(人による)。

なにもしなければflutterは英語のみサポートします。

せっかくですからアプリは国際化してみんなに使ってもらいましょう。

本ページでは、英語、日本語、台湾華語をターゲットに説明します。

翻訳対象

翻訳する対象がいくつかありそれぞれに手順があります。

今回参考になりそうな以下の3つのものをローカライズしていきたいと思います。

  • Widget
  • IntlのDateformatの日付形式
  • メッセージ(文字列)

動作環境

  • Mac mini – Apple M4
  • macOS Sequoia 15.4.1
  • flutter 3.29.3
  • flutter_localizations
  • intl any

Widgetのローカライズ

Widgetのローカライズです。

コンテキストメニューやカレンダーなどの文字列がローケールに合わせて変化します。

コンテキストメニューは、テキストフィールドなどのポップアップで表示されますね。

プロジェクトの準備

適当なプロジェクトに、「TextField」、「CalendarDatePicker」を追加しておいてください。

Widgetの表示部分がローカルの影響を受けているならなんでもいいです。

iPhoneの設定は日本語ですが、アプリの表示は英語ですね。

ではWidgetのローカライズに挑戦してみましょう。

Step

  • flutter_localizationsを追加する
  • flutter_localizationsをimportする
  • MaterialAppのプロパティに…
    • localizationsDelegatesを追加する
    • supportedLocalesを追加する
  • プラットフォームの言語を変えて動作を確認する

flutter_localizations の追加

https://api.flutter.dev/flutter/flutter_localizations flutter_localizations

それではインストールしてみましょう。

flutter pub add flutter_localizations --sdk=flutter

もしくは、YAML式記述子構文(The YAML formatted descriptor syntax)を使用して…

flutter pub add "flutter_localizations:{sdk: flutter}"

pubspec.yaml は以下のようになります。

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.8

  flutter_localizations:
    sdk: flutter

インストールオプション(–sdk=flutter)が付いていますね。

https://dart.dev/tools/pub/cmd/pub-add dart pub add

このオプションは、指定されたソースからパッケージを追加するものです。これはpub.devからではなくflutter SDKからのインストールであることを示しています。

そもそも「flutter_localizations」は、pub.devにはありませんでした。

pub.devには似た名前のライブラリ「flutter_localization」(末尾のsがない)があります。間違わないようにしましょう。

memo)flutter_localizationsのインストール時に、intlパッケージも同時にインストールする説明の記事が多かった印象です。intlは後で説明するarbファイルの日付等の表示で使用されているのかなと思っています。とりあえず今回のWidgetのローカライズ程度ではintlがなくとも動作しました。

Import

import 'package:flutter_localizations/flutter_localizations.dart'

localizationsDelegatesとsupportedLocalesの追加

return const MaterialApp(
  localizationsDelegates: [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],

  supportedLocales: [
    Locale('ja', 'JP'), // Japanese
    Locale('en', 'US'), // English
    Locale('zh', 'TW'), // Taiwan
  ],

  home: MyHomePage(),
);

Localeの文字列を間違ってはいけません。

Localeには、言語コード、国コードを指定します。他の参考書では言語コードだけ指定することが多いように感じました。

漢字圏の分類は複雑なようです。後でもう少し細かく指定する方法を記載します。

確認

さて、この時点でWidgetのローカライズの動作確認ができるはずです。Simulatorの言語を変更しながら確認してみましょう。

アプリのロケール、プラットフォームのロケールの確認コードは以下になります。

// 現在のアプリのロケール
Localizations.localeOf(context).toString();

// プラットフォーム
WidgetsBinding.instance.platformDispatcher.locale.toString();

コンテキストメニューもカレンダーの曜日の部分もローカライズできましたね。

Dateformatの日付形式のローカライズ

まずは、日付を表示してみましょう。

intlパッケージを使います。https://pub.dev/packages/intl

“Flutter Favorite” が付いていますね。とても有名なパッケージのようです。

日付の形式を見てみますと、日本のロケールでも米国風になっていますね。

intlもローカライズしていきましょう。

Step

  • intlを追加
  • importする
  • Intl.defaultLocale に現在のロケールを指定する
  • DateFormatで日付を表示する
  • プラットフォームの言語を変えて動作を確認する

インストール

flutter pub add intl:any

flutter_localizationと依存性関係があるためintlのバージョンはanyとする。

memo) ちなみに、flutter_localizationsをインストールした後にany付けずにintlをインストールした場合、pubspec.yamlには、intl:0.19.0と記されていました。

Import

import 'package:intl/intl.dart'; // DateFormat使いたいのです

intlのローカライズ

Intl.defaultLocale = Localizations.localeOf(context).toString();

日付表示

Text(DateFormat.yMEd().format(DateTime.now())),
Text(DateFormat.yMMMMEEEEd().format(DateTime.now())),

intlには表示形式がたくさんあるようですね。

確認

日付の形式がローカライズされましたね。

メッセージのローカライズ

文書の翻訳をローケールに合わせて表示します。

あらかじめ翻訳ファイルを用意しましょう。

使用する言語コード、国コード、文字コードは以下となります。

  • ja, JP
  • en, US
  • zh, TW, Hant

漢字圏には簡体字と繁体字の分類もあります。

  • Hans:簡体字
  • Hant:繁体字

Step

  • arbファイルを用意
  • l10n.yaml作成
  • generate: true
  • 生成ファイルをimport
  • localizationsDelegatesの修正
  • supportedLocalesの修正
  • ロケールされた文字列を出力して確認する

arbファイル

https://github.com/google/app-resource-bundle

arbファイルには翻訳情報を記述します。

「lib¥l10n」ディレクトリに保存します。

ファイル名規則

arbファイル名には規則があります。

アンダーバー「_」の後ろに言語コードを付けます。さらに必要な場合は国コードも追加します。

  • app_en.arb
  • app_ja.arb
  • app_zh_TW.arb
  • app_zh.arb

zh_TWを使用する場合、フォールバック用にzhが必要になります。

app_en.arb

{
  "@@locale": "en",
  "helloWorld": "Hello World",
  "@helloWorld": {
    "description": "A simple greeting message"
  },
  "message": "This is a message",
  "@message": {
    "description": "A simple message"
  },
  "greeting": "Hello {name}",
  "@greeting": {
    "description": "A greeting message with a name",
    "placeholders": {
      "name": {
        "type": "String"
      }
    }
  }
}
  • “greeting”にはプレースホルダーを使用しています

app_ja.arb

{
  "@@locale": "ja",
  "helloWorld": "こんにちは、世界!",
  "message": "これはメッセージです",
  "greeting": "こんにちは、{name}さん"
}

app_zh_TW.arb

{
  "@@locale": "zh_TW",
  "helloWorld": "哈囉世界",
  "greeting": "哈囉 {name}"
}
  • “message”の翻訳が無いですね。

app_zh.arb

{}
  • 今回このzhの翻訳データは使用しませんが、ファイルとして必要です。
  • 空の”{}”波括弧だけにしています。

app_zh.arbファイルが無いときの警告内容:

Arb file for a fallback, zh, does not exist, even though 
the following locale(s) exist: [zh_TW]. 
When locales specify a script code or country code, a 
base locale (without the script code or country code) should 
exist as the fallback. Please create a {fileName}_zh.arb 
file.

l10n.yaml

プロジェクトルートに「l10n.yaml」ファイルを作成しましょう。

https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization#configuring-the-l10n-yaml-file

リソースファイルである「arb」ファイルをもとに、dartファイルを生成しますが、「l10n.yaml」には、その設定を記述します。

arbファイルの場所やクラスファイルとして生成する場所など設定します。

l10n.yaml:

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

synthetic-package: false

デフォルトのファイルの生成先は、「.dart-tool」ディレクトリです。

どうやらそれは好ましくないとのことで生成時に警告が発生します。

警告内容:

Synthetic package output (package:flutter_gen) is deprecated: https://flutter.dev/to/flutter-gen-deprecation. In a future release, synthetic-package will default to false and will later be removed entirely.

重要な変更:

Localized messages are generated into source, not a synthetic package. https://docs.flutter.dev/release/breaking-changes/flutter-generate-i10n-source

synthetic-package: false」の設定することにより出力先を「arb-dir:」へ変更することができます。

flutterのupdateが進めばこの設定は不要になるでしょう。

output-dir: lib/l10n/output

生成ファイルの出力先の変更です。

生成されたファイルとarbファイルを分別するために「output」ディレクトリに設定しました。

pubspec.yamlの編集

pubspec.yamlに”generate: true”を追加します。

flutter:
  uses-material-design: true
  generate: true

“flutter pub get” で更新します。VSCodeは保存するだけで更新されますね。

pubspec.yaml を更新すると、翻訳データを保持したdartファイルが生成されます。

lib¥l10n¥outputにdartファイルが生成されていますので確認しましょう。

  • app_localizations_en.dart
  • app_localizations_ja.dart
  • app_localizations_zh.dart
  • app_localizations.dart

また、”flutter pub get” だけでなく、生成専用のコマンドもあります。

flutter gen-l10n

生成ファイルのImport

「app_localizations.dart」ファイルをimportします。

import 'l10n/output/app_localizations.dart';

localizationsDelegatesの修正

“AppLocalizations.delegate”を追加します。

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

supportedLocalesの修正

もう少し厳格にサポートするロケールを定義してみましょう。

言語コード、国コード、文字コードを指定します。

supportedLocales: const [
  Locale('ja', 'JP'), // Japanese
  Locale('en', 'US'), // English

  // Locale('zh', 'TW'), // Taiwan
  Locale.fromSubtags(
    languageCode: 'zh',
    scriptCode: 'Hant',
    countryCode: 'TW',
  ),
],

ロケールの文字列が次のように変わります。

zh_TW -> zh_Hant_TW

ロケールされた文字列の出力

Text(AppLocalizations.of(context).helloWorld),
Text(AppLocalizations.of(context).message),
Text(AppLocalizations.of(context).greeting('のりお')),

メソッドを使用して文書を出力しています。

翻訳文字列を準備しなかった場合はどうでしょうか?

このような場合はテンプレートである”app_en.arb”で定義した文字列が表示されます。

localizationsDelegates, supportedLocales の別記述

AppLocalizationsは元のリストを包含します。

以下のよに記述することも可能です。

return const MaterialApp(
  // ~~~
  localizationsDelegates: AppLocalizations.localizationsDelegates, 
  supportedLocales: AppLocalizations.supportedLocales,
  // ~~~
);

この場合、対応する言語は用意したarbファイルに依存します。

App Store(iOS)の対応

App Store でアプリの対応言語に対応する方法です。

2つ方法を見つけました。

flutter公式の対応方法と書籍にあった方法です。

xcodeでlocalization を追加する方法

https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization#localizing-for-ios-updating-the-ios-app-bundle

  • xcodeでプロジェクトを開きます
  • PROJECT RunnerのInfoタブを開きます
  • LocalizationsにLocalizationを追加するための「+」ボタンを押します
  • 言語リストが表示されますので、追加する言語を選択します。
    • Japanese(ja)でも選択してみましょう。
  • Finishボタンを押す
  • Localizationのリストに追加されていることを確認する

Info.plistを修正する方法

ios¥Runner¥Info.plistを開く

CFBundleLocalizationsを追加し。”ja”を追加する。

<key>CFBundleLocalizations</key>
<array>
    <string>ja</string>
</array>

参考

flutter公式にある国際化のページです。

https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization

ApplicationResourceBundleSpecification(arb) Wiki

https://github.com/google/app-resource-bundle/wiki/ApplicationResourceBundleSpecification

locale_names 1.1.1(ローカル文字列の参考)

https://pub.dev/packages/locale_names/example

https://ja.wikipedia.org/wiki/%E5%85%B1%E9%80%9A%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA