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


当前回答

根据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")

像下面这样inline更改language或更新上面类中的"changeCurrentLanguage"方法,以获取引用新语言的字符串参数。

[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];

其他回答

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

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

NSLocalizedString() reads the value for the key AppleLanguages from the standard user defaults ([NSUserDefaults standardUserDefaults]). It uses that value to choose an appropriate localization among all existing localizations at runtime. When Apple builds the user defaults dictionary at app launch, they look up the preferred language(s) key in the system preferences and copy the value from there. This also explains for example why changing the language settings in OS X has no effect on running apps, only on apps started thereafter. Once copied, the value is not updated just because the settings change. That's why iOS restarts all apps if you change then language.

但是,用户默认字典的所有值都可以被命令行参数覆盖。请参阅NSArgumentDomain上的NSUserDefaults文档。这甚至包括那些从应用程序首选项(.plist)文件加载的值。如果您只是为了测试而更改一个值,了解这一点非常有用。

所以如果你想改变语言只是为了测试,你可能不想改变你的代码(如果你忘记删除这段代码…),而是告诉Xcode用一个命令行参数启动你的应用程序(例如使用西班牙语本地化):

根本不需要修改代码。只需为不同的语言创建不同的方案,您可以快速启动应用程序一次在一种语言和一次在另一种只需切换方案。

正如Brian Webster提到的,语言需要在“应用程序启动初期的某个时候”设置。我认为AppDelegate的applicationDidFinishLaunching:应该是一个合适的地方来做它,因为它是我做所有其他初始化的地方。

但正如威廉·丹尼斯提到的,这似乎只有在应用程序重新启动后才会起作用,这有点没用。

不过,如果我把代码放在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;
}

如果有任何评论,我将不胜感激。

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

如前所述,只要做:

[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];

但是为了避免不得不重新启动应用程序,请将该行放在main的main方法中。m,就在UIApplicationMain(…)之前。