[iOS] ゼロから始める！簡単！多言語対応！

みなさん、多言語対応はしていますか？
大変そうに見えて、ちょっと躊躇してしまいますよね...

実際に僕もやってみたのですが、日本語の情報が少なくて導入部分で苦労したので、記事を書いてみることにしました。

簡単な導入のみなので、詳しいテクニックは後で紹介する参考サイト等を見てもらうといいと思います。

タイトルは若干つりです(๑>؂<๑)Շ^✩


# 多言語対応とは
端末本体の設定言語によって、アプリ内の文字列をその言語に合わせて表示することです。
日本人以外の人にも使ってもらえるようになるので、ぜひ対応したいですね！

完成形は以下のようになります。

``` xml:Localizable.strings(Base)
"welcome" = "Hello, World!";
"name" = "Your name is %@.";
"numbers" = "one: %d, two: %d";
"words" = "one: %1$@, two: %2$@";
```

``` xml:Localizable.strings(Japanese)
"welcome" = "ハローワールド！";
"name" = "あなたの名前は %@ です。";
"numbers" = "壱: %d, 弐: %d";
"words" = "弐: %2$@, 壱: %1$@";
```

``` swift:viewController.swift

override func viewDidLoad() {
    super.viewDidLoad()

    let myName = "sim"

    print(NSLocalizedString("welcome", comment: ""))
    print(String(format: NSLocalizedString("name", comment: ""), myName))
    print(String(format: NSLocalizedString("numbers", comment: ""), 10, 20))
    print(String(format: NSLocalizedString("words", comment: ""), "Apple", "Mac"))
}
```

結果（日本語以外の環境）

``` console:console
Hello, World!
Your name is sim.
one: 10, two: 20
one: Apple, two: Mac
```

結果（日本語環境）

``` console:console
ハローワールド！
あなたの名前は sim です。
壱: 10, 弐: 20
弐: Mac, 壱: Apple
```


# 多言語対応を始める前に
多言語対応を始める前に知っておきたいことがあります。
それは、外国語には””複数形””の存在があることです。
こいつがなかなか厄介（情報が少ない）なのですが、ちゃんと対応しましょう。

また、日付のフォーマットや通貨のフォーマットなどは今回紹介する方法ではなく、Formatterを使った方がいいです。ここら辺は`NSDateFormatter`や`NSNumberFormatter`について調べてみてください。

ちなみに、Storyboardのローカライズは言語ごとにStoryboardが複製されてそれぞれいじる必要が出てくるなど大変なので、僕はすべてコードでいじります。
なのでStoryboardのローカライズについては書けません...


