【Dart / Flutter】Slangで国際化対応する
はじめに
こんにちは!Altive株式会社Flutterアプリ開発者の中村です。
業務内でSlangを使用した国際化対応を行いましたので、導入方法や注意点など簡単にご紹介させていただきます🌏
本記事では以下の表示になるようにご説明します📝
en | jp |
---|---|
Slangとは
またFlutterに依存しないため、どんなDartプロジェクトでも使用可能です。
依存関係の追加
dependencies:
flutter_localizations:
sdk: flutter
slang: <version>
slang_flutter: <version> # Flutterアプリで使用する場合は追加
dev_dependencies:
build_runner: <version> # build_runnerを使用する場合のみ追加
slang_build_runner: <version> # build_runnerを使用する場合のみ追加
JSONファイルの作成からDartファイル生成まで
ARBからJSONに移行する場合
すでに他の手段で多言語化をしていてARBファイルがある場合は、以下のコマンドを叩けば簡単に移行できます。
dart run slang migrate arb source.arb destination.json
JSONファイル作成
各ロケールのJSONファイルを作成します。
ファイルの形式はJSON, YAML, CSV, ARBのどれでも構いませんが、今回はJSONで作成します。
ファイルの配置場所
Getting Startedによると
Most common i18n directories are
assets/i18n
andlib/i18n
.
とのことなので、lib/i18n
ディレクトリを作成してこちらに配置しました。
ちなみにデフォルトではJSONファイルの配置場所は特に指定がないので、別のディレクトリ名でも大丈夫です。
ただし、ファイル名のパターンはデフォルトで.i18n.json
となっているので、strings_en.i18n.json
のようにする必要があります。
今回はen
とjp
二つのロケール用のファイルを作成しました。
{
"greeting" : "Hello!",
"welcomeMessage": "Welcome to our application.",
"settings": {
"language": "Language",
"theme": "Theme",
"notification": "Notifications"
}
}
{
"greeting": "こんにちは!",
"welcomeMessage": "私たちのアプリケーションへようこそ",
"settings": {
"language": "言語",
"theme": "テーマ",
"notification": "通知"
}
}
コマンドを叩いてDartファイルを生成
各ロケールのJSONファイルを作成したら、コマンドを叩いてDartファイルを生成します。
build_runner
よりもslang
の方が高速なのでおすすめです。
-
slang
を使用する場合
dart run slang
-
build_runner
を使用する場合
dart run build_runner build -d
コマンドを叩くと、ディレクトリ指定がない場合はJSONファイルと同じディレクトリにstrings.g.dart
が生成されます🎉
これでstrings.g.dart
をimportしてDart/Flutterプロジェクトで使えるようになりました!
以下の例だと、言語がenの時にnotification
、jpの時には通知
と表示されます。
import 'i18n/strings.g.dart';
String notification = t.settings.notification;
slang.yaml(build.yaml)について
基本的にslang.yamlがなくても使用できるのですが、ファイル名のパータン変更などしたい時に作成する必要があります。
デフォルト設定から変更することがよくありそうな項目をいくつか紹介します。
- base_locale
デフォルトではen
が設定されていますが、その他言語にしたい場合はここで変更できます。
base_localeで設定しているロケールのJSONファイルが用意されていないと怒られるので、en
が必要なければ他のロケールを指定してください。 - input_directory
JSONファイルの置き場所を指定できます。 - input_file_pattern
デフォルトでは.i18n.json
なので、YAMLファイルを使用したい時に.i18n.yaml
に変更する等で必要になります。 - output_directory
strings.g.dart
の出力先を指定できます。
その他設定できる項目についてはConfigurationをご確認ください🙏🏻
デバイスのロケール情報を取得する
デバイスのロケール情報を取得してアプリに反映させるために、いくつか設定することがあります。
- LocaleSettings.useDeviceLocaleを実行してデバイスのロケールで初期化する
- TranslationProviderでラップする
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'i18n/strings.g.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// デバイスのロケールで初期化
LocaleSettings.useDeviceLocale();
// TranslationProviderでラップ
runApp(TranslationProvider(child: const MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
// TranslationProviderをロケールにセット
locale: TranslationProvider.of(context).flutterLocale,
supportedLocales: AppLocaleUtils.supportedLocales,
localizationsDelegates: GlobalMaterialLocalizations.delegates,
home: const MyHomePage(),
);
}
}
デバイスのロケール情報が取得できるようになったら、実際に使ってみましょう!
はじめにでご紹介した簡単なFlutterアプリで使用する例です。
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
Widget build(BuildContext context) {
final t = Translations.of(context);
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(t.greeting),
Text(t.welcomeMessage),
const Gap(30),
Container(
margin: const EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.settings),
const Gap(10),
TextButton(
onPressed: () {}, child: Text(t.settings.language)),
TextButton(onPressed: () {}, child: Text(t.settings.theme)),
TextButton(
onPressed: () {}, child: Text(t.settings.notification)),
],
),
),
],
),
),
);
}
}
さいごに
Slangで簡単に国際化対応ができると効率的にアプリ開発ができてありがたいですね🚀
記事を最後までご覧いただきありがとうございました🙏
Discussion