☆リソースプログラミングガイド;「文字列リソース」
これは、 「リソースプログラミングガイド」(Resource Programming Guide) 内の「文字列リソース」(String Resources)だけをiOS用に翻訳(かなり意訳)・手入れしたものである。

文字列リソース


ローカライズ過程での重要な部分は、あなたのアプリケーションで表示されるテキスト文字列の全てをローカライズすることである。 プログラムに埋め込まれる文字列を抽出し、ローカライズし、プログラムへと元通りに差し込まれなければならない。
この作業を単純化し、またプログラムのメンテナンスをより簡単にするため、iOSは文字列をプログラムから分離して、 簡単にローカライズできるリソースファイルに入れるための機能を提供する。

ローカライズ可能な文字列を含むリソースファイルは文字列ファイルと呼ばれ、それは.stringsである。 あなたは、あなたの必要次第で、手動またはプログラム的に、文字列ファイルを作成することができる。 標準的な文字列ファイルフォーマットは、オプションのコメントに加えて一つ以上のキー~値の組から成る。 所定の一組のキーと値は、""に入れられて、等号で区切られるテキストの文字列である。

リスト2-1は、デフォルト言語のために、ローカライズしないエントリを含む単純な文字列ファイルを示す。 文字列を表示する必要があるときは、左の文字列を、利用できる文字列読み込みルーチンへ渡す。 あなたが受け取るのは、カレントユーザのために最適であるテキスト翻訳を含んでいる、合致する値文字列(右側の文字列)である。
リスト 2-1 簡単な文字列ファイル

/* 要素メニューアイテムを挿入する */ 
"Insert Element" ="Insert Element"; 

/* 未知のエラーのために使うエラー文字列 */ 
"ErrorString_1" ="An unknown error occurred."; 
代表的アプリケーションには、ローカライゼーション(つまり、バンドルの.lprojサブディレクトリ内)につき、 少なくとも1つの文字列ファイルがある。 デフォルト文字列ファイルの名前はLocalizable.stringsであるが、どんなファイル名ででも文字列ファイルを作成することができる。 文字列ファイルを作成することは、「文字列リソースファイルを作成する」 で、より深く説明する。
注:
文字列ファイルは、UTF-16エンコードを使って保存するよう勧める。 そして、それは標準文字列ファイルのためのデフォルトエンコードである。
・・・とは書かれているが、Xcode4.xではUTF-8でも全く問題ない。 そもそも、他のソースがUTF-8で書かれているのにここだけUTF-16というのもおかしな話である。

最終的に文字列リソースを読み込ませることは、iOSで見つかるバンドルと国際化サポートに頼る。 バンドルに関して詳しくは、 「バンドルプログラミングガイド」(Bundle Programming Guide) を見なさい。 国際化とローカライゼーションの詳細については、 「国際化プログラミングトピック」 を見なさい。

文字列リソースファイルを生成する

手動で文字列ファイルを作成することもできるが、そうする必要はまれである。 プログラムにための文字列ファイルを作成する最も簡単な方法は、 適切な文字列-読み込みマクロを使用することと genstringsコマンド・ライン・ツールを使うことである。
・・・って書いてあるけど、最初からローカライズを意識して作るようになれば、 こんな物使わなくて良い。そう、最初から文字列が出てくるたびに文字列ファイルを作るだけで良いのである。 横着するなってこと。
以下の章は、genstringsツールの使用を容易にするために、あなたのソースファイルを準備する方法を記載する。 ツールの詳細については、 genstringsマニュアル・ページを参照しなさい。

ローカライズにどの文字列を選ぶか

アプリケーションのインターフェースをローカライズすることとなると、 用いられるすべての文字列をローカライズすることは、必ずしも適切でない。 翻訳は高くつく作業であるし、ユーザー見ることのない文字列まで翻訳することは時間とお金の浪費である。 例えばプログラム内部の通知名の文字列は、翻訳される必要はない。 (だからこそ、プログラマーが、都度文字列ファイルに書き出すのが適切なのである。)

