如何强制 NSLocalizedString 使用特定语言

发布于 2024-08-10 01:56:53 字数 130 浏览 8 评论 0原文

在 iPhone 上,NSLocalizedString 返回 iPhone 语言的字符串。 是否可以强制 NSLocalizedString 使用特定语言来安装应用程序 使用与设备不同的语言?

On iPhone NSLocalizedString returns the string in the language of the iPhone.
Is it possible to force NSLocalizedString to use a specific language to have the app
in a different language than the device ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(28

楠木可依 2024-08-17 01:56:53

NSLocalizedString()(及其变体)访问 NSUserDefaults 中的“AppleLanguages”键来确定用户的首选语言设置。这将返回一组语言代码,第一个是用户为其手机设置的语言代码,如果资源在首选语言中不可用,则后续的代码将用作后备。 (在桌面上,用户可以通过系统偏好设置中的自定义顺序指定多种语言)

如果您愿意,可以使用 setObject:forKey: 方法设置您自己的语言列表,从而覆盖您自己的应用程序的全局设置。这将优先于全局设置值,并返回到应用程序中执行本地化的任何代码。其代码如下所示:

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate

这将使德语成为您应用程序的首选语言,英语和法语作为后备语言。您可能希望在应用程序启动初期调用此函数。您可以在此处阅读有关语言/区域设置首选项的更多信息:国际化编程主题:获取当前语言和区域设置

NSLocalizedString() (and variants thereof) access the "AppleLanguages" key in NSUserDefaults to determine what the user's settings for preferred languages are. This returns an array of language codes, with the first one being the one set by the user for their phone, and the subsequent ones used as fallbacks if a resource is not available in the preferred language. (on the desktop, the user can specify multiple languages with a custom ordering in System Preferences)

You can override the global setting for your own application if you wish by using the setObject:forKey: method to set your own language list. This will take precedence over the globally set value and be returned to any code in your application that is performing localization. The code for this would look something like:

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate

This would make German the preferred language for your application, with English and French as fallbacks. You would want to call this sometime early in your application's startup. You can read more about language/locale preferences here: Internationalization Programming Topics: Getting the Current Language and Locale

想你的星星会说话 2024-08-17 01:56:53

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

所以基本上,当您的应用程序启动时和加载第一个控制器之前,只需call:

[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)
    }
}

I had the same problem recently and I didn't want to start and patch my entire NSLocalizedString nor force the app to restart for the new language to work. I wanted everything to work as-is.

My solution was to dynamically change the main bundle's class and load the appropriate bundle there:

Header file

@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end

Implementation

#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

So basically, when your app starts and before you load your first controller, simply call:

[NSBundle setLanguage:@"en"];

When your user changes his preferred language in your setting screen, simply call it again:

[NSBundle setLanguage:@"fr"];

To reset back to system defaults, simply pass nil:

[NSBundle setLanguage:nil];

Enjoy...

For those who need a Swift version:

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)
    }
}
沉睡月亮 2024-08-17 01:56:53

我通常以这种方式执行此操作,但您的项目中必须包含所有本地化文件。

@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

I usually do this in this way, but you MUST have all localization files in your project.

@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
江城子 2024-08-17 01:56:53

不要在 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, @""));

Do not use on iOS 9. This returns nil for all strings passed through it.

I have found another solution that allows you to update the language strings, w/o restarting the app and compatible with genstrings:

Put this macro in the Prefix.pch:

#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]

and where ever you need a localized string use:

NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")

To set the language use:

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];

Works even with consecutive language hopping like:

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, @""));
征﹌骨岁月お 2024-08-17 01:56:53

如前所述,只需执行以下操作:

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

但为了避免重新启动应用程序,请将此行放在 main.m 的 main 方法中,就在 UIApplicationMain(...) 。

As said earlier, just do:

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

But to avoid having to restart the app, put the line in the main method of main.m, just before UIApplicationMain(...).

蓝色星空 2024-08-17 01:56:53

通过从应用程序中选择特定语言来使用特定语言的技巧是强制 NSLocalizedString 根据所选语言使用特定包,

这是我为此编写的帖子
学习 iOS 应用中的高级本地化

以下是一个示例应用的代码iOS 应用中的高级本地化

The trick to use specific language by selecting it from the app is to force the NSLocalizedString to use specific bundle depending on the selected language ,

here is the post i have written for this
learning advance localization in ios apps

