私は(他のすべてと同様に)NSLocalizedString
を使用してアプリをローカライズしています。
残念ながら、いくつかの「欠点」があります(必ずしもNSLocalizedString自体の障害ではありません)。
genstring
が1つの文字列に対して複数のコメントになりますgenstring
を使用する場合、古いローカリゼーションを失わないように注意する必要があります。NSLocalizedString(@"Abort", @"Cancel action")
を使用した後、コードレビューにより、コードの一貫性を高めるために文字列の名前をNSLocalizedString(@"Cancel", @"Cancel action")
に変更するように求められます。私が行うこと(およびSOを検索した後、多くの人がこれを行うと考えた)は、すべてのローカライズコードをstrings.h
する別個の#define
ファイルを持つことです。例えば
// In strings.h
#define NSLS_COMMON_CANCEL NSLocalizedString(@"Cancel", nil)
// Somewhere else
NSLog(@"%@", NSLS_COMMON_CANCEL);
これは本質的に、コード補完、変数名を変更するための単一の場所(そのため、もはやgenstringを必要としない)、および自動リファクタリングするための一意のキーワードを提供します。ただし、これは、本質的に構造化されていない(つまり、LocString.Common.Cancelなどの)#define
ステートメントの束で終わるという代償を伴います。
だから、これはいくぶんうまく機能するが、私はあなたたちがあなたのプロジェクトでどのようにそれをするのかと思っていた。 NSLocalizedStringの使用を簡素化する他のアプローチはありますか?多分それをカプセル化するフレームワークもありますか?
NSLocalizedString
にはいくつかの制限がありますが、Cocoaの中心であるため、ローカライズを処理するカスタムコードを記述するのは不合理です。つまり、使用する必要があります。とはいえ、小さなツールが役立つ場合がありますが、ここに私が進める方法があります:
genstrings
は文字列ファイルを上書きし、以前の翻訳をすべて破棄します。 pdate_strings.py と書いて、古い文字列ファイルを解析し、genstrings
を実行し、空白を埋めて、既存の翻訳を手動で復元する必要がないようにしました。スクリプトは、既存の文字列ファイルをできるだけ密接に一致させて、更新時に大きすぎるdiffを作成しないようにします。
NSLocalizedString
を宣伝どおりに使用する場合:
NSLocalizedString(@"Cancel or continue?", @"Cancel notice message when a download takes too long to proceed");
コードの別の部分で同じ文字列を定義することになりますが、同じ英語の用語が異なるコンテキストで異なる意味を持つ可能性があるため、競合する可能性があります(OK
とCancel
が思い浮かびます)。そのため、モジュール固有のプレフィックスと非常に正確な説明を含む無意味な全大文字文字列を常に使用します。
NSLocalizedString(@"DOWNLOAD_CANCEL_OR_CONTINUE", @"Cancel notice window title when a download takes too long to proceed");
同じ文字列を複数回使用する場合は、マクロを使用するか、View Controllerまたはデータソースのインスタンス変数としてキャッシュすることができます。この方法では、同じローカリゼーションのインスタンス間で古くなったり矛盾したりする可能性のある説明を繰り返す必要がなく、常に混乱を招きます。インスタンス変数はシンボルであるため、これらの最も一般的な翻訳でオートコンプリートを使用し、特定の文字列に「手動」文字列を使用できます。
これらのヒントを使用して、Cocoaローカリゼーションの生産性を高めてください。
Xcodeの文字列の自動補完については、 http://questbe.at/lin/ を試すことができます。
Ndfredには同意しますが、これを追加したいと思います。
2番目のパラメーターは...デフォルト値として使用できます!!
(NSLocalizedStringWithDefaultValueはgenstringで適切に動作しないため、このソリューションを提案しました)
デフォルト値としてコメントを使用するNSLocalizedStringを使用するカスタム実装は次のとおりです。
1。事前にコンパイルされたヘッダー(.pchファイル)で、「NSLocalizedString」マクロを再定義します:
// cutom NSLocalizedString that use macro comment as default value
#import "LocalizationHandlerUtil.h"
#undef NSLocalizedString
#define NSLocalizedString(key,_comment) [[LocalizationHandlerUtil singleton] localizedString:key comment:_comment]
2。ローカライズハンドラーを実装するクラスを作成する
#import "LocalizationHandlerUtil.h"
@implementation LocalizationHandlerUtil
static LocalizationHandlerUtil * singleton = nil;
+ (LocalizationHandlerUtil *)singleton
{
return singleton;
}
__attribute__((constructor))
static void staticInit_singleton()
{
singleton = [[LocalizationHandlerUtil alloc] init];
}
- (NSString *)localizedString:(NSString *)key comment:(NSString *)comment
{
// default localized string loading
NSString * localizedString = [[NSBundle mainBundle] localizedStringForKey:key value:key table:nil];
// if (value == key) and comment is not nil -> returns comment
if([localizedString isEqualToString:key] && comment !=nil)
return comment;
return localizedString;
}
@end
。使用してください!
アプリのビルドフェーズにRunスクリプトを追加して、Localizable.stringsファイルがビルドごとに更新されるようにしてください。つまり、Localized.stringsファイルに新しいローカライズされた文字列が追加されます。
私のビルドフェーズスクリプトはシェルスクリプトです。
Shell: /bin/sh
Shell script content: find . -name \*.m | xargs genstrings -o MyClassesFolder
したがって、この新しい行をコードに追加すると、次のようになります。
self.title = NSLocalizedString(@"view_settings_title", @"Settings");
次に、ビルドを実行すると、。/ Localizable.scriptsファイルに次の新しい行が含まれます。
/* Settings */
"view_settings_title" = "view_settings_title";
そして、「view_settings_title」のキー==値なので、カスタムLocalizedStringHandlerはコメント、つまり「設定」を返します
Voilà:-)
Swiftでは、以下を使用しています。この場合の「はい」ボタンの場合:
NSLocalizedString("btn_yes", value: "Yes", comment: "Yes button")
デフォルトのテキスト値のvalue:
の使用に注意してください。最初のパラメーターは変換IDとして機能します。 value:
パラメータを使用する利点は、デフォルトのテキストを後で変更できるが、翻訳IDは同じままであるということです。 Localizable.stringsファイルには"btn_yes" = "Yes";
が含まれます
value:
パラメーターが使用されなかった場合、最初のパラメーターは、翻訳IDとデフォルトのテキスト値の両方に使用されます。 Localizable.stringsファイルには"Yes" = "Yes";
が含まれます。この種のローカライズファイルの管理は奇妙に思えます。特に、翻訳されたテキストが長い場合、IDも長くなります。デフォルトのテキスト値の文字が変更されるたびに、翻訳IDも変更されます。これは、外部翻訳システムを使用する場合に問題につながります。翻訳IDの変更は、新しい翻訳テキストを追加することと理解されますが、これは常に望ましいとは限りません。
Localizable.stringsを複数の言語で維持するためのスクリプトを作成しました。自動補完には役立ちませんが、コマンドを使用して.stringsファイルをマージするのに役立ちます:
merge_strings.rb ja.lproj/Localizable.strings en.lproj/Localizable.strings
詳細については、 https://github.com/hiroshi/merge_strings を参照してください
あなたの何人かはそれが役に立つと思います。
私自身は、多くの場合、エントリを.stringsファイルに入れるのを忘れて、コーディングに夢中になります。したがって、.stringsファイルに戻して翻訳する必要があるものを見つけるためのヘルパースクリプトがあります。
NSLocalizedStringで独自のマクロを使用しているため、使用する前にスクリプトを確認して更新してください NSLocalizedStringの2番目のパラメーターとしてnilが使用されていると仮定しました。変更したい部分は
NSLocalizedString\(@(".*?")\s*,\s*nil\)
マクロとNSLocalizedStringの使用法に一致するものに置き換えてください。
ここにスクリプトがあります。実際に必要なのはパート3だけです。残りは、すべてがどこから来たのかを簡単に確認することです:
// Part 1. Get keys from one of the Localizable.strings
Perl -ne 'print "$1\n" if /^\s*(".+")\s*=/' myapp/fr.lproj/Localizable.strings
// Part 2. Get keys from the source code
grep -n -h -Eo -r 'NSLocalizedString\(@(".*?")\s*,\s*nil\)' ./ | Perl -ne 'print "$1\n" if /NSLocalizedString\(@(".+")\s*,\s*nil\)/'
// Part 3. Get Part 1 and 2 together.
comm -2 -3 <(grep -n -h -Eo -r 'NSLocalizedString\(@(".*?")\s*,\s*nil\)' ./ | Perl -ne 'print "$1\n" if /NSLocalizedString\(@(".+")\s*,\s*nil\)/' | sort | uniq) <(Perl -ne 'print "$1\n" if /^\s*(".+")\s*=/' myapp/fr.lproj/Localizable.strings | sort) | uniq >> fr-localization-delta.txt
出力ファイルには、Localizable.stringsファイルではなく、コードで見つかったキーが含まれています。サンプルを次に示します。
"MPH"
"Map Direction"
"Max duration of a detailed recording, hours"
"Moving ..."
"My Track"
"New Trip"
確かにもっと磨くことができますが、共有したいと思いました。
Swiftソリューションを探している場合。私がここにまとめた私のソリューションを確認することをお勧めします:SwiftyLocalization
いくつかの設定手順を行うだけで、Googleスプレッドシートで非常に柔軟なローカライズが可能になります(コメント、カスタムカラー、ハイライト、フォント、複数シートなど)。
要するに、手順は次のとおりです。Googleスプレッドシート-> CSVファイル-> Localizable.strings
さらに、Localizables.Swiftも生成します。これは、キーの取得とデコードのインターフェイスのように動作する構造体です(キーからStringをデコードする方法を手動で指定する必要があります)。
なぜこれが素晴らしいのですか?
ローカライズ可能なキーをオートコンプリートできるツールがありますが。実際の変数への参照は、それが常に有効なキーであることを保証します。そうでなければ、コンパイルされません。
// It's defined as computed static var, so it's up-to-date every time you call.
// You can also have your custom retrieval method there.
button.setTitle(Localizables.login.button_title_login, forState: .Normal)
このプロジェクトは、Google App Scriptを使用してSheets-> CSVを変換し、Pythonスクリプトを使用してCSVファイルを変換します-> Localizable.strings.
#define PBLocalizedString(key, val) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:(val) table:nil]
iOS 7およびXcode 5では、「Localization.strings」メソッドの使用を避け、新しい「base localisation」メソッドを使用する必要があります。 「ベースローカリゼーション」をグーグルで検索する場合、いくつかのチュートリアルがあります
Apple doc: ベースのローカライズ