この例では、文字列"-"は内部的に使われて、ユーザー見られることはない。 したがって、それは文字列ファイルに置かれる必要はない。
    if (CFStringHasPrefix(value, CFSTR("-")) {
        CFArrayAppendValue(myArray,value);
    }
次のプログラムでは、文字列「%d %d %s」はローカライズされる必要はない。
    matches = sscanf(s, "%d %d %s", &first, &last, &other);
nibファイルが別途にローカライズされるのであれば、 nibファイルの中に位置する文字列を含める必要はない。 しかし、いくつかの文字列はローカライズしなければならない。

文字列読み込みマクロについて

FoundationとCore Foundationフレームワークは、 文字列ファイルから文字列を読み込ませるために、以下のマクロを定める。 あなたは、アプリケーションの文字列ファイルのうちの1つから文字列を読み込ませるために、ソースコード上でこれらのマクロを使用する。 実際の文字列値を取り出すとき、マクロはアカウントからユーザーの現在の言語指定を取り出す。 そのうえ、genstringsツールはこれらのマクロを捜し、それらが含む情報を、文字列ファイルの初期の組を作るために使う。
これらのマクロを使用する方法の詳細については、 「文字列リソースをあなたのプログラムに読み込ませる」ことを見なさい。

文字列ファイルを生成するためにGenstringsツールを使う

開発の間のいくつかのポイントで、あなたは、プログラムによって、必要な文字列ファイルを作成する必要がある。 あなたがプログラムをCore FoundationとFoundationマクロを使用して書き込むならば、 文字列ファイルを作成する最も単純な方法は、genstringsコマンド・ライン・ツールを使用することである。
あなたはこのツールを、文字列ファイルの新しいセットを生成するため、または あなたのソースコードに基づく一組の既存ファイルの更新をするために、使うことができる。

genstringsツールを使用するためには、一般的に少なくとも2つの引数を必要とする。 genstringsツールは、.c、.mまたは.javaファイル名拡張子でC、Objective-CとJavaコード・ファイルを解析することができる。
厳密には必要でないが、 genstringsが出力する文字列ファイルを置くところとして、出力ディレクトリを指定することが推薦されている。 ほとんどの場合、あなたはXcodeのプロジェクト・リソースを含んでいるしかるべきディレクトリを指定するだろう。 なお、出力しただけではXcodeのプロジェクトには自動的には追加されないので、出力後に別途追加する必要がある。

以下の例は、genstringsツールを実行するために、単純なコマンドを示す。 このコマンドは、ツールがカレントディレクトリですべてのObjective-Cソースファイルを解析して、 結果として生じる文字列ファイルをen.lprojサブディレクトリに置く。 そのディレクトリはすでに存在していなければならない。
    genstrings -o en.lproj *.m
あなたが初めてgenstringsツールを実行する時、それは一組の新しい文字列ファイルを作成する。
以降の実行では、それらの文字列ファイルの内容を、あなたのソースコードで見つかる現在の文字列エントリと入れ替える。 その際、念のためバックアップをとっておくことを推奨する。

それから、あなたは、プロジェクト内のどの文字列が追加された(または変更されたか)新旧バージョンの違いを決定できる。 また、あなたの文字列ファイルの、すでにローカライズされたバージョンでも更新するためにこの情報を使うことができる。

genstringsツールは、それが見つけるどんなエントリの複製の合体にも、うまく動作する。 それが単一の文字列ファイルで一度以上使われるキー文字列を発見するとき、 ツールは、個々のエントリから1つのコメント文字列にコメントを合併して、警告を生成する。 (-qオプションでエントリ複製警告を抑えることができる)。 同じキー文字列が、異なる文字列ファイルで文字列に割り当てられるならば、警告は生成されない。
genstringsツールを使用することに関する詳細は、 genstringsマニュアル・ページ を参照しなさい。

文字列ファイルを手動で生成する

genstringsツールは文字列ファイルを作成する最も便利な方法であるが、 あなたは手動でそれらを作ることもできる (←いっや、こっちが本筋だろう)

手動で文字列ファイルを作成するために、Xcode上で新しいファイルを作成して保存する。 このファイルの内容は、キーと値の組とそれぞれのキー-値の組の目的を記載しているオプションのコメントから成る。 キーと値文字列は等号で区切られる。そして、全エントリはセミコロン文字で終了されなければならない。 規則によって、コメントはC型コメント区切り文字(/*と*/)に入れられて、それらが解説するエントリの直前に置かれる。

リスト2-2は、文字列ファイルの基本形状を示す。 各々の等号の左側の文字列はキーを表す、そして、右辺の文字列は値を示す。 アプリケーション開発時の一般的規則は、開発で使用した言語のキー名と値を使うことである。 したがって、英語を使用して開発したなら、英語版Localizable.stringsファイルは、それに一致するキーと値を持つ。
リスト 2-2 英語にローカライズされた文字列

/* Menu item to make the current document plain text */
"Make Plain Text" = "Make Plain Text";

/* Menu item to make the current document rich text */
"Make Rich Text" = "Make Rich Text";
リスト2-3は、同じエントリのドイツの翻訳を示す。 これらのエントリもLocalizable.stringsと呼ばれているファイルの中にある。 しかし、このバージョンのファイルはアプリケーションのドイツ語プロジェクト・ディレクトリにある。 キーは英語のままである。しかし、それらのキーに割り当てられる値はドイツ語である。 これは、キー文字列がエンドユーザーによって決して見られないからである。 それらは相当値文字列を取り出すためにプログラムにより用いられる。 そして、それはこの場合ドイツ語である。
リスト 2-3 ドイツ語にローカライズされた文字列

/* Menu item to make the current document plain text */
"Make Plain Text" = "In reinen Text umwandeln";

/* Menu item to make the current document rich text */
"Make Rich Text" = "In formatierten Text umwandeln";

あなたのプログラムに文字列リソースを読み込む

Core FoundationとFoundationフレームワークは、文字列ファイルに保存された、ローカライズされた文字列を取り出すための マクロを提供する。これらのマクロの主目的は実行時に文字列を読み込ませることであるが、 第2の目的は、genstringsツールにローカライズすべき文字列の情報を特定させることである。
genstringsツールは、アプリケーションの文字列ファイルを自動的に生成または更新することを提供するための情報を使う。 表2は、あなたがこれらのルーチンを特定できる情報の型をリストしている。 そしてその情報がgenstringsツールでどのように使われるかを述べる。

表2 文字列読み込みルーチンで見つかる共通のパラメーター
パラメーター内容
キー文字列は、相当値を探したものである。この文字列にはASCII文字しか含んではいけない。
テーブル名指定されたキーが位置する文字列ファイルの名前。
genstringsツールはこのパラメータを、文字列が置かれなければならない、文字列ファイル名と解釈する。
テーブル名が提供されないならば、文字列はデフォルトのLocalizable.stringsファイルに置かれる。
(このパラメータに値を指定するときは、.strings拡張子なしでファイル名を含める。)
デフォルト値 所定のキーと結びつくデフォルト値。 デフォルト値が指定されないならば、genstringsツールは初期値としてキー文字列を使う。
デフォルト値文字列には、任意の文字が使える。
コメント所定の文字列が使われる方法について(手掛かりを翻訳チームに提供するため等に)コメントを使うことができる。
genstringsツールはこれらのコメントを文字列ファイルに入れて、関連するエントリに、それらをC型コメント区切り文字(/*と*/)で囲って入れる。
バンドル文字列ファイルを含んでいるバンドルと一致しているNSBundleオブジェクトまたはCFBundleRef型。
iOSでは無効。

Core Foundationフレームワークを使う

Core Foundationフレームワークは、 あなたのアプリケーション・バンドルからローカライズされた文字列を読み込ませるために、 一つの関数といくつかのマクロを定める。
CFBundleCopyLocalizedString関数は、文字列を取り出すための基本的な実装を提供する。 しかし、代わりに以下のマクロを使用するよう勧める。 CFBundleCopyLocalizedString関数の代わりにマクロを使用するいくつかの理由がある。
  1. マクロは、特定の一般的なケースで使用することが容易である(意味不明)
  2. マクロはコメント文字列で文字列エントリを連想させる
  3. マクロはgenstringsツールで認識される
しかし、CFBundleCopyLocalizedString関数はそうではない。

これらのマクロを使用する方法の追加情報については、 「バンドルプログラミングガイド」(Bundle Programming Guide) で「ローカライズされた文字列で働くこと」(Working With Localized Strings)を見なさい。
マクロおよび関数構文のために、 「CFBundleリファレンス」(CFBundle Reference) を見なさい。

Foundationフレームワークを使う

Foundationフレームワークは、文字列リソースを読み込ませるために、一つのメソッドといくつかのマクロを定める。
NSBundleクラスのlocalizedStringForKey:value:table:メソッドは、 現在のバンドルにある文字列ファイルから、指定された文字列リソースを読み込ませる。 Cocoa Touchも、ローカライズされた文字列を得るために、以下のマクロを定める: Core Foundationと同様に、マクロを使用するよう勧める。 これらのマクロの主な利点は、それらがgenstringsツールで解析されることができて、 あなたのアプリケーションの文字列ファイルを作成することに使えることである。 それらは使うのが簡単で、あなたにコメントで各々のエントリを連想させる。

前のマクロの構文に関して詳しくは、 「Foundation関数リファレンス」(Foundation Functions Reference) を見なさい。
文字列を読み込ませるための他のメソッドについてはNSBundleクラスリファレンス参照のこと。

文字列取得の例

以下の例は、文字列を取り出すためにFoundationとCore Foundationマクロを使用する基本的な技術を示す。 各々の例は、現在のバンドルが、日本語に翻訳されたCustom.stringsという名前の文字列ファイルを含むと仮定する。

この翻訳されたファイルは、以下の文字列を含む。
/* A comment */
"Yes" = "はい";
"The same text in English" = "日本語の同じ文字列";
Foundationフレームワークを使った場合、NSLocalizedStringFromTableマクロを使用して「Yes」文字列の値を得ることができる。
NSString* theString;
theString = NSLocalizedStringFromTable (@"Yes", @"Custom", @"A comment");
Core Foundationフレームワークを使った場合、CFCopyLocalizedStringFromTableマクロを使用して同じ文字列を得ることができる。
CFStringRef theString;
theString = CFCopyLocalizedStringFromTable(CFSTR("Yes"), CFSTR("Custom"), "A comment");
両方の例にて、プログラムは取り出すキーを指定する。それは文字列「Yes」である。 それらもキーを探す文字列ファイル(またはテーブル)を指定する。この場合Custom.stringsファイルである。 文字列検索の間、コメント文字列は無視される。

文字列ファイルへの一歩進んだ助言

この章では、文字列ファイルと文字列リソースについて、若干の助言を提供する。

genstringsでカスタム機能を探す

genstringsツールは、デフォルトでCore FoundationとFoundation文字列マクロを捜す。 あなたのプロジェクトの文字列ファイル内の文字列エントリを生成するために、これらのマクロ内の情報を使う。

あなたは直接genstringsに、プログラムでカスタムの文字列読み込み関数を探して標準的なマクロに加えてそれらの関数を使用するように指示することもできる。
あなたは、組み込み文字列読み込みルーチンを包むためにカスタム関数を使用し、追加の処理を実行するかもしれない または、カスタム・モデルでふるまいを取り扱っているデフォルト文字列に代わるかもしれない。
あなたが、カスタム関数でgenstringsを使いたいならば、その関数はFoundationマクロにより用いられる命名と フォーマット規約を使わなければならないし、引数は対応するマクロのパラメータと正確に一致しなければならない。
あなたがgenstringsを呼び出すとき、「-S NSLocalizedStringマクロと一致する関数の名前」オプションを指定しなければならない。 あなたのその関数名は、このベース名から構成されなければならない。 たとえば、あなたが関数名をMyStringFunctionと名づけるように指定するならば、 あなたのその関数名はMyStringFunctionFromTable、MyStringFunctionFromTableInBundle、MyStringFunctionWithDefaultValue でなければならない。
genstringsツールはこれらの関数を探して、対応する文字列ファイルを構築するために使う。

文字列リソースをフォーマットする

いくつかの文字列は、実行時に内容が変わるかもしれないので、 全ての文字列を文字列リソースにコード化しようと(または可能に)しなくていい。

たとえば、文字列がユーザー文書の名前を含むならば、動的ににその文書名を文字列に挿入する必要がある。 あなたが文字列リソースを作るとき、通常、FoundationとCore Foundationフレームワークで 文字列置き換えを取り扱うために使うだろう書式作成文字のどれでも使うことができる。

基本的な書式作成文字を使ういくつかの文字列リソースを示す。
リスト 2-4 フォーマット文字付きの文字列

"Windows must have at least %d columns and %d rows." = "ウインドウは最低 %d 桁と %d 行が必要です.";
"File %@ not found." = "ファイル %@ が見つかりません.";
フォーマット文字を実値に置き換えるためには、NSStringのstringWithFormat:メソッド またはCFStringCreateWithFormat関数を使う。 それは、フォーマット文字列として文字列リソースを使う。

FoundationとCore Foundationは、printf文で使われる大部分の標準的な書式作成文字をサポートする。 さらに、前の例で示した、任意のObjective-Cオブジェクトと関連した説明文を挿入できる%@指定子を使うことができる。 指定子の完全なリストは 「文字列プログラミングガイド」の中の 「フォーマット文字列オブジェクト」 を見なさい。

もし1つの文字列が複数の引数を含むならば、 翻訳者は、書式作成文字の間に、特別なタグ n$を(nが元の引数の位置がどこかを指定)挿入することができる。 これらのタグによって、翻訳者は元の文字列に現れる引数を並べ直すことができる。 以下の例は、二つ引数が翻訳された文字列で逆にされる文字列を示す。
/* 何か失敗したとき、アラートパネルに出すメッセージ */ 
"Oh %@! %@ failed!" ="%2$@ blah blah、%1$@ oh!"; 

文字列リソースで特別な文字を使う

Cの文字列と同様に、いくつかの文字はきちんと、文字列に含まれる「\」(英語環境ではバックスラッシュ)でプリフィックスしなければならない。 これらの文字は、ダブルクォート(\")、バックスラッシュ(\\)とキャリッジ・リターン(\n)を含む。 あなたは、「\n」でキャリッジ・リターンを指定することもできる。
"File \"%@\" cannot be opened" = " ... ";
"Type \"OK\" when done" = " ... ";
文字列は、Unicode文字を意味している「\U」に最高4つの16進数字が続く任意のUnicode文字を含むこともできる。 たとえば、スペースは「\U0020」として表現される。 文字列が何かの理由で入力することができないUnicode文字を含まなければならないならば、この記法が役に立つ。
この記法を使用するならばあなたは、16進数字が、結果として生じる文字列ファイルで正しく解釈されるよう -uオプションもgenstringsに渡さなければならない。 genstringsツールは、あなたの文字列がデフォルトで0x00~0x7fまでのASCII文字(low-ASCII)であると仮定する。 そして-uオプションが指定されたなら、バックスラッシュ列を解釈する。
注:
genstringsツールは、常にUTF-16エンコーディングを用いた文字列ファイルを生成する。
あなたがUnicode文字を文字列に含め、かつ文字列ファイルを作成するためにgenstringsを使わないならば、 必ずUTF-16エンコーディングで、あなたの文字列ファイルを保存するようにしなさい。
・・・て書いてあるけど、UTF-8でも良いのは前述の通り。 ヘルプから察するに、現在のgenstringsは読み込み側はUTF-8になっているので、出力側もそうだと思う。

文字列ファイルのデバッグ

テストの間に問題が起こって、文字列を取り出すための関数とマクロが、(翻訳された値と対照的に)同じキーを常に返しているとわかるならば、 /usr/bin/plutilツールを文字列ファイルに対して実行する。

文字列ファイルは、基本的に、特別な方法で書式を設定されるプロパティー・リストファイルである。 plutil -lintを実行すると、文字列が正しく取り出されるのを妨げている隠れた文字または他のエラーを見つけることができる。