Flutterに入門しました。
サンプルアプリを動かしてみたあと、「とりあえず多言語化対応はどうやるのかな」とAndroidのvalues/strings.xmlみたいなものを念頭に置きながら調べ始めて、最終的に到達した結論を書き残しておきます。
三日ぐらいしかいじってないので、ぼけてるところがあればツッコミお願いします。
Flutterで多言語化対応するには
まず、Flutter/Dartの開発系には文字列リソースという基本的な仕組みはないようです。
Flutter公式では以下のガイドラインが掲載されています。
https://flutter.io/tutorials/internationalization/
リンク先をざっと眺めて欲しいのですが、つまるところMapにKVペアを突っ込んで対応する文字列を返すコードを書け、と言うことになります。
さすがにこれはいくら何でもアレでしょう、ということで、Dart intl toolsというものが用意されていることがAppendixに書いてあります。本稿では、このツールの使い方を説明します。
Dart intl toolsとは
Dartコマンドラインで動く文字列リソースの加工ツールです。
- dartファイル内の国際化リソースをARBファイルに抽出する。
- ARBファイルを元に対応するdartコードを生成する。
の二つのツールからなっています。
その前に
Android StudioのNew Flutter Projectで作るサンプルアプリを元に進めていきます。
完成品はこちらに(github)
まず、パッケージをプロジェクトに追加します。
dependencies:
flutter_localizations:
sdk: flutter
intl:
intl_translation:
Dependenciesセクションに上の四行を追記します。
次に、lib/l10nディレクトリを掘り、以下のファイルを追加します。
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:intl/intl.dart';
import 'messages_all.dart';
class Strings {
static Future<Strings> load(Locale locale) {
final String name = locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final String localeName = Intl.canonicalizedLocale(name);
// ignore: strong_mode_uses_dynamic_as_bottom
return initializeMessages(localeName).then((Null _) {
Intl.defaultLocale = localeName;
return new Strings();
});
}
static Strings of(BuildContext context) {
return Localizations.of<Strings>(context, Strings);
}
static final Strings instance = new Strings();
// TODO 追加すべき文言
String get title => Intl.message('Flutter Demo Home Page', name: "title");
String get message => Intl.message('You have pushed the button this many times:', name: "message");
}
この時点で、importやinitializeMessages()が解決しませんが、問題ありません。
TODOコメントの後が、必要に応じて追加すべき文言となります。
ARBファイルのエクスポート
プロジェクトのルートで以下のコマンドを実行します。
$ flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/l10n/Strings.dart
これによって、lib/l10n/Strings.dart 内のIntl.message()呼び出しが抽出されて、intl_message.arbが出力されます。
{
"@@last_modified": "2018-03-04T02:14:41.057019",
"title": "Flutter Demo Home Page",
"@title": {
"type": "text",
"placeholders": {}
},
"message": "You have pushed the button this many times:",
"@message": {
"type": "text",
"placeholders": {}
}
}
これを元に以下の様なファイルを作成します。
{
"title": "フラッターデモホームページ",
"message": "ボタンを押した回数がここに表示されます"
}
ARBからdartコードの生成
ここで、以下のコマンドを実行します。
$ flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/l10n/Strings.dart lib/l10n/intl_messages.arb lib/l10n/intl_ja.arb
これによって、以下のファイルが生成されます。
- messages_all.dart
- messages_ja.dart
- messages_messages.dart
これらのファイルは DO NOT EDIT とあるので、編集してはいけません。
この時点で、先のビルドエラーは消えるはずです。
呼び出し側の設定
以下の修正を行います。
import 'dart:async';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'l10n/Strings.dart';
class _MyLocalizationsDelegate extends LocalizationsDelegate<Strings> {
const _MyLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en','ja'].contains(locale.languageCode);
@override
Future<Strings> load(Locale locale) => Strings.load(locale);
@override
bool shouldReload(_MyLocalizationsDelegate old) => false;
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
localizationsDelegates: [
const _MyLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', ''),
const Locale('ja', ''),
],
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
MaterialAppのパラメータに、localizationsDelegatesとsupportedLocalesを追加します。
ここまでで準備は終わり。文字列の呼び出しを修正します。
appBar: new AppBar(
title: new Text(Strings.of(context).title),
),
new Text(
Strings.of(context).message,
),
Strings.of(context).[id] の形で文字列を呼び出すことが出来ます。
文言の管理
この後の文言の管理手順としては
- Strings.dart に項目を追加
- ARBに変換
- intl_ja.arb に日本語翻訳を追加
- dartを生成
- 呼び出す
となります。
全部手作業でやるよりは少しはマシになったと思われます。
困った時は
Package追加した時、Android Studioの上の方に'get package'と出るので、クリックしましょう。
その際にエラーが出る場合は、FLUTTER_ROOTの設定し忘れかもしれません。
2018/03/04現在のFlutter インストールガイドではFLUTTER_ROOTへの言及がないので、設定しておきましょう。
(Flutterをインストールしたディレクトリを設定します)
参考) flutter projectでpub runコマンドが打てない時の対処法
https://qiita.com/konifar/items/d93e20ac0461e58a5247
参考リンク
Internationalizing Flutter Apps (公式ローカライゼーションのガイド)
https://flutter.io/tutorials/internationalization/#loading-and-retrieving
github dart-lang/intl_translation (ツールのソース)
https://github.com/dart-lang/intl_translation
github konifar/droidkaigi2018-flutter (現時点で日本語化されている数少ないFlutterアプリ)
https://github.com/konifar/droidkaigi2018-flutter
本記事のサンプルソース
https://github.com/jiro-aqua/flutter-localization
免債
Windows/Android環境でしか動かしていません。
感想
当分はポチポチ遊びながら、プロダクト投入可能なラインを探っていくことになるのでしょう。面白そうなので、今後に期待したいと思います。
以上です。