XcodeでStoryboardをローカライズして自動でstringsをアップデート

Xcode で .storyboard(.xib)ファイルをローカライズすると各言語用の .storyboard(.xib)ファイルができる。
そして、そこに何かしら UIオブジェクトを追加しようとすると、全てのローカライズした .storyboard(.xib)ファイルに同じ UIオブジェクトを追加しなければいけない。
これはかな〜り面倒。


と、思っていたのだけど、各言語で共通の .storyboard(.xib)を作って、そこに各言語用の .strings ファイルを作成してローカライズができるって知ってビックリした。
今までずぅ〜っと知らなかったよ…。


更に、.strings ファイルは 1度作成してしまうと、その後で .storyboard にUIオブジェクトを追加しても .strings ファイルの内容はアップデートされない…。
しかし、これを自動的にアップデートするスクリプトもあってとっても便利だよ!


というわけで、この方法でローカライズする実験をサクっとやってみたのでメモ。
ちなみに、やってることはここのページの内容そのまま。

Xcodeで普通?にローカライズしてみる

まずは、何も考えずに普通に「Single View Application」のプロジェクトを作成、こんな感じにラベルを配置。


次にこれまた普通にローカライズして「日本語」を加えてみる。

MainStoryboard.storyboard がローカライズされて、「English」と「Japanese」の .storyboard ができあがる。(InfoPlist.strings も英語と日本語ができあがるけど、今回の話とは関係ない。)


この状態だとそれぞれの Storyboard を独立して編集できるので、各言語間で機能が違ったりする場合には良いのかもしれない。
けど、単純に文字列が違うだけの UI の場合には、例えばラベルを加える場合には全ての言語用の .stryboard ファイルにラベルを加えなければならなくて位置合わせとかかなり面倒になる。

MainStoryboard.storyboard(English)

MainStoryboard.storyboard(Japanese)

できれば文字列を除いた UI は 1つの UI を使って、文字列だけ各言語用を用意して済ませたい。(NSLocalizedString を使うみたいに!)

Use Base Internationalization を使う

そんな時に使うのが [Use Base Internationalization] チェックボックス

[PROJECT] の [Info] タブの [Localizations] に表示される。


これをチェックすると「どのファイルを各言語ファイルを参照するようにするか?」を聞かれるので、.strings を参照するようにしたいファイル(今回は MainStoryboard.storyboard ファイル)を選択する。


すると「Base」ってファイルが増えて「English」が消える。

「Base」は「English」が元になっているので、「English」を触りたい場合は「Base」を修正すれば良い。


この時点では「English」が「Base」になっただけで、まだ「Japanese」は自分の .storyboard を持っている。


この状態で「Japanese」の MainStoryboard.storyboard を選択して [File Inspecter] の [Localization] にある [Japanese] の右側のポップアップを見ると、[Interface Builder Cocoa Touch Storyboard] と [Localizable Strings] が選択できるので、[Localizable Strings] を選択。


ダイアログには [Convert] と答えて変換してしまう。


すると 「MainStoryboard.storyboard(Japanese)」だったファイルが「MainStoryboard.strings(Japanese)」に変わって、内容が「MainStoryboard.storyboard(Base)」から参照される文字列のファイルになっている。


今回は MainStoryboard.storyboard にラベルを乗せて試しているのだけど、その文字列がどのラベルなのか?を示す ID が「GJ7-S6-YGt.text」とか「tyo-0G-HQA.text」なんかで何がなんだか…。
それでも、その上のコメントと文字列の内容でどのラベルかはイメージできるから、ま、問題ないけど。


この状態だと「English」には .strings ファイルが用意されておらず、MainStoryboard.storyboard(Base)を直接いぢって修正することになる。
「English」だけ特別扱いせずに .strings ファイルを用意するには、[File Inspecter] の [Localization] にある [English] の左にあるチェックボックスをチェックすれば良い。


これで共通の UI の文字列だけ .strings ファイルに抜き出してそれを編集してローカライズできるようになった。


が、ここで 1つ問題なのは、一度 [Interface Builder Cocoa Touch Storyboard] から [Localizable Strings] に変換してしまうと、それ以降は新たに MainStoryboard.storyboard(Base) に UI を加えてもこの .strings には反映されないってこと!
あ〜これってコードの中の文字列のローカライズ(NSLocalizedString)と同じ状況だ…。

.strings の内容を自動でアップデートしてくれるスクリプト

というわけで、この .strings の内容を最新の .storyboard に合わせてアップデートしてくれるスクリプトがあるので使ってみた。
ダウンロードは下記から

ファイルをダウンロードて展開したら、とりあえずプロジェクトフォルダに「scripts」フォルダを作ってそのなかに入れておく。
そして忘れずにスクリプトを実行できるようにしておく。

iMac-i3-27:~ paraches$ cd /Users/paraches/Desktop/MyLocalizedTest/scripts 
iMac-i3-27:scripts paraches$ ls -al
total 8
drwxr-xr-x  3 paraches  staff   102  2 24 12:24 .
drwxr-xr-x  5 paraches  staff   170  2 24 12:24 ..
-rw-r--r--@ 1 paraches  staff  2611  2 22 03:43 update_storyboard_strings.sh
iMac-i3-27:scripts paraches$ chmod +x update_storyboard_strings.sh 
iMac-i3-27:scripts paraches$ ls -al
total 8
drwxr-xr-x  3 paraches  staff   102  2 24 12:24 .
drwxr-xr-x  5 paraches  staff   170  2 24 12:24 ..
-rwxr-xr-x@ 1 paraches  staff  2611  2 22 03:43 update_storyboard_strings.sh
iMac-i3-27:scripts paraches$ 

そして以下の手順でビルド時に自動的にこのスクリプトが実行されるようにする。
まずは [TARGETS] の [Build Phases] タブの右下にある [Add Build Phase] ボタンから [Add Run Script] を選択。

[Run Script] が加わるのでそこで先ほどのスクリプトが起動するように編集する。


具体的には、「Type a script or drag a script file from your workspace」に「scripts」フォルダに入れた「update_storyboard_strings.sh」ファイルをドラッグ&ドロップ。
パスが絶対パスになるので、それが嫌な場合は相対パスに変更。(プロジェクトの位置からの相対パスだと、プロジェクトフォルダを移動しても大丈夫!)

これで準備完了!


MainStoryboard.storyboard(Base)に新しいラベル「New Localized Label」を追加。


ビルドしてみると…ちゃんと MainStoryboard.strings(Japanese) にも新しいラベルが入ってる!


この新しく入ったラベルの文字列を日本語に修正すればローカライズ完了!


というわけで、英語/日本語のローカライズしかしない自分だけど、やっぱり各言語用の .storyboard(.xib)を編集するのは面倒だったので、こうやって自動的にアップデートできる .strings でローカライズするのはとっても楽で良い!