Androidの国際化対応(Jetpack実装で)
新規案件のテスト雛形アプリをJetpack実装で、かつ国際化対応させる手順のメモ。文字列だけでよければiOSに比べ、ずっとシンプルだ。
国際化対応は見方によると各言語へのローカリゼーション対応なのでローカリゼーションという言葉を用いる場合が少なくない。本稿では特に言語を指定する時だけローカリゼーションという言葉を使うことにする。(長いので・・・)
- 言語はKotlin
- フレームワークはJetpack
- 国際化対応は日本、米国、繁体中文、簡体中文を選択
- フレームワークがJetpackなので各種CollectionはGuavaライブラリーのものを利用。
- ユーザー入力に対して何かを実行し、結果を表示する。これがAndroid実機上で問題なく動作するかどうか確認するのが第一の目標。
Project fileの準備
Jetpackフレームワーク、Kotlinで記述されたプロジェクトを生成する。まずは国際化対応の前まで。
- 通常のEmpty Activityプロジェクトを作成する。
- プロジェクト設定でKotlin、Jetpack実装を選択。
LanguageにKotlinを選び
下の方にあるチェックボックスでandroidx.* artifactをチェック
- build.gradle(Module: app)を確認する。
上の方でkotlin-androidのプラグイン二つ(Kotlinサポート)..
dependenciesセクションにandroidxがいくつか追加されているのを確認する(Jetpackサポート)
国際化に対応できるアプリにする
具体的には、res内のLayoutなどに現れる各種文字列をStringリソース利用の形にすること(だけ)である。ただ最初からやっておかず、あとでまとめてやろうと等すると結構な負担になる。ミスの元だ。
元々アプリケーションのタイトルが格納されているvalues/string.xmlの中に追加する形になる。
<resources>
<string name="app_name">My Application</string>
<string name="editText">Please input something</string>
<string name="btnText1">Calculate</string>
<string name="btnText2">Clear result</string>
</resources>
例えば、ここにあるname=”btnText1″に対応するものはactivity_main.xml内で
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="8dp"
android:text="@string/btnText1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText" />
の中でandroid:text=”@string/btnText1″のように関連付けられている。
言語リソースの追加(ここで国際化実行)
これはAndroid Studioの機能を使うのが一番分かりやすい。実はこの作業ある程度「あとでまとめてやった方がよい。」翻訳を頼むのはある程度UIが固まってからだろうし、変更が複数言語に跨がると手間だからである。ここは各プロジェクトの人員構成などに依存する。
具体的にはresフォルダ内にあるvalues-stringsフォルダと進んでいきstring.xmlを選択すると出てくる画面の操作でできるのである。
アプリケーション名を例に取ると、右上の選択肢からOpen Editorを選ぶと専用のエディタが開いて編集ができるようになる。対応したい言語を地球儀アイコンで開くメニューから選択する。メニューは長いのでjと打ってjで始まる所までジャンプするのが良いだろう。
これがTranslation Editor画面になり、以後変更はここで一元的にすること。個別のリソースでも操作できてしまうが、それは混乱の素である。
言語を追加すると左のプロジェクトペイン内のStringリソースに対応言語の複製版が生成される。これをその言語のものに書き換えればあとは自動でAndroidがやってくれる。繰り返しになるが書き換えは上記Translation Editor画面に統一した方が良い。
Translation Editor画面
画像など言語別リソースを持つ場合にはそのファイルのパスを「ローカライズ」することで対応が可能だ。つまりgetResourceなどを使う。ただ途端にメンドウになる。
テスト実施
Emulatorや実機でLocaleを変更してちゃんとその言語で文字列が表示されるか確認する。
「設定」アプリで「システム」「言語と入力」「言語」と選んでいき、言語の順序を変更した際に、作成したアプリの方が最高順位に設定した(対応済み)言語に自動的に変更されればOK。
注意が必要なのはアプリビルドにおける「影の主言語」が英語になっていること。だからアプリ対応言語が首位にはなく、2位以下にあって、アメリカ英語より上位にあっても英語が表示される。
iOSとの違い
iOSではソースコードにローライズ専用のマクロNSLocalizedStringを書き込み、大文字で入れたタグ(多分Unicodeだから日本語でもOKかもしれない・・・。)を頼りに言語リソースを紐付ける。紐付け先で変更(翻訳)をしなければ、タグ名がUIには表示される続ける。
また開発言語とベース言語を一致させないと何らかの不整合が起こり得た。具体的には日本語のアプリを作ったつもりで、それを英語向けにしようとすると、Baseで使われているのでダメとなってしまう。(もちろん回避できるだろうが・・・。)
AndroidではiOSでやったような既定(Base)の言語を変更すると言うものはなさそうだ。強いて言えばDefault Valueで設定された値が既定になる。ここは英語(ローマ字)にしておいた方が、デバッグ時などに表示できないと言ったトラブルに巻き込まれる怖れがない。
JavaやKotlinのソースコードには言語でも何でもリソースのタグ名が入るだけにできる。その意味では統一されシンプルだと言える。NSLocalizedStringのようなものを導入する必要はない。
ただしStringリソース以外の場合、Localeを取得してgetResources()で対象リソースを紐付ける必要があるのはiOSよりメンドウだと思える。また、どのタイミングで言語Localeを取得するのかなど、それだけで一記事掛ける価値があるので、また別途記載する。