strings ファイル
各国語化の工程の重要な部分は、あなたのアプリケーションによって表示されるテキスト文字列のすべてを翻訳することを伴います。
本質的に、既に(nib ファイルといった)リソースファイルに配置されている文字列は、各国語化できる用意ができているといえます。
あなたのコードに埋め込まれた文字列は問題となることがあり、そのため、これらを各国語化できるように、リソースファイルへ抜き出す必要があります。
たとえば、標準的な関数を用いるアラート【警告】ボックスを表示する際に、一般的にあなたのコードはそのアラートボックスの中で表示するためのテキストを伴う文字列を指定します。これはユーザの目に触れるため、そのアラートボックス内の文字列はあなたのコードから抜き出し、リソースファイルへ配置しなければいけません。
Mac OS X は、埋め込まれた文字列を抜き出し、使用する工程を、strings ファイルを通じて簡単にしています。
strings ファイルは、特定の各国語化のための文字列リソースを格納している、UTF-16 でエンコードされたテキストファイルです。(「strings ファイル」という名前は、そのファイル自体が .strings という拡張子を持つ事実に由来しています。)
一般的なアプリケーションは、各国語化あたり最低一つ、つまり、バンドルの各 .lproj サブディレクトリごとに一つの strings ファイルを持ちます。
strings ファイルのデフォルトの名前は Localizable.strings ですが、あなたは関連する文字列を互いにグループ化するための必要に応じて、追加の strings ファイルを作成することができます。
注: UTF-8 を用いてエンコードされた strings ファイルの動作は保障されていません。疑わしいときは、UTF-16 を用いてエンコードしてください。
strings ファイルの内容は、一つ以上のキーと値の組で構成されています。
各キーはあなたのコードによって使用され、翻訳の必要がある、単一の文字列を区別します。そのキーに関連付けられた値は、翻訳された文字列です。
あなたのコードが文字列を表示しようとするときはいつでも、必要なキーを適切なバンドルルーチンに渡します。バンドルが返すものが、現在のユーザのために翻訳されたテキストを含む文字列となります。
あなたは strings ファイルを手動でも、プログラム的にも作成することができます。
もし、あなたが文字列を取得するために CFBundle や NSBundle 関数を使用しているのであれば、あなたは genstrings ツールを用いて、あなたのアプリケーションのための strings ファイルをプログラム的に生成することができます。詳細は、「strings ファイルを生成する」(39ページ)を参照してください。
strings ファイルから文字列を取得する
Core Foundation および Cocoa は共に、strings ファイルに記録された文字列を取得するための便利機能を提供しています。
以下のセクションでは、文字列を取得するための関数とメソッドの一覧を、あなたのコードでこれらをどのように使用するかの例と一緒に提供します。
注:これらのセクションにおける関数とメソッドの使用は推奨されています。これらは genstrings ツールを用いて自動的にあなたの初期 strings ファイルを生成することを容易にするためです。
Core Foundation を使用する
Core Foundation フレームワークは、あなたのアプリケーションバンドルから各国語化された文字列を取得するための、一つの関数といくつかのマクロを定義しています。
CFBundleCopyLocalizedString 関数は、文字列の取得のための基本的な実装を提供します。けれども、一般的に、あなたは代わりに以下のマクロを文字列取得のために使用すべきです…
- CFCopyLocalizedString
- CFCopyLocalizedStringFromTable
- CFCopyLocalizedStringFromTableInBundle
- CFCopyLocalizedStringWithDefaultValue
これらのマクロは二つの利点をもたらします。
第一に、あなたは特定の文字列が定義されているのがどこか【どのファイルか】を知っている場合に、特定の strings ファイルの名前を指定することができます。
第二に、genstrings ツールはあなたのコード内でこれらの場所を特定することができ、翻訳可能文字列の初期テーブルを作成するためにこれら【上記マクロに設定された値】を利用します。
これらのマクロの使い方についての補足情報は、Bundle Programming Guideの、"Working With Localized Strings"を参照してください。マクロと関数の構文については、CFBundle のリファレンスを参照してください。
Cocoa を使用する
Cocoa は、アプリケーションバンドルの外【?】の各国語化された文字列を取得するために、以下のマクロを定義しています。
- NSLocalizedString
- NSLocalizedStringFromTable
- NSLocalizedStringFromTableInBundle
- NSLocalizedStringWithDefaultValue
また、あなたは適切な strings ファイルから、各国語化された文字列を取得するために、NSBundle クラスを使用することもできます。
localizedStringForKey:value:table: メソッドは、指定された strings ファイルから、各国語化されたバージョンの文字列を返します。このメソッドの table パラメータに、strings ファイルの名前を―.strings 拡張子を除いて―指定してください。もしこのパラメータに nil を渡すと、このメソッドは Localizable.strings という名のファイル内で文字列を探します。詳細は、NSBundle の資料を参照してください。
文字列の取得の例
以下の例は、アプリケーションのフランス語各国語化に、Custom.strings という名前の strings ファイルが存在していることを想定しています。このファイルの内容は以下の通りです…
/* A comment */
"Yes" = "Oui";
"The same text in English" = "Le même texte en français";
Cocoa アプリケーションからは、あなたはここに示す通り、NSLocalizedStringFromTable マクロを用いて"YES"文字列の値を取得することができます…
NSString* theString;
theString = NSLocalizedStringFromTable (@"Yes", @"Custom", @"A comment");
Core Foundation アプリケーションからは、あなたはここに示す通り、CFCopyLocalizedStringFromTable 関数を用いて同じ文字列を取得することができます…
CFStringRef theString;
theString = CFCopyLocalizedStringFromTable(CFSTR("Yes"), CFSTR("Custom"), "A comment");
strings ファイルを生成する
strings ファイルは、あなたのアプリケーションによって使用される文字列の各国語化されたバージョンを格納しているリソースファイルです。
以下のセクションではこれらのファイルを作成するためのテクニックを説明します。
各国語化する文字列を選択する
あなたのアプリケーションのインタフェースを各国語化する時がやってきたら、あなたのアプリケーションが使用するすべての文字列を各国語化してしまうというのは、必ずしも適切ではありません。
翻訳はコストのかかる工程であり、ユーザの眼に触れることのない文字列を翻訳することは時間と費用の浪費です。
ユーザに対して表示されるすべての文字列は、翻訳の目的のために strings ファイル内にするべきです。
ユーザに対して表示されない文字列、たとえばあなたのアプリケーションが内部的に使用する通知名などは、翻訳する必要はありません。
ここに示す、もう一つの例を考えてみてください…
if (CFStringHasPrefix(value, CFSTR("-")) { CFArrayAppendValue(myArray, value);};
文字列"-"は内部的に用いられ、ユーザの眼に触れることはないため、strings ファイルに配置する必要はありません。
ユーザが見ることはないであろう文字列のもう一つの例は、以下の C 構文に含まれています。
matches = sscanf(s, "%d %d %s", &first, &last, &other);
文字列"%d %d %s"は、ユーザが見ることはなく、ユーザが目にするあらゆるものに対して一切影響がないため、各国語化する必要はありません。対して、アラートパネルに現れる文字列は各国語化する必要があります。
genstrings ツールを使用する
strings ファイルを生成するための最も単純な方法は、コマンドラインから genstrings ツールを使用することです。このツールはあなたの指定したソースファイルを分析して、NSLocalizedString、CFCopyLocalizedString、およびこれらの変種(「strings ファイルから文字列を取得する」(37ページ)のセクション内で一覧にされています)の呼び出しを見つけます。
また、あなたは -s オプションを用いることで、 genstrings にあなたの独自ルーチンを探すように伝えることもできます。
このツールは、適切な strings ファイル内にエントリを生成するために、これらのマクロ内の情報を利用します。
関数とマクロのいくつかは、あなたが検索したい strings ファイルの名前を指定することのできる、table パラメータを含んでいます。(table パラメータに値を指定するときは、.strings 拡張子を含めないでください。)
ユニーク【一意】なテーブル名に出会うたびに、genstrings は新しい strings ファイルを作成し、対応する文字列をそのファイル内に置きます。
関数やマクロが table 名を含まない場合は、genstrings は対応する文字列を、デフォルトファイルである Localizable.strings の中に配置します。
もし、あなたのマクロの中に翻訳コメントを含んでいたら、genstrings ツールはこれらのコメントを文字列エントリと一緒に strings ファイルに書き込みます。
コメントは、その文字列が何のために用いられているのかについての、よりよい認識を翻訳者に与え、翻訳作業の間の時間と予算を共に節約します。
一つの strings ファイルの中の各キーは、ユニークでなければいけません。
genstrings ツールは、けれども、重複したエントリを結合します。そのため、もしあなたのコードが、同じキーをいくつかの異なる場所で使用していたら、このツールは strings ファイル内に単一のエントリを作成し、各エントリからのコメントを数珠繋ぎにします。また、このツールはキーが複数回使用されていたことを警告する出力を生成します。
各ファイルごとにそのキーがただの一度だけ現れている限り、同一のキーを異なる strings ファイル内で使用することは問題ありません。
Cocoa と Core Foundation は共に、あなたに各文字列に対するデフォルト値を指定させるためのルーチンを提供します。
もしあなたがデフォルト値を指定しなければ、genstrings はデフォルトではキーと値に同じ文字列を使用します。同じ文字列を使用することは、もしその文字列がHigh-ASCII文字【拡張ASCII文字】セットからの文字を含んでいたときに、問題となります。(これらの文字は、通常はASCII文字のアクセント記号付きバージョンです。)strings ファイル内のキーはいかなるHigh-ASCII文字も含むことができませんが、これらのキーに対する値はそうした文字を含むことが可能です。
あなたにデフォルト値を指定させる関数やマクロを使用することは、この問題を解決します。
genstrings ツールの使用についての詳細は、genstrings man page を参照してください。
strings ファイルを手作業で作成する
strings ファイルを手作業で作成するには、テキストファイルを作成し、Unicode UTF-16 エンコーディングを用いて保存してください。各国語化する必要のある文字列を、以下の例に示す形式を用いて、そのファイル内に配置してください…
/* A comment */
"Yes" = "Oui";
"The same text in English" = "Le même texte en français";
左辺の文字列は、右辺の文字列を取得するためにあなたのコードで使用するキーとなります。キーと値のそれぞれの組は、セミコロンを続ける必要があります。
あなたは、前述の例に示した C 言語形式のコメント囲いを用いて、各組の上にコメントを含めることができます。
文字列を整形する
(Cocoa の stringWithFormat: メソッドや Core Foundation の CFStringCreateWithFormat 関数といった)いくつかの関数およびメソッドは、あなたに文字列の中に書式文字【formatting characters】を含めさせます。
これらの関数とメソッドのために、あなたは以下の例に示す通り、 strings ファイルのエントリのキーと値の双方に書式文字を指定することができます。
"Windows must have at least %d columns and %d rows." =
"Les fenêtres doivent être composes de %d colonnes et %d lignes au minimum.";
"File %@ not found." = "Le fichier %@ n’existe pas.";
注: %@ 指定子は、標準 printf() 書式文字を拡張したものです。これは Cocoa と Core Foundation 独自のオブジェクトを表します。指定子の完全なリストについては、String Programming Guide for Cocoaの、"Formatting String Objects"を参照してください。
翻訳者は、必要であれば翻訳された文字列内の引数を並べ替えることができます。
もし、文字列が複数の引数を含んでいたら、翻訳された文字列はそれぞれの引数に対して、n が元の引数の位置を表すとして、 [n][$] 修飾語 [] n$ 修飾語 を使用することができます。【原文の誤記か?】
たとえば、以下の strings ファイルエントリは二つの引数の順序を入れ替えます。
/* Message in alert dialog when something fails */
"%@ Error! %@ failed!" = "%2$@ blah blah, %1$@ blah!";
ちょうど C 言語と同様に、いくつかの文字はあなたが文字列の中に置けるようにする前にバックスラッシュを接頭辞として付け加える必要があります。これには二重引用符【"】、バックスラッシュ【\】、キャリッジリターン【改行】といった文字が含まれます。あなたはキャリッジリターンを \n で指定することができます。
"File \"%@\" cannot be opened" = " ... ";
"Type \"OK\" when done" = " ... ";
あなたは、\\U の直後に四桁までの16進数を続けて指定することにより、Unicode 独自の文字を値の文字列の中に含めることができます。
四つの数字は、求める Unicode 文字のためのエントリを表します。たとえば、空白文字は十六進数の 20 で表されるため、Unicode 文字として指定するときは \\U0020 となるでしょう。
このオプションは、文字列が何らかの理由により入力できない Unicode 文字を含まなければならない場合に有用です。
あなたは常に strings ファイルを Unicode UTF-16 形式で保存すべきです。
テキストエディット アプリケーションはファイルを Unicode 形式で保存することができます。あなたはプレーンテキストモードの保存ダイアログか、テキストエディットの「一般」環境設定のいずれかでエンコーディングを選択することができます。
各国語化できない文字列を検出する
あなたは文字列に関する各国語化の問題を検出するために役立つ、二つのデフォルト設定を使用することができます。
-
NSShowNonLocalizableStrings デフォルト設定は、各国語化不能な文字列を見分けます。文字列はシェルに大文字でログ出力されます。
このオプションは時おり誤検出【false positive】を生じますが、全体としては有用なテクニックです。
- NSShowNonLocalizedStrings デフォルト設定は、各国語化可能であるが strings ファイル内に見つけられないという文字列を特定します。あなたはこのオプションを、古い各国語化に伴う問題を捕らえるために使用することができます。
これらの設定を用いるには、あなたのアプリケーションをコマンドラインから起動する必要があります。あなたの実行可能ファイルへのパスに加えて、設定の名前を、あなたがそれを記録したいかどうかを示す真偽値と共に含めます。
たとえば、テキストエディット アプリケーションに NSShowNonLocalizedStrings 設定を使用するには、ターミナルで以下を入力することになります…
/Applications/TextEdit.app/Contents/MacOS/TextEdit -NSShowNonLocalizedStrings YES
strings ファイルをデバッグする
もしあなたが、試験中に問題に出くわし、文字列を取得する関数とマクロが(翻訳された値ではなく)常に同じキーを返すことを発見したら、あなたの strings ファイルに /usr/bin/plutil ツールを実行してください。
strings ファイルは特殊な形式のプロパティリスト ファイルです。plutil をこのファイル上で実行することにより、隠れた文字を発見したり、文字列を正常に取得されることから阻むその他のエラーを発見することができます。