はじめに
こんにちは。OREOです。
本記事ではGemini APIを活用したモバイルアプリの多言語対応の実装について取り扱いたいと思います。
Flutter公式も推奨しているライブラリ”flutter_localizations”とGeminiAPIを組み合わせるような実装の流れになります。
導入手順
Geminiについて触れる前にFLutterプロジェクトの多言語化対応, すなわちflutter_localizationsの導入から解説を行なっていきます。
flutter_localizations
1. パッケージのインストール
pubspec.yaml
内のdepencies配下に下記の3つの記述を追加してください。
dependencies:
flutter:
sdk: flutter
flutter_localization: ^0.2.0 # 追加
intl: ^0.19.0 # 追加
# 省略~~~~~~~
flutter:
generate: true # 追加
パッケージのインストールについてはターミナルで下記を叩くだけでも大丈夫です。
$ flutter pub add flutter_localizations --sdk=flutter
$ flutter pub add intl
2. 言語設定ファイルの作成
プロジェクトのルートディレクトリに下記の内容でl10n.yaml
を追加してください。
arb-dir: lib/l10n # ARBファイルのパスの指定
template-arb-file: app_ja.arb # デフォルトの言語のARBファイルの指定
output-class: L10n # 言語を呼び出す時のクラス名
output-localization-file: app_localizations.dart # 自動生成されるローカライゼーションファイル名
ちなみにl10nはlocalizationの略語のようです。
3. 言語ファイルの作成
2の工程で指定したlib/l10nディレクトリ内に言語ファイルを作成します。
{
"@@locale": "ja",
"home": "ホーム",
"@home": {
"description": "home"
},
"setting": "設定",
"@setting": {
"description": "setting"
},
"profile": "プロフィール",
"@profile": {
"description": "profile"
},
"news": "お知らせ",
"@news": {
"description": "news"
},
"login": "ログイン",
"@login": {
"description": "login"
},
"logout": "ログアウト",
"@logout": {
"description": "logout"
}
}
4. localizationsファイルの自動生成
ターミナルで下記のファイルコマンドを叩きます。
$ flutter gen-l10n
すると.dart_tool/flutter_gen/gen_l10n
配下にapp_localizations.dart
とapp_localizations_ja.dart
が生成されます。
abstract class L10n {
L10n(String locale)
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
final String localeName;
static L10n? of(BuildContext context) {
return Localizations.of<L10n>(context, L10n);
}
static const LocalizationsDelegate<L10n> delegate = _L10nDelegate();
/// A list of this localizations delegate along with the default localizations
/// delegates.
///
/// Returns a list of localizations delegates containing this delegate along with
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
/// and GlobalWidgetsLocalizations.delegate.
///
/// Additional delegates can be added by appending to this list in
/// MaterialApp. This list does not have to be used at all if a custom list
/// of delegates is preferred or required.
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
<LocalizationsDelegate<dynamic>>[
delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
];
// 以下略
import 'app_localizations.dart';
/// The translations for Japanese (`ja`).
class L10nJa extends L10n {
L10nJa([String locale = 'ja']) : super(locale);
@override
String get home => 'ホーム';
@override
String get setting => '設定';
@override
String get profile => 'プロフィール';
@override
String get news => 'お知らせ';
@override
String get login => 'ログイン';
@override
String get logout => 'ログアウト';
}
5. MaterialAppに設定を追加
MaterialAppに以下の2行を追記します。
@override
Widget build(BuildContext context) {
return MaterialApp.router(
localizationsDelegates: L10n.localizationsDelegates, // 追加
supportedLocales: L10n.supportedLocales, // 追加
theme: ThemeData(useMaterial3: true, colorScheme: lightColorScheme),
darkTheme: ThemeData(useMaterial3: true, colorScheme: darkColorScheme),
routerConfig: goRouter,
);
}
L10nを使用するために
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
をMaterialAppを呼び出しているdartファイルへ追記します。
main.dartファイルである必要はないです。MaterialAppを呼び出しているところに追記してください。
6. アプリ側から呼び出し
4の工程で自動生成したファイルから文字列を呼び出します。
final l10n = L10n.of(context)!;
final menuList = [
l10n.profile,
l10n.news,
l10n.news,
l10n.login,
l10n.logout
];
ソースコード全体は下記です。
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class Page1 extends StatelessWidget {
const Page1({super.key});
@override
Widget build(BuildContext context) {
// l10nファイルの読み込みを行っている部分
final l10n = L10n.of(context)!;
final menuList = [
l10n.profile,
l10n.news,
l10n.news,
l10n.login,
l10n.logout
];
Widget listTile(String title) {
return Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
IconButton(
onPressed: () {},
icon: const Icon(Icons.arrow_forward_ios_outlined),
)
],
),
),
const Divider(
thickness: 1.0,
color: Color.fromARGB(255, 183, 180, 180),
),
],
);
}
return Scaffold(
appBar: AppBar(
title: const Center(child: Text('Gemini翻訳テスト')),
backgroundColor: Colors.amberAccent,
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: IconButton(
icon: const Icon(Icons.flag),
onPressed: () {},
),
),
],
),
drawer: Drawer(
child: ListView(
children: [
const Divider(
thickness: 1.0,
color: Color.fromARGB(255, 183, 180, 180),
),
...menuList.map(
(e) => listTile(e),
)
],
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: 0,
selectedFontSize: 10,
unselectedFontSize: 10,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: const Icon(Icons.home),
activeIcon: Container(
key: const Key('bottom_navigation_bar_home'),
margin: const EdgeInsets.fromLTRB(0, 0, 0, 4),
child: const Icon(Icons.home)),
label: l10n.home,
backgroundColor: Colors.red,
),
BottomNavigationBarItem(
icon: const Icon(Icons.settings),
activeIcon: Container(
key: const Key('bottom_navigation_bar_settings'),
margin: const EdgeInsets.fromLTRB(0, 0, 0, 4),
child: const Icon(Icons.settings)),
label: l10n.setting,
),
],
selectedItemColor: Theme.of(context).colorScheme.primary,
onTap: (int index) {
// context.replace(locationNames[index]);
},
),
);
}
}
初期画面 | ハンバーガーメニュー表示時 |
---|---|
![]() |
![]() |
これでflutter_localizationsの動作確認がきました。
Geminiの導入
次にGeminiを導入し多言語対応を行なっていきたいと思います。
1. Gemini API トークンを生成
Google AI for Developersのページからトークンを生成してください。
2. arb_translateをアクティブ化
ターミナルで下記のコマンドを叩き, arb_translateを有効化してください。
$ dart pub global activate arb_translate
3. トークンの設定
1の工程で取得したトークンを下記のコマンドを叩き, 環境変数に設定してください。
$ export ARB_TRANSLATE_API_KEY={your-api-key}
非推奨ではありますが, l10n.yamlに追記する方法もあります。
arb-dir: lib/l10n # ARBファイルを格納するディレクトリを指定します。
template-arb-file: app_ja.arb # テンプレートのARBファイルを指定します。デフォルトの言語のARBファイルを設定すると良いと思います。
output-class: L10n # 手順3-4で自動生成されるクラス名。設定しないとAppLocalizationsになります。
output-localization-file: app_localizations.dart # 手順3-4で自動生成される言語ファイル名。ローカライゼーションを使うときはこのファイルをインポートします。
arb-translate-api-key: your-api-key # 追記
4. 追加したい言語の空のarbファイルを作成
lib/l10n
に追加したい言語の言語キーを用いて空ファイルを作成してください。
例1) 英語の場合: app_en.arb
例2) インドネシア語の場合: app_id.arb
5. arbファイルをGeminiで自動生成
次にターミナルで下記のコマンドを叩きます。
$ arb_translate
すると4の工程で作成したからファイルに翻訳したものをGeminiが自動で追記してくれます。
{
"home": "Home",
"setting": "Settings",
"profile": "Profile",
"news": "News",
"login": "Login",
"logout": "Logout"
}
{
"home": "Beranda",
"setting": "Setelan",
"profile": "Profil",
"news": "Berita",
"login": "Login",
"logout": "Logout"
}
6. localizationsファイルの自動生成
ターミナルで下記のファイルコマンドを叩きます。
$ flutter gen-l10n
すると英語とインドネシア語のlocalizationsファイルが生成されます。(flutter_localizationsの4の工程と同じ)
import 'app_localizations.dart';
/// The translations for English (`en`).
class L10nEn extends L10n {
L10nEn([String locale = 'en']) : super(locale);
@override
String get home => 'Home';
@override
String get setting => 'Settings';
@override
String get profile => 'Profile';
@override
String get news => 'News';
@override
String get login => 'Login';
@override
String get logout => 'Logout';
}
import 'app_localizations.dart';
/// The translations for Indonesian (`id`).
class L10nId extends L10n {
L10nId([String locale = 'id']) : super(locale);
@override
String get home => 'Beranda';
@override
String get setting => 'Setelan';
@override
String get profile => 'Profil';
@override
String get news => 'Berita';
@override
String get login => 'Login';
@override
String get logout => 'Logout';
}
7. アプリ言語を変えて実行
初期画面
日本語 | 英語 | インドネシア語 |
---|---|---|
![]() |
![]() |
![]() |
ハンバーガーメニュー表示時
日本語 | 英語 | インドネシア語 |
---|---|---|
![]() |
![]() |
![]() |
これにてGeminiを用いた多言語化対応が実装できました!
さいごに
Gemini✖️Flutter についての発表などがあったGoogle I/O 2024。AIともうまくつきあいながら開発効率上げていきたいですね。Gemini関連でまたなにかあれば書きたいと思います!
参考文献