145

私は(他のすべての人と同じように)NSLocalizedString自分のアプリをローカライズするために使用しています。

残念ながら、次のようないくつかの「欠点」があります(必ずしもNSLocalizedString自体の障害ではありません)。

  • Xcodeの文字列の自動補完はありません。これにより、エラーが発生しやすくなるだけでなく、作業が面倒になります。
  • 同等の文字列がすでに存在することを知らなかったという理由だけで、文字列を再定義してしまう可能性があります(つまり、「パスワードを入力してください」と「最初にパスワードを入力してください」)。
  • オートコンプリートの問題と同様に、コメント文字列を「記憶」/コピーして貼り付ける必要があります。そうしない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はもう必要ありません)、および自動リファクタリングのための一意のキーワードを提供します。ただし、これには、#define本質的に構造化されていない(つまり、LocString.Common.Cancelなどの)ステートメントが大量に発生するという犠牲が伴います。

ですから、これはある程度うまく機能しますが、皆さんがプロジェクトでどのようにそれを行うのか疑問に思いました。NSLocalizedStringの使用を簡素化する他のアプローチはありますか?それをカプセル化するフレームワークさえあるのでしょうか?

4

9 に答える 9

101

NSLocalizedStringにはいくつかの制限がありますが、Cocoa にとって非常に重要であるため、ローカリゼーションを処理するカスタム コードを作成するのは合理的ではありません。つまり、それを使用する必要があります。とはいえ、ちょっとしたツールが役に立ちます。次のように進めます。

文字列ファイルの更新

genstrings文字列ファイルを上書きし、以前の翻訳をすべて破棄します。update_strings.pyを作成して、古い文字列ファイルを解析し、実行genstringsて空白を埋めて、既存の翻訳を手動で復元する必要がないようにしました。スクリプトは、既存の文字列ファイルをできるだけ厳密に一致させて、更新時に差分が大きくなりすぎないようにします。

文字列に名前を付ける

NSLocalizedString宣伝どおりに使用する場合:

NSLocalizedString(@"Cancel or continue?", @"Cancel notice message when a download takes too long to proceed");

コードの別の部分で同じ文字列を定義することになる可能性があります。これは、同じ英語の用語が異なるコンテキストで異なる意味を持つ可能性があるため、競合する可能性があります (OKCancel頭に浮かぶ )。そのため、モジュール固有のプレフィックスと非常に正確な説明を含む意味のないすべて大文字の文字列を常に使用します。

NSLocalizedString(@"DOWNLOAD_CANCEL_OR_CONTINUE", @"Cancel notice window title when a download takes too long to proceed");

異なる場所で同じ文字列を使用する

同じ文字列を複数回使用する場合は、以前と同じようにマクロを使用するか、View Controller またはデータ ソースでインスタンス変数としてキャッシュすることができます。こうすれば、同じローカリゼーションのインスタンス間で古くなって一貫性がなくなり、常に混乱を招く可能性のある説明を繰り返す必要がなくなります。インスタンス変数はシンボルであるため、これらの最も一般的な翻訳に対してオートコンプリートを使用し、特定の翻訳に対して「手動」文字列を使用することができます。これはとにかく一度しか発生しません。

これらのヒントを参考にして、Cocoa ローカリゼーションの生産性を高めてください。

于 2012-04-17T17:49:45.823 に答える
25

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

3.それを使用してください!

アプリのビルドフェーズで実行スクリプトを追加して、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";

また、key == value for'view_settings_title'であるため、カスタムLocalizedStringHandlerはコメント、つまり'Settings"を返します。

Voilà:-)

于 2012-05-09T09:27:13.983 に答える
2

Swiftソリューションを探している人なら。ここにまとめた私のソリューションをチェックしてみてください: SwiftyLocalization

いくつかの手順をセットアップするだけで、Google スプレッドシートで非常に柔軟なローカリゼーション (コメント、カスタム カラー、ハイライト、フォント、複数のシートなど) を使用できます。

要するに、手順は次のとおりです。Google スプレッドシート --> CSV ファイル --> Localizable.strings

さらに、Localizables.swift も生成します。これは、キーの取得とデコードへのインターフェイスのように機能する構造体です (ただし、キーから文字列をデコードする方法を手動で指定する必要があります)。

なぜこれが素晴らしいのですか?

  1. いたるところにプレーンな文字列としてキーを用意する必要はなくなりました。
  2. 間違ったキーはコンパイル時に検出されます。
  3. Xcode はオートコンプリートを実行できます。

ローカライズ可能なキーをオートコンプリートできるツールがあります。実際の変数への参照は、それが常に有効なキーであることを保証します。それ以外の場合はコンパイルされません。

// 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 を使用してシートを変換します --> CSV と、Python スクリプトを使用して CSV ファイルを変換します --> Localizable.strings このサンプル シートを簡単に見て、何が可能かを知ることができます。

于 2016-10-13T06:00:34.130 に答える
2

Localizable.strings を複数の言語で維持するためのスクリプトを作成しました。オートコンプリートには役立ちませんが、次のコマンドを使用して .strings ファイルをマージすると役立ちます。

merge_strings.rb ja.lproj/Localizable.strings en.lproj/Localizable.strings

詳細については、 https ://github.com/hiroshi/merge_strings を参照してください。

役に立つと思う人もいると思います。

于 2013-09-29T02:56:18.870 に答える
1

iOS 7 および Xcode 5 では、'Localization.strings' メソッドの使用を避け、新しい 'base localisation' メソッドを使用する必要があります。「ベースローカリゼーション」をグーグルで検索すると、いくつかのチュートリアルがあります

Apple doc :基本ローカリゼーション

于 2014-02-02T16:36:46.260 に答える
0

私自身、コーディングに夢中になり、エントリを .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"

確かにもっと磨くことができますが、共有したいと思います。

于 2016-04-07T14:59:18.490 に答える
0
#define PBLocalizedString(key, val) \

[[NSBundle mainBundle] localizedStringForKey:(key) value:(val) table:nil]
于 2013-06-27T09:05:30.460 に答える