and here is the code of one sample app advance localization in ios apps

余生再见 2024-08-17 01:56:53

您对 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.

What do you think about this solution for 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)
    }
}

Simple usage:

"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.
征﹌骨岁月お 2024-08-17 01:56:53

正如 Brian Webster 提到的,需要“在应用程序启动的早期”设置语言。我认为 AppDelegateapplicationDidFinishLaunching: 应该是执行此操作的合适位置,因为它是我执行所有其他初始化的位置。

但正如 William Denniss 提到的,这似乎只有在应用程序重新启动后才有效,这有点无用。

不过,如果我将代码放在主函数中,它似乎工作得很好:如果

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;
}

对此有任何评论,我将不胜感激。

As Brian Webster mentions, the language needs to be set "sometime early in your application's startup". I thought applicationDidFinishLaunching: of the AppDelegate should be a suitable place to do it, since it's where I do all other initialization.

But as William Denniss mentions, that seems to have an effect only after the app is restarted, which is kind of useless.

It seems to work fine if I put the code in the main function, though:

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;
}

I'd appreciate any comments on this.

难如初 2024-08-17 01:56:53

NSLocalizedString() 从标准用户默认值 ([NSUserDefaults standardUserDefaults]) 中读取键 AppleLanguages 的值。它使用该值在运行时从所有现有本地化中选择适当的本地化。当 Apple 在应用程序启动时构建用户默认字典时,他们会在系统首选项中查找首选语言键并从那里复制值。这也解释了为什么更改 OS X 中的语言设置对正在运行的应用程序没有影响,只会影响此后启动的应用程序。复制后,该值不会仅仅因为设置更改而更新。这就是为什么如果您更改语言,iOS 会重新启动所有应用程序。

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

因此,如果您想更改语言只是为了测试,您可能不想更改您的代码(如果您稍后忘记删除此代码......),而是告诉 Xcode 使用命令行参数启动您的应用程序(例如使用西班牙语本地化):

在此处输入图像描述

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

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.

However, all values of the user defaults dictionary can be overwritten by command line arguments. See NSUserDefaults documentation on the NSArgumentDomain. This even includes those values that are loaded from the app preferences (.plist) file. This is really good to know if you want to change a value just once for testing.

So if you want to change the language just for testing, you probably don't want to alter your code (if you forget to remove this code later on ...), instead tell Xcode to start your app with a command line parameters (e.g. use Spanish localization):

enter image description here

No need to touch your code at all. Just create different schemes for different languages and you can quickly start the app once in one language and once in another one by just switching the scheme.

清音悠歌 2024-08-17 01:56:53

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

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

因此,如果您想使用标准方法(使用 NSLocalizedString),您可以在所有文件中进行快速语法替换。

I like best Mauro Delrio's method.
I also have added the following in my Project_Prefix.pch

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

So if you ever want to use the standard method (that uses NSLocalizedString) you can make a quick syntax substitution in all files.

吃不饱 2024-08-17 01:56:53

我想出了一个允许您使用 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

不仅仅是将 import NSBundle+RunTimeLanguage.h 添加到使用 NSLocalizedString 的文件中。

如您所见,我将 languageCode 存储在 AppDelegate 的属性中。这可以存储在您想要的任何地方。

我唯一不喜欢的是 NSLocalizedString marco 重新定义的警告。也许有人可以帮我修复这部分。

I came up with a solution that allows you to use NSLocalizedString. I create a category of NSBundle call NSBundle+RunTimeLanguage. The interface is like this.

// 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

The implementation is like this.

// 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

Than just add import NSBundle+RunTimeLanguage.h into the files that use NSLocalizedString.

As you can see I store my languageCode in a property of AppDelegate. This could be stored anywhere you'd like.

This only thing I don't like about it is a Warning that NSLocalizedString marco redefined. Perhaps someone could help me fix this part.

拒绝两难 2024-08-17 01:56:53

斯威夫特版本:

NSUserDefaults.standardUserDefaults().setObject(["fr"], forKey: "AppleLanguages")
NSUserDefaults.standardUserDefaults().synchronize()

Swift Version:

NSUserDefaults.standardUserDefaults().setObject(["fr"], forKey: "AppleLanguages")
NSUserDefaults.standardUserDefaults().synchronize()
如若梦似彩虹 2024-08-17 01:56:53

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

Swift 3 extensions:

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
    }
}

