在iPhone上NSLocalizedString返回iPhone语言的字符串。 是否有可能强制NSLocalizedString使用特定语言来拥有应用程序 用不同的语言吗?


当前回答

对我来说,测试计划用户,在测试计划的参数中指定- applellanguages (en_BZ)(英语伯利兹语)在启动时传递是有效的。

因为我们使用en_GB和en_BZ, iOS总是首选en_GB。即便如此,当我将设备语言切换到EN,区域切换到BZ,以及在测试计划应用程序语言和应用程序区域设置中设置这些值时。除了上面的老方法,什么都没用:)

其他回答

我想添加对iOS官方不支持的语言的支持(未在系统设置下的语言部分列出)。通过遵循苹果的国际化教程和Brian Webster和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]));
    }
}

这适用于Storyboard和NSLocalizedString代码。该代码假设用户将有一个选项,手动更改应用程序内的语言稍后。

当然,不要忘记添加适当的故事板翻译和本地化。字符串翻译(见链接到上面的苹果页面如何做到这一点)。

我想出了一个解决方案,允许你使用NSLocalizedString。我创建了一个名为NSBundle+ runtimellanguage的NSBundle类别。界面是这样的。

// 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马可重新定义。也许有人能帮我修好这部分。

我最近也遇到了同样的问题,我不想启动和修补我的整个NSLocalizedString,也不想强迫应用程序重新启动新的语言工作。我希望一切都能按原样工作。

我的解决方案是动态地改变主bundle的类,并在那里加载适当的bundle:

头文件

@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

我最喜欢Mauro Delrio的方法。 我还在我的Project_Prefix.pch中添加了以下内容

#import "Language.h"    
#define MyLocalizedString(key, alt) [Language get:key alter:alt]

如果你想使用标准方法(使用NSLocalizedString)你可以在所有文件中做一个快速的语法替换。