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


当前回答

我通常这样做,但你必须有所有的本地化文件在你的项目。

@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

其他回答

我最近也遇到了同样的问题,我不想启动和修补我的整个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)
    }
}

你觉得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.

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

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

无论你做什么,最好的方法是获取指定语言的short_name,即:fr, en, nl, de, it,等等…并将其赋值为全局值。

使选择器视图像下拉菜单一样弹出(单击一个按钮,选择器视图从下面出现一个语言列表),并选择您想要的语言。让短名称存储在内部。 创建一个名为LocalisedString的.h + .m文件。

将short_name的全局值设置为LocalisedString.m中获取的值 当选择所需的语言时,分配NSBundlePath为所需的语言创建项目子目录。例如,nl。项目,en.proj。

当选择特定的proj文件夹时,调用相应语言的本地化字符串并动态更改语言。

没有违反规则。

你可以用你想要做这件事的本地化字符串集构建一个子bundle,然后使用NSLocalizedStringFromTableInBundle()来加载它们。(我假设这是与你可能在应用上做的正常UI本地化分开的内容。)