Flutter

Flutter Internationalization(多言語化)をしてみた

Flutterで多言語化をしてみたので、その方法を書き留めておきます。

試してみたのは、タイトルやボトムナビゲーションバーの名称と、画面上に表示されるデータ(SQLiteに格納)を端末の言語設定にもとづいて言語切り替えすること。

本記事のソースコードはGitHubで公開していますので、必要であれば参照してください。

多言語化パッケージを追加する

flutter_localizationsを使うために、pubspec.yamlに多言語化パッケージを追加します。追加するパッケージは、

  • flutter localizations
  • intl package

の二つ。

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations: # for internationalization
    sdk: flutter
  intl: ^0.17.0

また、flutterの領域に、generate: trueを追加します。

flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true
  generate: true # flutter localizations

追加したらpub getを実行します。

l10n.yamlを新規作成する

l10n.yamlという名前がついたファイルをrootディレクトリに新規作成します。
l10n.yamlの内容は

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

記載されている意味は、

  • 辞書化するファイルを${FLUTTER_PROJECT}/lib/l10n ディレクトリに配置する
  • テンプレートファイルはapp_en.arb
  • 翻訳した結果はapp_localizations.dartに記載される

という意味らしいです。

辞書ファイルを作成する

${FLUTTER_PROJECT}/lib/l10nに翻訳したい言語の数だけ辞書ファイルを作成します。

まずはテンプレートファイルであるapp_en.arbを新規作成し、lib/l10nディレクトリに配置します。

app_en.arb

{
    "applicationTitle": "Flutter Localization Demo",
    "@applicationTitle": {"description": "This is English version title."},
    "home": "Home",
    "@home": {},
    "search": "Search",
    "@search": {},
    "bookmark": "Bookmark",
    "@bookmark": {}
}

つぎに日本語のためにapp_ja.arbを新規作成し、lib/l10nディレクトリに配置します。

app_ja.arb

{
    "applicationTitle": "Flutter多言語デモ",
    "@applicationTitle": {"description": "これは日本語版のアプリ名です。"},
    "home": "ホーム",
    "@home": {},
    "search": "検索",
    "@search": {},
    "bookmark": "ブックマーク",
    "@bookmark": {}
}

main.dartを書く

次の二つのライブラリをimportします

main.dart

import 'package:flutter_localizations/flutter_localizations.dart';

MaterialAppに次のコードを追加します

return MaterialApp(
  title: 'Localizations Sample App',
  localizationsDelegates: const [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: const [
    Locale('en', ''), // English, no country code
    Locale('ja', ''), // Japanese, no country code
  ],
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  home: const MyHomePage(),
);

ここでアプリを一度実行します。実行すると下記ディレクトリにファイルが生成されます。

${FLUTTER_PROJECT}/.dart_tool/flutter_gen/gen_l10n.

ファイル生成を確認できたらさらにコードを追加します。

main.dart

app_localization.dartをimportします。

import 'package:flutter_gen/gen_l10n/app_localizations.dart';

MaterialAppに下記1行を追加します。

return const MaterialApp(
  title: 'Localizations Sample App',
  localizationsDelegates: [
    AppLocalizations.delegate, // Add this line
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
//以下省略

AppBar

appBar: AppBar(
  title: Text(AppLocalizations.of(context)!.applicationTitle),
),

AppLocalizations.of(context)!.applicationTitle では、app_en.arbに定義されたapplicationTitleの文字列が言語設定に基づいて返されます。

今回のサンプルでは、

  • “en”ならFlutter Localization Demo
  • “ja”ならFlutter多言語デモ

のいずれかが表示されます。

後は翻訳したいところに上記を適用していけばよいので、

bottomNavigationBar

bottomNavigationBar: BottomNavigationBar(
  items: [
    BottomNavigationBarItem(
        icon: const Icon(Icons.home),
        label: AppLocalizations.of(context)!.home),
    BottomNavigationBarItem(
        icon: const Icon(Icons.search),
        label: AppLocalizations.of(context)!.search),
    BottomNavigationBarItem(
        icon: const Icon(Icons.bookmark),
        label: AppLocalizations.of(context)!.bookmark),
  ],
),

のように書けます。

SQLiteからデータを取得する

SQLiteのデータ作成や取得のふるまいはsqlite_helper.dartに定義しました。

テーブルの設計はこんな感じです(この設計はベストではないかも…です)

データ作成・取得のふるまい(SQLiteの取り扱い)はサンプルソースコードを参照してください。

SQLiteのデータ取得のメソッドをmain.dartから呼び出します。その際に、現在の端末の言語設定を取得してから、当該言語のデータを取りに行くように書きました。

言語設定を取得するには

//get a current language setting
Locale locale = Localizations.localeOf(context);
String languageCode = locale.languageCode;
debugPrint(languageCode);

でできます。

あとは、変数languageCodeに格納された”en”や”ja”をデータベースヘルパーに渡してあげれば、言語ごとのデータを取得できます。

例えばデータ取得は

sqlite_helper.dart

//get data from sqlite table
Future<List<Map>> dataSelect(String locale) async {
  String sqlQuery;

  var databasesPath = await getDatabasesPath();
  String path = join(databasesPath, 'demo.db'); //import path/path.dart
  Database database = await openDatabase(path);

  // Get the records
  if (locale == "en") {
    sqlQuery = 'SELECT * FROM vehicle_master';
  } else {
    sqlQuery = 'SELECT * FROM vehicle_other where language = "$locale"';
  }
  List<Map> list = await database.rawQuery(sqlQuery);

  await database.close();
  return list;
}

引数でlocaleを渡します。

ちなみにデータを取得する処理はすべて非同期のため、main.dartではFutureBuilderを使います。

実行

アプリを実行すると下記のディレクトリに辞書ファイルが生成されます。

${FLUTTER_PROJECT}/.dart_tool/flutter_gen/gen_l10n

以上、Flutter多言語化のサンプルでした。

おわり。