Xcode 6で導入されたXLIFFによる国際化フローの使いドコロ


[XLIFF](https://ja.wikipedia.org/wiki/XLIFF)(XML Localization Interchange File Format)とは、ソフトウェアや文書の国際化、翻訳のために定められた標準規格です。
Xcode 6で、`strings`ファイルのXLIFF形式へのExport, その逆にXLIFF形式を`strings`ファイルとしてImportの機能がサポートされました。

このサポート前までは、`strings`ファイルを直接編集するか、あるいは独自翻訳フローを構築する必要がありました。
今までXLIFFサポート自体は知りつつも特にその機能を活用していませんでしたが、[今開発中のPlayer!](https://itunes.apple.com/jp/app/id897872395)への導入を検討しながら情報をまとめてみました。

Appleのリファレンス: [Localizing Your App](https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/LocalizingYourApp/LocalizingYourApp.html)

## `strings`ファイルをXLIFFファイルとしてExportするとどうなる？

こんな`strings`ファイルがあり、

```
# ja/Card.strings
"Comment" = "コメント";
```

こう呼び出している場合、

```swift
let localized = LocalizedProfile("Comment", tableName: "Card", comment: "ノートです(　´･‿･｀)")
```

XLIFFとしてExportすると、こうなります。
(親要素など省略)

```xml
<file original="Player/UI/Localization/Strings/en.lproj/Card.strings" source-language="en" datatype="plaintext" target-language="ja">
  <header>
    <tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="6.3.2" build-num="6D2105"/>
  </header>
  <body>
    <trans-unit id="CommentsCountFormat_One">
      <source>Comment</source>
      <target>コメント</target>
      <note>ノートです(　´･‿･｀)</note>
    </trans-unit>
  </body>
</file>
```

また、嬉しいこととして、大量の`strings`ファイルが言語ごとに1つのXLIFFファイルとして束ねられるため、翻訳時のファイルの扱いが簡単になります。

生のXLIFFファイルは読みにくいので、後述の「[XLIFFクライアントアプリ](http://qiita.com/mono0926/items/ceda2500fe60e26e1c7c#xliffクライアントアプリ)」などで閲覧・編集します。



![Screen Shot 2015-06-28 at 8.59.04 AM.png](https://qiita-image-store.s3.amazonaws.com/0/19398/4c1305da-ebc0-b060-e13e-db7c03e874ae.png "Screen Shot 2015-06-28 at 8.59.04 AM.png")


## XLIFFを用いた翻訳フロー

### XcodeあるいはコマンドラインでExport

Xcodeで **左のツリーでプロジェクトを選択した状態**で、
ツールメニューの`Editor` -> `Export for localization`でExportできます。

あるいはコマンドラインで、以下のような感じで同じことが出来ます。


```
xcodebuild -exportLocalizations -localizationPath ./xliff -project Player.xcodeproj -exportLanguage ja
```

Xcodeだとエラーが出た時に、その詳細が分からないので、困ったらコマンドラインで実行すると良いです。

個人的には、Xcode上じゃ無くてコマンドライン経由で、プロジェクト設定のBuild Phasesに入れるか、あるいはCIフローに組み込むかなどが良いかなと思います。

### 翻訳作業

XLIFFエディタを使って、翻訳していきます。

### XcodeあるはコマンドラインでImport

翻訳後のXLIFFファイルをExport時とは逆に、
ツールメニューの`Editor` -> `Import localizations`でExportできます。

同様にコマンドラインでも可能です。

```
xcodebuild -importLocalizations -localizationPath ./xliff -project Player.xcodeproj [-forceImport]
```


## XLIFFエクスポート機能の問題

### `NSLocalizedString`の引数に文字列リテラルを渡す必要がある

「[`strings`ファイルをXLIFFとしてExportするとどうなる？](http://qiita.com/mono0926/items/ceda2500fe60e26e1c7c#stringsファイルをxliffファイルとしてexportするとどうなる)」に貼ったXLIFFファイルに`<note>ノートです(　´･‿･｀)</note>`という要素があり、エディタ上にも右のカラムに出ていますが、これは、`NSLocalizedString`の`comment`引数に相当します。

今まで、`comment`引数はコード上でしか意味をなして無くてほとんど活用していなかったですが、翻訳のヒントとなるためちゃんと記載するとかなり分かりやすくなると思います。

これ自体はとても良い機能だと思うのですが、これらなどを実現するためか、XLIFFヘのExport時に`NSLocalizedString`利用箇所を解析して渡された文字列リテラルを解釈する、というような挙動となっているようです。

そのため、組み立てた文字列だったり、変数として`NSLocalizedString`に渡している箇所があると以下のエラーが出てしまいます。

```
Bad entry in file /Users/mono/Documents/Git/ookami/ookami-ios/PlayerLib/Localization.swift (line = 29): Argument is not a literal string.
```

一応StackOverflowで質問もしてみましたが多分これは現状の制約だと思います:
[xcode - NSLocalizedString should be used directly for exporting XLIFF? - Stack Overflow](http://stackoverflow.com/questions/31084240/nslocalizedstring-should-be-used-directly-for-exporting-xliff)

### `stringsdict`非対応

`stringsdict`についてはこちらご覧ください:
[国際化 - Xcode 6で導入されたstringsdictファイルを使って、イケてる複数形多言語対応 - Qiita](http://qiita.com/mono0926/items/647f6d741cd9965d9806)

`stringsdict`XLIFFフォーマットのエクスポート・インポート非対応のため、XLIFFを使った場合でも`stringsdict`ファイルはこれまでの`strings`ファイルと同様に、直接ファイル編集する必要が出てきます。

XLIFF形式にすると、`strings`ファイルが1つのファイルにまとめられて便利な反面、`stringsdict`は別管理となると、ちょっと中途半端な気がします。

#### 【追記】Xcode 9で対応されました🎉

[Localizing with Xcode 9 - WWDC 2017 - Videos - Apple Developer](https://developer.apple.com/videos/play/wwdc2017/401)

<img width="2130" alt="Screen Shot 2017-06-11 at 15.51.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/19398/c2c4ae9f-9175-5f48-1bfd-77578fc34892.png">


### `strings`ファイルにコメントがあるとエラー

これは、XLIFF Exportの欠点では無いですが、ハマりどころです。

以下のような`strings`ファイルが存在すると、

```
# ja/Card.strings
"Comment" = "コメント"; // ノートです(　´･‿･｀)
```

こんなエラーが発生します。
分かりにくいエラーなので、注意です。
この用途だと、`NSLocalizedString`の`comment`引数に書いた方が良いですね。

```
** INTERNAL ERROR: Uncaught exception **
Exception: -[__NSCFString substringWithRange:]: Range {771, 21} out of bounds; string length 791
Stack:
  0  0x00007fff93a5ca3d __exceptionPreprocess (in CoreFoundation)
  1  0x00007fff99f1e13a objc_exception_throw (in libobjc.A.dylib)
  2  0x00007fff93a5c905 +[NSException raise:format:] (in CoreFoundation)
  3  0x00007fff9395ee00 -[__NSCFString substringWithRange:] (in CoreFoundation)
  4  0x000000010a635d55 -[IDELocalizationUtilities_parser _currentOffsetContext] (in IDEFoundation)
```

## どのようなユースケースで使える？

と、色々利点やイケてない点などありましたが、個人的には「[`NSLocalizedString`の引数に文字列リテラルを引数に渡す必要がある](http://qiita.com/mono0926/items/ceda2500fe60e26e1c7c#nslocalizedstringの引数に文字列リテラルを渡す必要がある)」という制約がメリットの恩恵に対してやや薄いと感じたため、導入は見送ろうかなと思いました。

XLIFFは翻訳者にとっての標準フォーマットなので、[XLIFF: Localize Your Xcode Application With XLIFF](https://localize-software.phraseapp.com/posts/xliff-localize-your-xcode-application-with-xliff/)にも書いてある通り、外注による国際化フローを回したい需要など出てきたら良いと感じました。

そこで紹介されている[PhraseApp: Software Translation Management](https://phraseapp.com/en)は、XLIFFおよび`stringsdict`ファイルをアップロードすれば翻訳してくれるようです。



## XLIFFクライアントアプリ

XMLなので、もちろん手でも弄れますが、使いやすいGUIを利用した方がずっと良いと思います。
直にファイル編集するなら、stringsファイルがむしろ扱いやすいと思いますし。

開発者がXLIFFファイルを見たい場合・チーム内の文言担当の人がXLIFFファイルを扱う場合など、以下から気にいったものを使えば良いと思います。
外注する場合は、専門家なのでXLIFFファイル渡せば適当にお気に入りのツールで処理してくれるでしょう。

### [Mac App Store - Xliffie](https://itunes.apple.com/us/app/xliffie/id961651406)

- 120円
- Macアプリとしては一番の定番だと思う
- ここにアプリ説明が詳しく載ってる: [Xliffie - A localization assistance for your iOS / Mac app](http://hotmilktea.com/xliffie/)

### [Mac App Store - iXLIFF](https://itunes.apple.com/jp/app/ixliff/id944658897)

- 120円
- 悪く無いけど、Xliffieの方が作り込んである印象

### [XLIFF localization tools for Xcode 6 - Stack Overflow](http://stackoverflow.com/questions/26363627/xliff-localization-tools-for-xcode-6)

StackOverflowで、アプリについてたくさん紹介されています。
上記2つがけっこう良かったため、特に他のアプリはチェックしていません。

## 参考

- [\[iOS 8/Xcode 6\] Localization がより簡単になりました ｜ Developers.IO](http://dev.classmethod.jp/references/xcode6-localization/)
- [Xcode 6.3でローカライズする時の作業メモ - 開発メモ](http://seeku.hateblo.jp/entry/2015/04/12/153149)