アプリを他言語で表示するためにはLocalizationの設定が必要です。Localizationはstoryboardを分けてレイアウトを個々に作成したり、レイアウトはそのままで言語のみを変更したりできます。アプリ名の変更も他言語化できます。
このLocalizationは変更が毎回微妙にあるのでいつも悩みのタネではあります。
Xcode 11.4
Localization
Localizationとはアプリを各国の言語に合わせることです。英語圏では英語でラベルを表示させ、日本語圏では日本語のラベルにするわけです。通常デフォルトとしては英語にしておいて、日本語圏のみ日本語にする、それ以外は英語というのが簡単です。
もちろん翻訳を入れ込んで各言語に対応することもできます。(もっとも国や地域によっては英語にしないと無理な場所もあります)
1. Localizationの追加
2. Localizable.strings
3. Localizable Stringsの変換
4. storyboardの変換
5. アプリ名のローカライズ
6. CollectionViewをLocalize
Localizationの追加
Xcodeの「PROJECT」(TARGETではありません)「Info」の「Localization」の下に「Use Base Internationalization」がありチェックされていると思います。
Development Language はdefaultでEnglishが設定されています。
「+」から追加したい言語を選びます。
例えば日本語を追加します。
ローカライズするファイルの選択ですが「Main.storyboard」を選択
右クリックでFile Typeの設定をしますが、開発方法によって選びます。
- Interface Builder Storyboard:
- storyboardのレイアウトが異なるものを作りたい場合、英語と日本語での文字幅が異なってレイアウトを変える必要があるなど
- Localizable Strings:コードで全て記述したい場合はこちら
- レイアウトは同じで表示言語だけ変えたい場合など
この設定は後からでも可能です。レイアウトはstoryboardを使わずコードで記述する場合は適当で大丈夫です。
これでEnglisの下に「Japanese」が追加されました。
プロジェクト内のファイルを見てみると「 ja.lproj 」フォルダーが新しくでき、その中にファイルが2つあるのがわかります。
Localizable.strings
Localizable.stringsファイルを作成します。これは翻訳したいKeyワードを登録しておくファイルになります。
例えば、Localizable.strings(Japanese)というファイルに
“hello” = “こんにちは”;
と記述するとダウンロードされた端末が日本語のときに「hello」が「こんにちは」に変換されます。
設定例:
Localizable.strings(Englsih) | key | Localizable.strings(Japanese) |
“hello” = “Hello”; | ←hello→ | “hello” = “こんにちは”; |
作成:
「File」「New」「File…」から「Strings File」というのを探します。
iOSのResourceにあります。検索した方が早いかもしれませんが…
Localizable.stringsというファイル名にして「Create」します。
ファイル名はLocalizable.stringsにするとdefaultになります。カスタムで名前を設定できますが、table名として呼び出しで指定しないといけません。
ファルが作成されました。
このファイルを選択した状態でInspector(Show the File inspector)を見るとLocalizationの下に「Localize…」というボタンらしきもの?がありますのでクリック
白いボタンですがクリックすると青くなりダイアログが現れる
Japaneseを選択して「Localize」をクリックすると「Japanese」がLocalizationにできす。
ここで「English」にチェックを入れるとLocalizable.stringsの下に
Localizable.string(Japanese)
Localizable.string(English)
ができます。
Localizable Stringsの変換
テーブルの設定
Localizable.strings (Japanese) を選択して以下のように書き込みます
1 |
"hello" = "こんにちは"; |
同様にLocalizable.strings (English)を選択して以下のように書き込みます
1 |
"hello" = "Hello"; |
これらを呼び出すためにはNSLocalizedStringを使います。
1 2 3 4 5 |
func NSLocalizedString(_ key: String, tableName: String? = default, bundle: Bundle = default, value: String = default, comment: String) -> String |
- key:キーワードです。これを元に翻訳
- tableName:Localizable.stringsはdefaultのテーブルになります。異なるABC.stringsのようなファイルを作った場合そのテーブル名(ABC)を指定します。
- bundle:stringsを含めたbundle
- value:keyに合うものが見つからない場合に表示するもの
- comment:コメント
keyとcommentだけとして省略できます。
ViewController.swift
1 2 3 4 5 6 7 8 9 10 11 12 |
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let localStr = NSLocalizedString("hello", comment: "") print(localStr) } } |
これで実行させて見ます。
結果Log
Japanese:
1 2 |
こんにちは |
English:
1 2 |
Hello |
Xcodeのsimulatorでは言語設定はSchemeから変更できます。(アプリ名以外)
「Product」「Scheme」「Edit Scheme」
Run, Options からApplication Languageを変更することにより対応言語を変更できます。
storyboardの変換
最初のLocalizeでMain.storyboardの選択で
Localizable Stringsを選択した場合は
Main.strings (Japanese)には何もありません
Main.storyboard (Base)にLabelを1つ置きます。
これでMain.storyboard(Japanese)のFile TypeをInterface Builder Storyboardに変更し「Convert」すると
ストーリボードが表示されました。BaseのLabelと同じLabelが見えます
Main.strings(Japanese)からLocalization設定が見えない場合は
上位のMain.storyboardから見えるかもしれません
BaseのstoryboardとJapaneseを別々にstoryboard上で変更できます。
Base:
Japanese:
Base側での変更はJapanese側には反映されませんので注意
Launch Screen:
ところで同じように Launch Screen もLocalizeしたいのですが
”Avoid including text on your launch screen. Because launch screens are static, any displayed text won’t be localized.”
Ref: Launch Screen – Icons and Images – iOS Human Interface Guidelines
とあるように今のところでオフィシャルにはきないということでしょうか。
https://stackoverflow.com/questions/30079257/how-to-localize-launch-screen/45436837#45436837のようなworkaroundもケースバイケースでできるようですが、どうでしょう?
アプリ名をローカライズ
アプリの名前は今までと多少異なります。アプリ名はInfo.plistで設定できますが、これを今まで通りにローカライズするとエラーになります。別のファイルInfoPlist.stringsを作ります。
- Info.plist:CFBundleDisplayName = “App”を設定
- InfoPlist.strings:CFBundleDisplayName = “アプリ”を記述
Info.plistを開いてCFBundleDisplayNameを新しく入力し名前「App」を入れます。
ファイルに記述
1 2 3 4 5 6 7 8 |
... <dict> ... <key>CFBundleDisplayName</key> <string>App</string> ... </dict> ... |
Xcodeからみると
次にInfoPlist.stringsを「File」「New」「File…」「Strings File」から作成します。
Localizable.strings と同じようにして
Licalizationボタンをクリックして「Japanese」でローカライズします。
InfoPlist.stringsに
CFBundleDisplayName = “アプリ”;
記述します。(keyは””がいりません、セミコロンも忘れずに)
これで出来上がりですが、この場合のテストはsimulatorの場合はSchemeは使えません、通常のiPhoneでの言語設定と同じように、simulatorの「設定」から変えます。
CollectionViewのLocalize
こちらのCollectionViewをローカライズしてみます。
- English
- 名前を英語
- 名前の背景色を半透明グリーン
- 日本語
- 名前を日本語
- 名前の背景色を半透明ピンク
Localizable.strings (English)
1 2 3 4 5 6 7 8 9 10 |
"nagi" = "Nagi YONEZAKI"; "toko" = "Toko"; "saya" = "Saya AKANE"; "yumiko" = "Yumiko WATANABE"; "yuyu" = "Yuyu KITANO"; "yuka" = "Yuka KAWAMURA"; "miki" = "Miki"; "mai" = "Mai MIYAMOTO"; "kurumi" = "Kurumi YAMATO"; "katakuriko" = "Katakuriko SHIRATORI"; |
Localizable.strings (Japanese)
1 2 3 4 5 6 7 8 9 10 |
"nagi" = "米崎奈棋"; "toko" = "toko"; "saya" = "茜さや"; "yumiko" = "渡辺友美子"; "yuyu" = "北野佑々"; "yuka" = "河村友歌"; "miki" = "みき"; "mai" = "宮本舞"; "kurumi" = "大和くるみ"; "katakuriko" = "白鳥片栗粉"; |
名前を変更しますが、CollectionViewなのでCellによって変わるところに NSLocalizedString を使います。
ViewController.swift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
import UIKit class ViewController: UIViewController ,UICollectionViewDataSource, UICollectionViewDelegate , UICollectionViewDelegateFlowLayout { let photos = ["nagi", "toko","saya","yumiko","yuyu","yuka","miki","mai","kurumi","katakuriko"] override func viewDidLoad() { super.viewDidLoad() } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{ // Cell はストーリーボードで設定したセルのID let testCell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) // Tag番号を使ってImageViewのインスタンス生成 let imageView = testCell.contentView.viewWithTag(1) as! UIImageView // 画像配列の番号で指定された要素の名前の画像をUIImageとする let cellImage = UIImage(named: photos[(indexPath as NSIndexPath).row]) // UIImageをUIImageViewのimageとして設定 imageView.image = cellImage // Tag番号を使ってLabelのインスタンス生成 let label = testCell.contentView.viewWithTag(2) as! UILabel let str = NSLocalizedString(photos[(indexPath as NSIndexPath).row], comment: "") label.text = str return testCell } // Screenサイズに応じたセルサイズを返す // UICollectionViewDelegateFlowLayoutの設定が必要 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let cellSize:CGFloat = self.view.frame.size.width/2-2 // 正方形で返すためにwidth,heightを同じにする return CGSize(width: cellSize, height: cellSize) } func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { // 要素数を入れる、要素以上の数字を入れると表示でエラーとなる return 10; } } |
後は、それぞれのストーリーボード上でラベルの背景色の変更をします
最終的にこのようになりました。
English:
Japanese:
References:
NSLocalizedString(_:tableName:bundle:value … – Apple Developer
Internationalization and Localization for iOS – Apple Developer
Localizing Your App