## 多言語対応を調べるときに参考になったサイト
(@mono0926 さんは多くの良記事を書いているすごいお方なので是非フォローしましょう)
・[iOSアプリの国際化対応の勘所とTips集(Swift版) - @mono0926 ](http://qiita.com/mono0926/items/c41c1ce18b90b765a8f2)
・[Xcode 6で導入されたstringsdictファイルを使って、イケてる複数形多言語対応 - @mono0926 ](http://qiita.com/mono0926/items/647f6d741cd9965d9806)
・[iOS Developer Library - Localizing Your App](https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/LocalizingYourApp/LocalizingYourApp.html#//apple_ref/doc/uid/10000171i-CH5-SW10)
・[iOS Developer Library - Stringsdict File Format](https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html#//apple_ref/doc/uid/10000171i-CH16-SW1)
・[iOS Developer Library - String Format Specifiers](https://developer.apple.com/library/ios/documentation/CoreFoundation/Conceptual/CFStrings/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265)


## 多言語対応を使う時に便利なやつ
[questbeat/Lin](https://github.com/questbeat/Lin)


# 多言語対応の方法
今回紹介する多言語対応の方法はstringsファイルを用いたものを紹介します。

## stringsファイルの仕組み
完成形で見てもらっているように、Localizable.stringsにキーとなる文字と表示させたいものを書きます。
Localizable.stringsはファイルが各言語ごとに分けることができます。
これを対応したい各言語ごとに用意して、`NSLocalizedString`でキーを指定することによって端末の設定言語に自動で判定して文字を入れてくれます。

## 手順1 stringsファイルを追加する
新規ファイル作成よりLocalizable.stringsファイルを追加します。
<img width="740" alt="手順1.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/d30cc5ae-1ff2-267c-e473-df79c64597aa.png">
<img width="719" alt="手順2.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/8b14475a-8436-23e6-03bf-7f3eba55ba3c.png">


## 手順2 stringsファイルをLocalizeする
右側の`Localize...`ボタンを押す。
選択は`Base`でOK
<img width="1072" alt="手順3.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/e5a03a6a-6f36-2284-bef0-b80167d9e9f9.png">
<img width="435" alt="手順4.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/31c720cb-7311-348c-c38c-677aee1a596d.png">


## 手順3 アプリの対応言語を増やす
プロジェクトの設定の`Localizations`の＋ボタンから追加したい言語(今回はJapanese)を選択する。
<img width="1392" alt="手順5.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/6f2ae584-08d4-1ab9-f439-5cf18393cc0a.png">


チェックボックスは`Localizable.strings`のみ選択する。（Storyboardのlocalizeはこの記事では説明しない）
<img width="739" alt="手順6.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/e76d9e17-42b0-f476-86dd-490f111f8520.png">

こうなっていればOK
<img width="254" alt="手順7.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/de40d47e-b53c-2710-879e-308da839f04b.png">


## 手順4 stringsファイルに記述する

今回は本体の設定言語がJapaneseの時は`Localizable.strings`が利用され、それ以外はBaseの方の`Localizable.strings`が使われる。
(BaseはデフォルトでEnglishになっているが、このままいじらない方が良い)

つまり、設定が日本語の時表示したい文字を`Localizable.strings(Japanese)`ファイルに記述し、またそれ以外の`Localizable.strings(Base)`ファイルに記述する。
(記事上部の完成形参考)

### フォーマット
stringsファイルのフォーマットは以下のようになっています。

``` xml:Localizable.strings
"キーとなる文字" = "表示したい文字（とフォーマット）";
```
**swiftを触っていると普段セミコロンを使わないので、書き忘れがちなので注意！！**

### 代表的なフォーマット文字列
以下のようなフォーマット文字列を使って、`String(format: _, arguments: _)`と組み合わせることによって表示したい文字の中に変数の値を入れることができます。

|型|フォーマット|
|:--|:--|
|String|%@|
|Int   |%d|
|Double|%f|
もっと詳しく知りたい時ならこれを参照
→ [iOS Developer Library - String Format Specifiers](https://developer.apple.com/library/ios/documentation/CoreFoundation/Conceptual/CFStrings/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265)

他にも、`%`の直後に`1$`や`2$`をつけることで、引数の順番を選択できたり、数字の小数点以下の数の指定等もできます。

## 手順5 使う

使いたい場所で`NSLocalizedString`を使いましょう。

``` swift:~.swift
// 変数を入れない場合
NSLocalizedString("キーとなる文字", comment: "")

// 変数を入れたい場合
String(format: NSLocalizedString("キーとなる文字", comment: ""), 変数１, 変数２, ...)
```
# 複数形対応の方法
複数形への対応にはstringdictファイルを用います。

## stringdictファイルの仕組み
`Localizable.strings`ファイルと違う点として、フォーマット文字列で受け取る数字が'0'なのか'1'なのか'2'なのか、少なめなのか、多めなのか、それ以外なのかを判定して文字列を分けることができるようになります。

## 手順1 stringsdictファイルを追加する
新しくファイルを追加する。
追加するのはPropertyListファイルだが、名前は**Localizable.stringsdict**とする。

<img width="737" alt="スクリーンショット 2016-05-02 17.02.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/51203117-c1fc-ea1a-6161-dce9bed5dfd8.png">

**できたファイルは`Localizable.stringsdict.plist`となっているので、`plist`の部分を削除する！！**


## 手順2 stringsdictファイルをLocalizeする
stringsファイルと同様`Localize...`ボタンより`Base`でローカライズする。
<img width="263" alt="スクリーンショット 2016-05-02 17.04.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/b0d5caf8-55d6-2aa3-c385-91f5ba4d6e2d.png">

<img width="427" alt="スクリーンショット 2016-05-02 17.04.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/27a93978-216e-e74b-81a8-6e48bc2cc38f.png">

## 手順3 stringsdictファイルの言語を増やす
先ほど`Localized...`ボタンがあった辺りにLocalization欄が追加されていると思うので、そこからJapaneseにチェックを入れる。

<img width="261" alt="スクリーンショット 2016-05-02 17.04.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/b5baddce-bd47-1560-759b-ddf0ddb65205.png">


こうなっていたらOK
<img width="238" alt="スクリーンショット 2016-05-02 18.27.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/62690/09ff5170-755f-05b6-59c0-e23271efc421.png">



## 手順4 stringsdictファイルに記述する
list形式よりコード形式の方がいじりやすいので、Localizable.stringsdictファイルを右クリックからの`Open as`から`Source Code`を選んで開いてください。
stringsdictファイルは以下のような形式で記述します。

``` xml:Localizable.stringsdict(Base)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>key1</key>
	<dict>
		<key>NSStringLocalizedFormatKey</key>
		<string>%#@apples@</string>
		<key>apples</key>
		<dict>
			<key>NSStringFormatSpecTypeKey</key>
			<string>NSStringPluralRuleType</string>
			<key>NSStringFormatValueTypeKey</key>
			<string>d</string>
			<key>one</key>
			<string>an apple</string>
			<key>other</key>
			<string>%d apples</string>
		</dict>
	</dict>
	<key>key2</key>
	<dict>
		<key>NSStringLocalizedFormatKey</key>
		<string>%#@goods@</string>
		<key>goods</key>
		<dict>
			<key>NSStringFormatSpecTypeKey</key>
			<string>NSStringPluralRuleType</string>
			<key>NSStringFormatValueTypeKey</key>
			<string>d</string>
			<key>one</key>
			<string>%d GOOD</string>
			<key>other</key>
			<string>%d GOODS</string>
		</dict>
	</dict>
</dict>
</plist>
```

``` xml:Localizable.stringsdict(Japanese)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>key1</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@apples@</string>
        <key>apples</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>other</key>
            <string>%d 個のリンゴ</string>
        </dict>
    </dict>
    <key>key2</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@goods@</string>
        <key>goods</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>other</key>
            <string>%d いいね</string>
        </dict>
    </dict>
</dict>
</plist>
```

### コードの説明
- `<key>key1</key>`
これはstringsファイルの"キーとなる文字"と同じです。

- `<key>NSStringLocalizedFormatKey</key> <string>%#@apples@</string>`
これは、`%#@apples@`の部分が変数のようなものと考えてください。この後で各変数の設定をしていく感じです。

- `<key>apples</key>　<dict>　... </dict>`
ここのdictの中に設定を書いていきます。

- `<key>NSStringFormatSpecTypeKey</key> <string> ... </string>`
これはそのまま写しましょう。

- `<key>NSStringFormatValueTypeKey</key> <string> ... </string>`
これは引数の型のフォーマットを書きます。ほぼInt型だと思うので`d`と書いておきましょう。

- `<key>one</key> <string> ... </string>`
ここに引数の数が`1`だった時の表示したい文字(フォーマット)を書きます。

- `<key>other</key> <string> ... </string>`
ここに上記以外の時の表示したい文字(フォーマット)を書きます。

`<key>one</key>`の他にも`zero, two, few, many`などがあります。
使えるキーは言語ごとに異なっています。
[Language Plural Rules](http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html)に各言語対応表がありますので確認しましょう。
ちなみに日本語は`zero`と`other`のみ使えるそうです。


## 手順5 使う
Localizable.stringsの使い方と変わりません！！

``` swift:~.swift
String(format: NSLocalizedString("key1", comment: ""), 1)
String(format: NSLocalizedString("key2", comment: ""), 6)
```


わかりにくいところ、間違っているところがあればコメントください！
また、ちゃんと使うためにも参考サイトは一度目を通しておいたほうがいいと思います。


サンプルプロジェクトをGithubにあげました！！
[simorgh3196/LocalizationSample](https://github.com/simorgh3196/LocalizationSample)