Usage:

Locale.preferredLanguage = "uk"

label.text = "localizedKey".localized
玩世 2024-08-17 01:56:53

在 swift 4 中,我已经解决了这个问题,无需重新启动或使用库。

尝试了很多选项后,我找到了这个函数,您可以在其中传递要翻译的 stringToLocalize(Localized.String,字符串文件)、要翻译的语言以及它返回的内容是 Strings 文件中该字符串的值:

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!)!
    }
}

要从整个应用程序以及其余 ViewController 的每个字符串中访问,而不是输入:

NSLocalizedString ("StringToLocalize", comment: “")

I已将其替换为

let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()

NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: “”) //use in each String

我不知道这是否是最好的方法,但我发现它非常简单,并且对我有用,希望对您有帮助!

In swift 4, I have solved it without needing to restart or use libraries.

After trying many options, I found this function, where you pass the stringToLocalize (of Localizable.String, the strings file) that you want to translate, and the language in which you want to translate it, and what it returns is the value for that String that you have in Strings file:

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)
}

Taking into account this function, I created this function in a Swift file:

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!)!
    }
}

To access from the whole app, and in each string of the rest of ViewControllers, instead of putting:

NSLocalizedString ("StringToLocalize", comment: “")

I have replaced it with

let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()

NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: “”) //use in each String

I do not know if it's the best way, but I found it very simple, and it works for me, I hope it helps you!

痴骨ら 2024-08-17 01:56:53

简而言之:

本地化您的应用程序

您要做的第一件事就是使用至少两种语言(本例中为英语和法语)本地化您的应用程序。

覆盖 NSLocalizedString

在您的代码中,不要使用 NSLocalizedString(key, comment),而是使用如下定义的宏 MYLocalizedString(key, comment)
#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];

MYLocalizationSystem 单例将:

  • 通过设置正确的语言来设置语言本地化的 NSBundle 用户要求
  • 根据先前设置的语言返回本地化的 NSString

设置用户语言

当用户将应用程序语言更改为法语时,调用 [[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

In a nutshell :

Localize your application

It's the first thing you have to do is to localise your app with at least two languages (english and french in this example).

Override NSLocalizedString

In your code, instead of using NSLocalizedString(key, comment), use a macro MYLocalizedString(key, comment) defined like this :
#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];

This MYLocalizationSystem singleton will :

  • Set langage by setting the right localized NSBundle user asks for
  • Returns the localized NSString according to this previously set language

Set user language

When user changed application language in french, call [[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];
}

In this example this method set localized bundle to fr.lproj

Return localized string

Once you've set the localized bundle, you'll be able to get the right localised string from him with this method :

- (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];
}

Hope this will help you.

You'll find more details in this article from NSWinery.io

成熟的代价 2024-08-17 01:56:53

在文件.pch中定义:

#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]


#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")

In file .pch to define:

#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]


#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")
街角卖回忆 2024-08-17 01:56:53

也许你应该补充这个(在 #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]

Maybe you should complement with this (on .pch file after #import ):

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]
倾城°AllureLove 2024-08-17 01:56:53

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

给出了一些可以使用的语言代码的示例。希望这有帮助

Swift 3 solution:

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

Gave some examples of language codes that can be used. Hope this helps

瀞厅☆埖开 2024-08-17 01:56:53

您可以使用要执行此操作的一组本地化字符串构建一个子包,然后使用 NSLocalizedStringFromTableInBundle() 加载它们。 (我假设这是与您可能在应用程序上执行的正常 UI 本地化分开的内容。)

You could build a sub-bundle with the set of localized strings that you want to do this with, and then use NSLocalizedStringFromTableInBundle() to load them. (I'm assuming that this is content separate from the normal UI localization you might be doing on the app.)

所谓喜欢 2024-08-17 01:56:53

对于我的情况,我有两个本地化文件,ja和en

,如果系统中的首选语言既不是en也不是ja,我想强制它为en,

我将编辑main.m文件,

我将检查第一个是否首选是 en 或 ja ,如果不是,那么我会将第二首选语言更改为 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]));


    }


}

for my case i have two localized file , ja and en

and i would like to force it to en if the preferred language in the system neither en or ja

i'm going to edit the main.m file

i 'll check whether the first preferred is en or ja , if not then i 'll change the second preferred language to 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]));


    }


}
星光不落少年眉 2024-08-17 01:56:53

