アプリを再起動することなく、アプリ内で言語を変更できるアプリもあるようですが、どのように実装されているのでしょうか。
たとえば、NSLocalizedString
を使用する場合、AppDelegate
が初期化されていないときに、main.m
の実行時に言語を設定できることはわかっていますが、一度初期化されると(特にView Controllerが作成されます) )、次のrestartまで有効にならない変更
[[NSUserDefaults standardUserDefaults]
setObject:[NSMutableArray arrayWithObjects:language, nil]
forKey:@"AppleLanguages"];
アプリを再起動せずに、これらの動的な言語の変更を行う方法を知っている人はいますか?
ここでは、他のアプローチ、特に通知ベースのアプローチについて説明します。
iOS:アプリを再起動せずにプログラムでアプリの言語を変更する方法
私の見解では、実際には3つのタスクがあります。(1)nibsから自動的にロードされたリソースの再ローカリゼーション。 (たとえば、nibから別のカスタムUIViewを動的にインスタンス化する場合、「古い」言語の文字列と設定(画像、テキストの方向)がロードされます)(2)画面に現在表示されている文字列の再ローカライズ。 (3)開発者(あなた)がプログラムコードに挿入した文字列の再ローカライズ。
(3)から始めましょう。定義を探すと、NSLocalizedStringがマクロであることがわかります。したがって、既存のコードをあまり変更したくない場合は、おそらく新しいヘッダーファイルを作成することで(3)の問題を解決できます。そのヘッダーファイルでは、#undef
その後、再#define NSLocalizedString
適切な場所からローカライズされた文字列を選択します。iOSのデフォルトではなく、グローバル変数(アプリデリゲートivarなど)で追跡する文字列です。 NSLocalizedStringを再定義したくないが、それでも独自の代替を作成する場合は、おそらく#undef NSLocalizedString
将来の開発者が、置換するマクロの代わりに誤って呼び出すことを望まない場合。理想的なソリューションではありませんが、おそらく最も実用的なソリューションです。
(1)については、Interface Builderでローカライズを行っていないが、viewDidLoadなどで動的に行っている場合は問題ありません。先ほど説明したのと同じ動作(つまり、変更されたNSLocalizedStringなど)を使用できます。それ以外の場合は、(a)上記のリンクで説明されているように通知システムを実装する(複雑な)か、(b)ローカリゼーションをIBからviewDidLoadに移行することを検討するか、(c)initWithNibName:
そして、古い言語リソースでロードされたオブジェクトを、新しい言語リソースでロードされたオブジェクトと交換します。これは、この議論の一番下でMohamedが言及したアプローチでした: http://learning-ios.blogspot.ca/2011/04/advance-localization-in-ios-apps.html 。彼はそれが問題を引き起こすと主張しています(viewDidLoadは呼び出されません)。動作しない場合でも、試してみると、動作する何かを示す可能性があります。
最後に、(2)はおそらく最も簡単なタスクです。現在のビューを削除して再追加するだけです(場合によっては再描画するだけです)。
アイデアは、別の特定のバンドルから翻訳を取得するかどうかを確認するNSLocalizedString
のような新しいマクロを作成することです。
method 2 in this article でその方法を正確に説明しています。この特定のケースでは、作成者は新しいマクロを使用しませんが、直接カスタムクラスを設定します _[NSBundle mainBundle]
_の場合。
@holexがこれを読んでいる問題を理解することを願っています。
私の実装では、クラスを使用して言語を変更し、現在の言語バンドルにアクセスします。これは一例であるため、私とは異なる言語を使用する場合は、メソッドを変更して正確な言語コードを使用してください。
このクラスは、NSLocaleから優先言語にアクセスし、使用されている言語である最初のオブジェクトを取得します。
@implementation OSLocalization
+ (NSBundle *)currentLanguageBundle
{
// Default language incase an unsupported language is found
NSString *language = @"en";
if ([NSLocale preferredLanguages].count) {
// Check first object to be of type "en","es" etc
// Codes seen by my eyes: "en-US","en","es-US","es" etc
NSString *letterCode = [[NSLocale preferredLanguages] objectAtIndex:0];
if ([letterCode rangeOfString:@"en"].location != NSNotFound) {
// English
language = @"en";
} else if ([letterCode rangeOfString:@"es"].location != NSNotFound) {
// Spanish
language = @"es";
} else if ([letterCode rangeOfString:@"fr"].location != NSNotFound) {
// French
language = @"fr";
} // Add more if needed
}
return [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]];
}
/// Check if preferred language is English
+ (BOOL)isCurrentLanguageEnglish
{
if (![NSLocale preferredLanguages].count) {
// Just incase check for no items in array
return YES;
}
if ([[[NSLocale preferredLanguages] objectAtIndex:0] rangeOfString:@"en"].location == NSNotFound) {
// No letter code for english found
return NO;
} else {
// Tis English
return YES;
}
}
/* Swap language between English & Spanish
* Could send a string argument to directly pass the new language
*/
+ (void)changeCurrentLanguage
{
if ([self isCurrentLanguageEnglish]) {
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
} else {
[[NSUserDefaults standardUserDefaults] setObject:@[@"en"] forKey:@"AppleLanguages"];
}
}
@end
上記のクラスを使用して、文字列ファイル/画像/ビデオ/などを参照します。
// Access a localized image
[[OSLocalization currentLanguageBundle] pathForResource:@"my_image_name.png" ofType:nil]
// Access a localized string from Localizable.strings file
NSLocalizedStringFromTableInBundle(@"StringKey", nil, [OSLocalization currentLanguageBundle], @"comment")
以下のようにインラインで言語を変更するか、上記のクラスの「changeCurrentLanguage」メソッドを更新して、新しい言語コードを参照する文字列パラメーターを取得します。
// Change the preferred language to Spanish
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
私は常にこの方法を使用していますが、完璧に機能し、あなたにも役立つかもしれません。
すべてのUI
の_-viewWillAppear:
_メソッドで、現在の言語のUIViewController
にNSLocalizableString(...)
を使用してすべてのテキストを設定する必要があります。
この方法を使用すると(つまり、ユーザー)再起動する必要はありませんSettingsでiOS
の言語を変更した後のアプリケーション。
もちろん、私はAppleの標準的なローカライズアーキテクチャを使用しています。
アプリケーションがフォアグラウンドに入ると、実際のビューに対して_–viewWillAppear:
_メソッドが実行されないことを経験しました。この問題を解決するために、ビューでUIApplicationWillEnterForegroundNotification
通知を受け取ったときに手順(上記を参照)もコミットします。
私は同じ問題で立ち往生しました、私の要件は「ユーザーはドロップダウンから言語を選択でき、アプリケーションは選択された言語(英語またはアラビア語)に従って動作する必要がありました」このようにして、ユーザーは言語を選択できます。同じためにNSBundleを使用しました。お気に入り
XIBの場合
self.homeScreen = [[HomeScreen alloc] initWithNibName:@"HomeScreen" bundle:[CommonData sharedCommonData].languageBundle];
テキスト用
_lblHeading.text = [self languageSelectedStringForKey:@"ViewHeadingInfo"];
/**
This method is responsible for selecting language bundle according to user's selection.
@param: the string which is to be converted in selected language.
@return: the converted string.
@throws:
*/
-(NSString*) languageSelectedStringForKey:(NSString*) key
{
NSString* str=[[CommonData sharedCommonData].languageBundle localizedStringForKey:key value:@"" table:nil];
return str;
}