iPhone NSLocalizedString
では、文字列をiPhone の言語で返します。NSLocalizedString
特定の言語を使用して、デバイスとは異なる言語でアプリを強制することは可能ですか?
iPhone NSLocalizedString
では、文字列をiPhone の言語で返します。NSLocalizedString
特定の言語を使用して、デバイスとは異なる言語でアプリを強制することは可能ですか?
回答:
NSLocalizedString()
(およびそのバリアント)で「AppleLanguages」キーにアクセスして、NSUserDefaults
優先言語のユーザー設定を確認します。これは、言語コードの配列を返します。最初のコードはユーザーが自分の電話用に設定したものであり、リソースが優先言語で使用できない場合、後続のコードはフォールバックとして使用されます。(デスクトップでは、ユーザーはシステム環境設定でカスタム注文で複数の言語を指定できます)
必要に応じて、setObject:forKey:メソッドを使用して独自の言語リストを設定することにより、独自のアプリケーションのグローバル設定をオーバーライドできます。これは、グローバルに設定された値よりも優先され、ローカライズを実行しているアプリケーションのコードに返されます。このためのコードは次のようになります。
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate
これにより、ドイツ語がアプリケーションの優先言語になり、英語とフランス語がフォールバックになります。アプリケーションの起動の早い段階でこれを呼び出す必要があります。言語/ロケールの設定について詳しくは、こちらをご覧ください:国際化プログラミングトピック:現在の言語とロケールの取得
最近同じ問題が発生し、NSLocalizedString全体を開始してパッチを適用したくありませんでしたたり、アプリを強制的に再起動して新しい言語を機能。私はすべてが現状のままで機能することを望んでいました。
私の解決策は、メインバンドルのクラスを動的に変更し、適切なバンドルをそこにロードすることでした。
ヘッダーファイル
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end
実装
#import <objc/runtime.h>
static const char _bundle=0;
@interface BundleEx : NSBundle
@end
@implementation BundleEx
-(NSString*)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
NSBundle* bundle=objc_getAssociatedObject(self, &_bundle);
return bundle ? [bundle localizedStringForKey:key value:value table:tableName] : [super localizedStringForKey:key value:value table:tableName];
}
@end
@implementation NSBundle (Language)
+(void)setLanguage:(NSString*)language
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
object_setClass([NSBundle mainBundle],[BundleEx class]);
});
objc_setAssociatedObject([NSBundle mainBundle], &_bundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
したがって、基本的に、アプリが起動したとき、最初のコントローラーをロードする前に、次のコードを呼び出すだけです。
[NSBundle setLanguage:@"en"];
ユーザーが設定画面で優先言語を変更した場合は、もう一度呼び出すだけです。
[NSBundle setLanguage:@"fr"];
システムのデフォルトにリセットするには、nilを渡すだけです。
[NSBundle setLanguage:nil];
楽しい...
Swiftバージョンが必要な場合:
var bundleKey: UInt8 = 0
class AnyLanguageBundle: Bundle {
override func localizedString(forKey key: String,
value: String?,
table tableName: String?) -> String {
guard let path = objc_getAssociatedObject(self, &bundleKey) as? String,
let bundle = Bundle(path: path) else {
return super.localizedString(forKey: key, value: value, table: tableName)
}
return bundle.localizedString(forKey: key, value: value, table: tableName)
}
}
extension Bundle {
class func setLanguage(_ language: String) {
defer {
object_setClass(Bundle.main, AnyLanguageBundle.self)
}
objc_setAssociatedObject(Bundle.main, &bundleKey, Bundle.main.path(forResource: language, ofType: "lproj"), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
私は通常、この方法でこれを行いますが、プロジェクトにはすべてのローカリゼーションファイルが必要です。
@implementation Language
static NSBundle *bundle = nil;
+(void)initialize
{
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:@"AppleLanguages"];
NSString *current = [[languages objectAtIndex:0] retain];
[self setLanguage:current];
}
/*
example calls:
[Language setLanguage:@"it"];
[Language setLanguage:@"de"];
*/
+(void)setLanguage:(NSString *)l
{
NSLog(@"preferredLang: %@", l);
NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];
bundle = [[NSBundle bundleWithPath:path] retain];
}
+(NSString *)get:(NSString *)key alter:(NSString *)alternate
{
return [bundle localizedStringForKey:key value:alternate table:nil];
}
@end
iOS 9では使用しないでください。これは、渡されたすべての文字列に対してnilを返します。
アプリを再起動せずにgenstringsと互換性のある言語文字列を更新できる別のソリューションを見つけました。
このマクロをPrefix.pchに配置します。
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
ローカライズされた文字列の使用が必要な場合:
NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")
言語の使用を設定するには:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
次のような連続した言語ホッピングでも機能します:
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"fr"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"it"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
前に述べたように、次のようにします。
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];
ただし、アプリを再起動する必要がないように、その行をのメインメソッドのmain.m
直前UIApplicationMain
(...)に配置します。
NSAutoreleasePool * pool ..
、自動解放されたオブジェクトがリークした後にその行を挿入する必要があります。
[[NSBundle mainBundle] URLForResource:withExtension:]
以前に電話をかけた場合、これは機能しません。
アプリから選択して特定の言語を使用するコツは、 NSLocalizedString
、選択した言語に応じて特定のバンドルを使用することことです。
これは私がiOSアプリでこのローカリゼーションのローカリゼーションを学ぶために書いた投稿 です
そして、これはiOSアプリでの1つのサンプルアプリ事前ローカリゼーションのコードです
Swift 3のこのソリューションについてどう思いますか?
extension String {
func localized(forLanguage language: String = Locale.preferredLanguages.first!.components(separatedBy: "-").first!) -> String {
guard let path = Bundle.main.path(forResource: language == "en" ? "Base" : language, ofType: "lproj") else {
let basePath = Bundle.main.path(forResource: "Base", ofType: "lproj")!
return Bundle(path: basePath)!.localizedString(forKey: self, value: "", table: nil)
}
return Bundle(path: path)!.localizedString(forKey: self, value: "", table: nil)
}
}
簡単な使い方:
"report".localized(forLanguage: "pl") //forced language
"report".localized() //default language selected by user in settings, in case when your app doesnt support selected lanaguage, the default one is selected, here is an english.
Brian Websterが述べているように、言語は「アプリケーションの起動の早い時期」に設定する必要があります。私は考えましapplicationDidFinishLaunching:
たAppDelegate
、私は他のすべての初期化を行う場所、それはだから、それを行うために適した場所でなければなりません。
しかし、William Dennissが言及しているように、それはアプリが再起動された後にのみ効果があるようで、それは一種の役に立たないです。
ただし、コードをmain関数に配置すると問題なく動作するようです。
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Force language to Swedish.
[[NSUserDefaults standardUserDefaults]
setObject:[NSArray arrayWithObject:@"sv"]
forKey:@"AppleLanguages"];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
これについてのコメントをいただければ幸いです。
[[NSUserDefaults standardUserDefaults] synchronize];
電話をかけてから使用してくださいsetObject:forKey:
私はマウロデルリオの方法が一番好きです。Project_Prefix.pchにも以下を追加しました
#import "Language.h"
#define MyLocalizedString(key, alt) [Language get:key alter:alt]
したがって、(NSLocalizedStringを使用する)標準メソッドを使用したい場合は、すべてのファイルで簡単な構文置換を行うことができます。
NSLocalizedString()
キーの値をAppleLanguages
標準ユーザーのデフォルト([NSUserDefaults standardUserDefaults]
)から読み取ります。この値を使用して、実行時にすべての既存のローカリゼーションの中から適切なローカリゼーションを選択します。Appleがアプリの起動時にユーザーデフォルト辞書を作成するとき、システム設定で優先言語キーを検索し、そこから値をコピーします。これは、たとえば、OS Xで言語設定を変更しても、実行中のアプリに影響を与えず、その後起動したアプリにのみ影響する理由も説明します。一度コピーすると、設定が変更されただけでは値は更新されません。そのため、言語を変更すると、iOSがすべてのアプリを再起動します。
ただし、ユーザーデフォルト辞書のすべての値は、コマンドライン引数で上書きできます。のNSUserDefaults
ドキュメントを参照してくださいNSArgumentDomain
。これには、アプリの設定(.plist)ファイルから読み込まれた値も含まれます。これは本当に知っておくと良いです、テストのために一度だけ値を変更したいどうかのにです。
したがって、テストのためだけに言語を変更したい場合は、おそらくコードを変更したくないでしょう(後でこのコードを削除するのを忘れた場合...)代わりに、Xcodeにコマンドラインパラメーター(例:スペイン語のローカリゼーションを使用):
コードに触れる必要はまったくありません。言語ごとに異なるスキームを作成するだけで、スキームを切り替えるだけで、ある言語でアプリをすばやく起動し、別の言語でアプリをすばやく起動できます。
Options
Appleが提供する新しいXcodeバージョンと同様に、言語を上書きしないようにしてください。同じように。
私はあなたが使用できるようにするソリューションを思いつきましたNSLocalizedString
。NSBundle
通話のカテゴリを作成しますNSBundle+RunTimeLanguage
。インターフェースはこんな感じ。
// NSBundle+RunTimeLanguage.h
#import <Foundation/Foundation.h>
@interface NSBundle (RunTimeLanguage)
#define NSLocalizedString(key, comment) [[NSBundle mainBundle] runTimeLocalizedStringForKey:(key) value:@"" table:nil]
- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName;
@end
実装はこんな感じです。
// NSBundle+RunTimeLanguage.m
#import "NSBundle+RunTimeLanguage.h"
#import "AppDelegate.h"
@implementation NSBundle (RunTimeLanguage)
- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSString *path= [[NSBundle mainBundle] pathForResource:[appDelegate languageCode] ofType:@"lproj"];
NSBundle *languageBundle = [NSBundle bundleWithPath:path];
NSString *localizedString=[languageBundle localizedStringForKey:key value:key table:nil];
return localizedString;
}
@end
NSBundle+RunTimeLanguage.h
使用するファイルにインポートを追加するだけではありませんNSLocalizedString
。
ご覧のとおり、languageCodeをのプロパティに格納していますAppDelegate
。これは、好きな場所に保存できます。
これについて私が気に入らないのは、NSLocalizedString
マルコが再定義した警告だけです。おそらく、誰かがこの部分の修正を手伝ってくれるでしょう。
#undef NSLocalizedString
直前に追加#define
最初に行う必要があるのは、少なくとも2つの言語(この例では英語とフランス語)でアプリをローカライズすることです。
コードではNSLocalizedString(key, comment)
、を使用する代わりに、マクロを使用しますMYLocalizedString(key, comment)
次のように定義され。
#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];
このMYLocalizationSystem
シングルトンは:
ユーザーがフランス語でアプリケーションの言語を変更した場合は、 [[MYLocalizationSystem sharedInstance] setLanguage:@"fr"];
- (void)setLanguage:(NSString *)lang
{
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj"];
if (!path)
{
_bundle = [NSBundle mainBundle];
NSLog(@"Warning: No lproj for %@, system default set instead !", lang);
return;
}
_bundle = [NSBundle bundleWithPath:path];
}
この例では このメソッドはローカライズされたバンドルをfr.lprojに設定します
ローカライズされたバンドルを設定すると、次のメソッドを使用して、ローカライズされた正しい文字列を彼から取得できるようになります。
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value
{
// bundle was initialized with [NSBundle mainBundle] as default and modified in setLanguage method
return [self.bundle localizedStringForKey:key value:value table:nil];
}
これがお役に立てば幸いです。
詳細については、NSWinery.ioのこの記事をご覧ください。
Swift 3拡張:
extension Locale {
static var preferredLanguage: String {
get {
return self.preferredLanguages.first ?? "en"
}
set {
UserDefaults.standard.set([newValue], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
}
}
}
extension String {
var localized: String {
var result: String
let languageCode = Locale.preferredLanguage //en-US
var path = Bundle.main.path(forResource: languageCode, ofType: "lproj")
if path == nil, let hyphenRange = languageCode.range(of: "-") {
let languageCodeShort = languageCode.substring(to: hyphenRange.lowerBound) // en
path = Bundle.main.path(forResource: languageCodeShort, ofType: "lproj")
}
if let path = path, let locBundle = Bundle(path: path) {
result = locBundle.localizedString(forKey: self, value: nil, table: nil)
} else {
result = NSLocalizedString(self, comment: "")
}
return result
}
}
使用法:
Locale.preferredLanguage = "uk"
label.text = "localizedKey".localized
定義するファイル.pch内:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")
多分これで補完する必要があります(#importの後の.pchファイルで):
extern NSBundle* bundle; // Declared on Language.m
#ifdef NSLocalizedString
#undef NSLocalizedString
// Delete this line to avoid warning
#warning "Undefining NSLocalizedString"
#endif
#define NSLocalizedString(key, comment) \
[bundle localizedStringForKey:(key) value:@"" table:nil]
Swift 3ソリューション:
let languages = ["bs", "zh-Hant", "en", "fi", "ko", "lv", "ms", "pl", "pt-BR", "ru", "sr-Latn", "sk", "es", "tr"]
UserDefaults.standard.set([languages[0]], forKey: "AppleLanguages")
使用できる言語コードの例をいくつか示しました。お役に立てれば
これを実行するローカライズされた文字列のセットでサブバンドルを作成し、それを使用NSLocalizedStringFromTableInBundle()
してそれらをロードすることができます。(これは、アプリで行う可能性のある通常のUIローカリゼーションとは別のコンテンツであると想定しています。)
私の場合、私は2つのローカライズされたファイル、jaとenを持っています
システムの優先言語がenでもjaでもない場合は、強制的にenにしたい
main.mファイルを編集します
最初の優先言語がenかjaかを確認し、そうでない場合は2番目の優先言語をenに変更します。
int main(int argc, char *argv[])
{
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSString *lang = [[NSLocale preferredLanguages] objectAtIndex:0];
if (![lang isEqualToString:@"en"] && ![lang isEqualToString:@"ja"]){
NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[NSLocale preferredLanguages]];
[array replaceObjectAtIndex:1 withObject:@"en"];
[[NSUserDefaults standardUserDefaults] setObject:array forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
あなたはこのようなことをすることができます:
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];
NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):
アプリケーションを終了したり再起動したりせずに言語を変更するというTudorizerの回答に基づいています。
マクロの代わりに、特定の言語コードが存在するかどうかを確認するために、優先言語にアクセスするためのクラスを使用します。
以下は、iOS 9で動作する現在の言語バンドルを取得するために使用されるクラスです。
@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」メソッドを更新して、新しい言語を参照する文字列パラメーターを取得します。
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
Swift 4では、ライブラリを再起動したり、ライブラリを使用したりすることなく解決しました。
多くのオプションを試した後、私はこの関数を見つけました、そこでは翻訳したい(Localizable.Stringの文字列ファイルの)stringToLocalizeと、あなたがそれを翻訳したい言語を渡します、そしてそれが返すものはStringsファイルにあるそのString:
func localizeString (stringToLocalize: String, language: String) -> String
{
let path = Bundle.main.path (forResource: language, ofType: "lproj")
let languageBundle = Bundle (path: path!)
return languageBundle! .localizedString (forKey: stringToLocalize, value: "", table: nil)
}
この関数を考慮して、この関数をSwiftファイルに作成しました。
struct CustomLanguage {
func createBundlePath () -> Bundle {
let selectedLanguage = //recover the language chosen by the user (in my case, from UserDefaults)
let path = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj")
return Bundle(path: path!)!
}
}
アプリ全体から、および残りのViewControllersの各文字列からアクセスするには、次のように配置するのではなく、
NSLocalizedString ("StringToLocalize", comment: “")
に置き換えました
let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()
NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: “”) //use in each String
それが最善の方法であるかどうかはわかりませんが、非常にシンプルであることがわかりました。それでうまくいきます。
この関数は、現在の言語にローカライズされた文字列を取得しようとし、見つからない場合は英語を使用して取得します。
- (NSString*)L:(NSString*)key
{
static NSString* valueNotFound = @"VALUE_NOT_FOUND";
static NSBundle* enBundle = nil;
NSString* pl = [NSLocale preferredLanguages][0];
NSString* bp = [[NSBundle mainBundle] pathForResource:pl ofType:@"lproj"];
NSBundle* b = [NSBundle bundleWithPath:bp];
NSString* s = [b localizedStringForKey:key value:valueNotFound table:nil];
if ( [s isEqualToString:valueNotFound] ) {
if ( !enBundle ) {
bp = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
enBundle = [NSBundle bundleWithPath:bp];
}
s = [enBundle localizedStringForKey:key value:key table:nil];
}
return s;
}
iOSで公式にサポートされていない言語のサポートを追加したかった(システム設定の[言語]セクションにリストされていない)。Appleの国際化チュートリアルと、ブライアンウェブスターとgeonによるいくつかのヒントに従って、次のコードを思いつきました(main.mに入れてください)。
int main(int argc, char * argv[]) {
@autoreleasepool {
// Grab regional settings locale, for Slovenian this is either sl_SI or en_SI
NSLocale *locale = [NSLocale currentLocale];
NSString *ll = [locale localeIdentifier]; // sl_SI
// Grab the first part of language identifier
NSArray *comp = [ll componentsSeparatedByString:@"_"];
NSString *ll1 = @"en";
if (comp.count > 0) {
ll1 = comp[0]; // sl, en, ...
}
// Check if we already saved language (user can manually change it inside app for example)
if (![[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"]) {
// Slovenian (Slovenia), Slovenia
if ([ll isEqualToString:@"sl_SI"] || [ll isEqualToString:@"en_SI"]) {
ll1 = @"sl-SI"; // This is the part of localized path for Slovenian language that Xcode generates
}
// Add more unsupported languages here...
[[NSUserDefaults standardUserDefaults] setObject:ll1 forKey:@"SelectedLanguage"]; // Save language
}
else {
// Restore language as we have previously saved it
ll1 = [[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"];
}
// Overwrite NSLocalizedString and StoryBoard language preference
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:ll1, @"en", @"fr", nil] forKey:@"AppleLanguages"];
// Make sure settings are stored to disk
[[NSUserDefaults standardUserDefaults] synchronize];
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
これは、ストーリーボードとNSLocalizedStringコードの両方でうまく機能します。コードは、ユーザーが後でアプリ内の言語を手動で変更するオプションがあることを前提としています。
もちろん、適切なStoryboard翻訳とLocalizable.strings翻訳を追加することを忘れないでください(その方法については、上のAppleページへのリンクを参照してください)。
この問題の適切な解決策を次に示します。アプリケーションを再起動する必要はありません。
https://github.com/cmaftuleac/BundleLocalization
この実装は、NSBundle内を調整することで機能します。考え方は、NSBundleオブジェクトのインスタンスでメソッドlocalizedForForKeyをオーバーライドしてから、このメソッドを別の言語の別のバンドルで呼び出すというものです。シンプルでエレガント、あらゆるタイプのリソースと完全に互換性があります。
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj" ];
何をするにせよ、最善の方法は、指定された言語のshort_nameを取得することです。つまり、fr、en、nl、de、itなどです。これをグローバル値に割り当てます。
ドロップダウンメニューのようにポップアップするピッカービューを作成し(クリックすると、ピッカービューが下から言語のリストとともに表示されるボタンの組み合わせ)、目的の言語を選択します。短縮名を内部に保存します。LocalisedStringという名前の.h + .mファイルを作成します。
short_nameのグローバル値をLocalisedString.mで取得した値と等しくなるように設定します。必要な言語が選択されたら、NSBundlePathを割り当てて、必要な言語のプロジェクトサブディレクトリを作成します。たとえば、nl.proj、en.proj。
特定のprojフォルダーを選択すると、それぞれの言語にローカライズされた文字列が呼び出され、言語が動的に変更されます。
ルール違反はありません。
Swiftの場合は、main.swift
アプリを実行する前に、ファイルを上書きしてUserDefaults文字列を設定できます。この方法では、目的の効果を確認するためにアプリを再起動する必要はありません。
import Foundation
import UIKit
// Your initialisation code here
let langCultureCode: String = "LANGUAGE_CODE"
UserDefaults.standard.set([langCultureCode], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
ファイル@UIApplicationMain
内のの削除とペアになっていAppDelegate.swift
ます。