你可以这样做:

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];


NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];

NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):

You can do something like this:

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];


NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];

NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):
满栀 2024-08-17 01:56:53

这是解决此问题的一个不错的解决方案,并且不需要重新启动应用程序。

https://github.com/cmaftuleac/BundleLocalization

此实现通过在 NSBundle 内部进行调整来实现。这个想法是,您在 NSBundle 对象的实例上重写 localizedStringForKey 方法,然后在使用不同语言的不同包上调用此方法。简洁大方,完全兼容各类资源。

Here is a decent solution for this problem, and it does not require application restart.

https://github.com/cmaftuleac/BundleLocalization

This implementation works by tweaking inside NSBundle. The idea is that you override the method localizedStringForKey on the instance of NSBundle object, and then call this method on a different bundle with a different language. Simple and elegant fully compatible with all types of resources.

三岁铭 2024-08-17 01:56:53

基于 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"];

Based on Tudorizer's answer to change language without leaving or restarting the application.

Instead of a macro, use a class for accessing the preferred language in order to check if a specific language code is present.

Below is a class used to obtain the current language bundle that is working for 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

Use the class above to reference a string file / image / video / etc:

// 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")

Change language in-line like below or update the "changeCurrentLanguage" method in the class above to take a string parameter referencing the new language.

[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
盗心人 2024-08-17 01:56:53

此函数将尝试获取当前语言的本地化字符串,如果未找到,它将使用英语获取它。

- (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;
}

This function will try to get localized string for current language and if it's not found it will get it using english language.

- (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;
}
秉烛思 2024-08-17 01:56:53

我想添加对 iOS 未正式支持的语言的支持(未在系统设置下的语言部分列出)。按照 Apple 的国际化教程 以及 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 代码都很有效。该代码假设用户稍后可以选择手动更改应用程序内的语言。

当然,不要忘记添加正确的 Storyboard 翻译和 Localized.strings 翻译(有关如何执行此操作的信息,请参阅上面的 Apple 页面链接)。

I wanted to add support for a language that isn't officially supported by iOS (not listed in Language section under system settings). By following the Apple's Internationalization Tutorial and few hints here by Brian Webster and geon, I came up with this piece of code (put it in 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]));
    }
}

This works well for both Storyboard and NSLocalizedString code. The code assumes that user will have an option to manually change language inside app later on.

Of course, don't forget to add proper Storyboard translations and Localizable.strings translations (see link to Apple page above for how to do that).

夕色琉璃 2024-08-17 01:56:53

对于 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))

与删除 AppDelegate.swift 文件中的 @UIApplicationMain 配合使用。

For Swift you can override the main.swift file and set the UserDefaults string there before you app runs. This way you do not have to restart the App to see the desired effect.

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))

paired together with the removal of @UIApplicationMain in your AppDelegate.swift file.

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

由于我们使用 en_GB 和 en_BZ,iOS 总是首选 en_GB。即使如此,当我将设备语言切换为 EN、将区域切换为 BZ 以及在测试计划 应用程序语言应用程序区域 设置中设置这些值时。除了上面的旧参数方法之外,没有任何帮助:)

在此处输入图像描述

For me, Test-Plan user, specifying -AppleLanguages (en_BZ) (English Belize) in the TestPlan's Arguments Passed On Launch is working.

Since we use en_GB and en_BZ, iOS always preferred en_GB. Even so when I switched the devices language to EN and the region to BZ and when setting these values in the Test Plans Application Language and Application Region settings . Nothing helped except the good old arguments approach above :)

enter image description here

没︽人懂的悲伤 2024-08-17 01:56:53

无论你们做什么,最好的方法是获取指定语言的短名称,即:fr、en、nl、de、it 等...并将其分配给全局值。

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

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

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

没有违反规则。

whatever you all do, the best way is to take the short_name for the specified language, i.e.: fr, en, nl, de, it, etc... and assign the same to a global value.

make a picker view to pop up like a drop down menu (combination of a button on click of which a picker view appears from below with a list of languages) and select the language you desire. let the short name be stored internally.
make a .h + .m file named LocalisedString.

Set the global value of short_name to be equal to the obtained value in LocalisedString.m
When the required language is selected assign the NSBundlePath to create project sub-directories for the needed language. for eg, nl.proj, en.proj.

When the particular proj folder is selected call the localised string for the respective language and change the language dynamically.

no rules broken.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文