在iPhone上,NSLocalizedString以iPhone的语言返回字符串。
是否可以强制NSLocalizedString使用特定的语言来使应用
与设备使用其他语言? />

评论

请参考:stackoverflow.com/a/48187049/6665075像护身符一样工作

#1 楼

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

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

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


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

评论


这对我不起作用,无论如何,它将使用默认语言。

– Quno
2010-2-22在17:41

丹尼斯如果在启动应用程序之前设置语言首选项,效果会更好。我在调用UIApplicationMain()之前在main()函数中进行此操作。一旦实际运行,它就不会更改使用的语言,而只需设置下一次的首选项。

– Geon
2010年9月1日于21:44

您必须在初始化UIKit之前设置语言,并且必须指定完整的语言+区域语言环境-查阅完整的示例blog.federicomestrone.com/2010/09/15/…

–fedmest
2011年4月21日在9:16

设置AppleLanguages将在运行时更改语言(如果在main()中完成)-是的!但是...首次安装该应用程序后,将在调用UIApplicationMain()之后初始化nsuserdefaults,这将忽略先前设置的AppleLanguages,并且需要强制强制重新启动该应用程序才能查看所需的语言。

– JohnPayne
2013年9月9日在1:02



这不适用于Localizable.stringsdict中定义的多个项目。知道是否有可能的解决方法吗?

– Mihai Fratu
2015年12月8日23:37

#2 楼

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


评论


嗨@Wirsing,到目前为止,这对我来说非常有用。我什至已经将一个应用程序上载到了商店,Apple也没有抱怨。

–吉拉德·诺维克(Gilad Novik)
2014-03-25 18:04



这是一个很棒的解决方案,我在这里也引用了此:medium.com/ios-apprentice/905e4052b9de

–詹姆士·唐(James Tang)
2014年5月6日晚上8:34

@JamesTang,您好:感谢您提供参考和您的帖子-我在那里找到了许多有关本地化的有用信息。

–吉拉德·诺维克(Gilad Novik)
2014年5月7日下午3:55

@Gilad您的方法非常适合动态字符串(我在localizable.strings中定义的字符串),但对于情节提要按钮和标签,它仅适用于主要方法。所以您可以扩展您的答案以包括UI控件本地化吗?我的意思是我调用[NSBundle setLanguage:@“ ??”];之后如何刷新(不关闭)故事板?

–贾瓦德·谢赫(Jawad Al Shaikh)
14年5月14日在9:09

至于XIB /故事板:您需要确保在加载视图之前调用此方法。就实时更新视图而言:就我而言,我只是重新加载了视图控制器(将其放在导航控制器中,只是更换了控制器。重新加载后-它获得了新的翻译字符串)。我正在为此设计一个cocoapod,我可能还会在其中添加一个示例。敬请关注...

–吉拉德·诺维克(Gilad Novik)
14年5月14日在21:42

#3 楼

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

@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


评论


+1。这是一个非常不错的技巧,我在其他任何地方都没有看到过。通过从一个本地化文件夹中创建一个“子捆绑包”,只要将NSLocalizedString包装在此处绕行的东西,就可以使字符串工作正常。

–本·佐托(Ben Zotto)
2010-6-28在15:44

优秀的毛罗。我注意到它也可以用于项目外的文件。如果出于某种原因(例如我的情况),您需要从网络下载字符串文件,并将它们存储在“文档”目录中(文件夹结构为Documents / en.lproj / Localizable.strings,Documents / fr.lproj / Localizable.strings,...)。您甚至可以制作一个NSBundle。只需对路径使用此代码:NSString * path = [NSHomeDirectory()stringByAppendingPathComponent:[NSString stringWithFormat:@“ / Documents /%@。lproj”,l,nil]];

– arnaud del。
2012年2月6日在21:13



在我看来,这是最好的方法,下面还有亚历山德罗的贡献。它不是那么麻烦,不需要重新启动。

– PKCLsoft
2012年2月29日,下午3:37

我究竟做错了什么?我做了一个Language类,继承了NSObject,将其放在实现中,将方法名称放在.h中,然后放入[Language setLanguage:@“ es”];在我的“更改语言”按钮中,代码运行(调用了按钮方法,并转到“语言”类),但没有执行任何操作。我也设置了localizable.strings(西班牙语)。但这似乎对许多其他人都起作用。请有人为我哑巴。

– SirRupertIII
2012年11月19日23:37

@KKendall您这样称呼它:[Language setLanguage:@“ es”]; NSString * stringToUse = [语言获取:@“您的文本” alter:nil];

– Mikrasya
2013年9月28日19:08



#4 楼

不要在iOS 9上使用。这会为通过它的所有字符串返回nil。

将此宏放在Prefix.pch中: />
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]


设置语言请使用:
NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")


评论


@ powerj1984:不,它将仅更改源文件中的字符串。如果要更改xib语言,则必须从所选语言包中手动重新加载xib。

– gklka
2014年1月23日在21:57

@gklka我已经按照了Tudozier给出的步骤,但是我的XIB并没有改变语言,正如您手动告诉重新加载XIB那样,重新加载XIB实际上意味着什么?

– Dk Kumar
14年2月22日在8:55

@DkKumar:您必须执行类似的操作:stackoverflow.com/questions/21304988/…

– gklka
2014年2月22日在12:12

@gklka您的答案似乎正确,我已按照您在答案中所述的相同步骤进行操作,但是问题是如果我们更改包路径,则它将在其中找到所有资源(即XIB中使用的.png文件)相同的包,因此我们必须在所有包中(例如en.lproj,es.lproj等)过度复制images文件夹,这样会影响IPA大小的增加,那么有什么办法可以解决这个问题?正如您在帖子中所说的,让我尝试一下,让您更多地感谢您为我提供的帮助

– Dk Kumar
2014-2-24的3:51



这在iOS 9中被严重破坏,返回所有字符串的null。

– Alex Zavatone
2015年10月14日在16:25

#5 楼

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

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


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

评论


很有帮助的答案!附言对于初学者来说,听起来似乎很明显,但是您应该在NSAutoreleasePool * pool ..之后插入该行,否则一些自动释放的对象将泄漏。

–pt2ph8
2011年7月18日在16:52



重要说明:如果您之前调用[[NSBundle mainBundle] URLForResource:withExtension:],则此操作将无效。

–科夫
13年7月30日在8:31

如果使用Swift,那么没有main.m怎么办?

–图灵测试
15年11月24日在18:22

@turingtested您是否尝试过快速和情节提要,是否可行?

– iDevAmit
16/12/22在3:11

嗨,如何本地化来自服务器的动态文本,在我的应用程序中,我必须以简体中文显示每个文本,但是如何以英语显示中文文本。帮我。

–马赫什·纳拉(Mahesh Narla)
17 Mar 28 '17 at 6:02

#6 楼

通过从应用程序中选择特定语言的技巧是强制NSLocalizedString根据所选语言使用特定捆绑软件。 ios应用中的本地化

,这是ios应用中一个示例应用高级本地化的代码

评论


它也可以在iOS7上运行,我不得不从Brian的解决方案切换到该解决方案,因为iOS似乎再次覆盖了languages选项,因此我坚持使用首次设置语言。您的解决方案就像一个魅力!

– haxpor
13年12月28日在12:59

#7 楼

您如何看待这个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.


评论


嗨,如何本地化来自服务器的动态文本,在我的应用程序中,我必须以简体中文显示每个文本,但是如何以英语显示中文文本。帮我。

–马赫什·纳拉(Mahesh Narla)
17 Mar 28 '17 at 6:02

这是一个绝妙的答案;)

–‐BartłomiejSemańczyk
19年4月11日在21:17

好答案对我有帮助

– Dilip Tiwari
19-09-26在6:14

#8 楼

正如Brian Webster所提到的,需要在“应用程序启动初期”设置语言。我以为applicationDidFinishLaunching:中的AppDelegate应该是一个合适的地方,因为它是我进行所有其他初始化的地方。 ,这是没有用的。

但是,如果我将代码放在主函数中,似乎可以正常工作:

非常感谢对此的任何评论。

评论


在我的实现中,这是用户可设置的事情-所以我只是弹出一个对话框,告诉他们他们需要重新启动:)

–威廉·丹尼斯(William Denniss)
2010年9月4日,下午1:41

它几乎适用于所有-除了本地化的Default.png图片。

–卢卡斯
2010-11-30 7:40

如果要让用户设置一种语言然后告诉他们重新启动应用程序,请记住,如果用户重新启动的速度过快,则可能不会保存NSUserDefaults。大多数用户的运行速度并不快,但是当您测试应用程序时,您可能会过快并看到不一致的行为。我花了几个小时才意识到为什么我的语言切换有时会起作用而有时却没有起作用!

– arlomedia
13年1月4日在7:21



这不是问题,只需使用[[NSUserDefaults standardUserDefaults] sync]即可;调用setObject:forKey之后:

–本·男爵
13年2月1日,下午1:38

#9 楼

NSLocalizedString()从标准用户默认值(AppleLanguages)中读取键[NSUserDefaults standardUserDefaults]的值。它使用该值在运行时在所有现有本地化中选择合适的本地化。当Apple在应用启动时构建用户默认词典时,他们会在系统偏好设置中查找首选语言键,然后从中复制值。例如,这也解释了为什么在OS X中更改语言设置对运行的应用程序无效,而仅对之后启动的应用程序无效。一旦复制,就不会仅因为设置更改而更新值。这就是为什么如果您更改语言后iOS会重新启动所有应用的原因。
但是,用户默认字典的所有值都可以被命令行参数覆盖。请参阅NSUserDefaults上的NSArgumentDomain文档。这甚至包括从应用程序首选项(.plist)文件加载的那些值。很高兴知道您是否只想更改一个值以进行测试。您忘记稍后再删除此代码...),而是告诉Xcode使用命令行参数启动您的应用程序(例如,使用西班牙语本地化):



否需要完全触摸您的代码。只需为不同的语言创建不同的方案,就可以通过切换方案快速以一种语言启动应用程序,然后以另一种语言快速启动应用程序。

评论


此功能仅在第一次后才能再次加载到设备偏好设置中。语言 ..

–问
17年8月1日在17:05

@Aks每次都为我工作。确保您启动了正确的方案,确保您从Xcode内部开始(重新启动,派生等),并且确保您没有像Apple提供的新Xcode版本那样覆盖Options中的语言那也是。

–梅基
17年8月2日在8:34

感谢您的回复@Mecki ..对我来说,它不能在xcode中工作,但是当我在代码中提及时,它可以工作。我要传递参数的语言...

–问
17年8月2日在20:04



@Aks在设备上使用时,它仅在直接从Xcode启动时才起作用,当您通过在某些设备上点击其图标再次启动该应用程序时,它将不起作用,并且在该应用程序被杀死时也将不起作用(因为它进入后台)并由系统重新启动(因为此重新启动不是Xcode进行的重新启动)-因此,如果iOS必须在两者之间杀死您的应用程序,则切换到其他应用程序并返回可能不起作用需要内存)。

–梅基
17年8月3日在15:14

您可以将此参数传递与StandardUserDefaults中的更改结合使用,每次都将像超级按钮一样工作

– Leemur
7月7日23:17

#10 楼

我最喜欢Mauro Delrio的方法。
我还在Project_Prefix.pch

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


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

评论


我也喜欢他的方法,并添加了一种方法来加载png图像:+(UIImage)imageNamed:(NSString *)imageFileName {NSString fullPath = [bundle pathForResource:imageFileName ofType:@“ png”]; UIImage * imageObj = [[UIImage alloc] initWithContentsOfFile:fullPath];返回[imageObj autorelease]; }

– Jagie
2011年7月11日在13:04

#11 楼

我想出了一个允许您使用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.h放入使用NSLocalizedString的文件中。

如您所见,我将languageCode存储在AppDelegate的属性中。它可以存储在您想要的任何位置。

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

评论


在#define之前添加#undef NSLocalizedString以禁用警告

–铍
2014年5月3日19:02

这对xib文件的本地化有效吗?我有.xib文件和.strings以特定语言翻译UI名称。我尝试过,但它不能与XIB一起使用,但是我不确定我是否做对了

– Kong Hantrakool
2015年3月1日在18:18

孔先生对您的回复延迟表示抱歉。在您使用NSLocalizedString的任何地方都可以使用。因此它不能直接在XIB中工作。您将需要IBOutlet到XIB中的字符串,然后必须以编程方式在代码中设置字符串值。

– qman64
2015年10月12日23:29

这种方法对我有用,并且我能够即时更改语言。请注意,诸如“ es”,“ fr”和“ en”之类的语言代码可以正常工作,但是“ zh”(简体中文)失败并给了我空字符串。我在系统上对“ es.lproj”进行了全局搜索看到我正在访问的文件在哪里,我发现那里的“ zh.lproj”实际上是“ zh-Hans.lproj”。

–加里蒙
18年7月23日在2:46

#12 楼

迅捷版本:

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


#13 楼

简而言之:

本地化应用程序

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

覆盖NSLocalizedString

在您的代码中,而不是使用NSLocalizedString(key, comment),而是使用这样定义的宏MYLocalizedString(key, comment): Singleton将:


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

设置用户语言

当用户以法语更改应用程序语言时,请致电#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];

- (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中本文的详细信息

评论


我们要求您不仅在答案中链接到解决方案;该链接可能有一天会停止工作。虽然您不必从答案中删除链接,但我们确实要求您编辑答案以包括链接文章相关部分的摘要。

–圣人圣贤
15年4月22日在18:51

#14 楼

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


评论


谢谢。工作顺利。

– Krunal Nagvadia
19年5月7日在19:39

#15 楼

在文件.pch中定义:

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


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


评论


如何摆脱警告“覆盖...”?

–伊丹·莫西(Idan Moshe)
2014-02-19 13:33

简单的解决方案可以满足我的所有需求。能够以此为指导来解决我的问题。如果pathForResource因为没有本地化文件而返回nil,则我使用pathForResource:@“ Base”,因为我尝试过的其他所有操作均未从基本本地化中提取字符串。谢谢。

– GRW
2014-09-19 5:44



这很hacky(所有其他答案也是如此),并且在我正在编写的单元测试中最容易实现。

–最大
19/12/11在17:23

#16 楼

也许您应该对此进行补充(在#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]


评论


/Users/pwang/Desktop/Myshinesvn/Myshine/viewController/OrientationReadyPagesView.m:193:31:使用未声明的标识符“ bundle”

– pengwang
13年3月12日在4:08

#17 楼

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


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

#18 楼

在Swift 4中,我无需重新启动或使用库即可解决该问题。

尝试了许多选项之后,我发现了此函数,您可以在其中传递(Localizable.String,字符串文件的)stringToLocalize您要翻译的语言以及要翻译的语言,它返回的是字符串文件中该字符串的值:

    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


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

评论


这个答案很好,因为它也可以在例如Linux上运行的Swift软件包中使用。

–RémiB.
9月30日18:11

#19 楼

您可以使用要使用的本地化字符串集构建子捆绑包,然后使用NSLocalizedStringFromTableInBundle()加载它们。 (我假设这是与您可能在应用程序上进行的常规UI本地化不同的内容。)

#20 楼

就我而言,我有两个本地化文件ja和en

,并且如果系统中的首选语言既不是en也不是ja
m将编辑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]));


    }


}


评论


感谢@ chings228这对我来说很有用,但这不会更改我对每种语言都有不同启动效果的应用程序的默认启动图像(启动)。你知道如何申请吗?

– JERC
2014年6月4日18:13

我认为启动程序在主程序开始运行之前就运行了,所以我不知道如何重写它,也许plist可以提供帮助,但是下次应用程序打开时可能会起作用

– chings228
2014年6月5日,1:12

#21 楼

您可以执行以下操作:

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


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

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


#22 楼

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

https://github.com/cmaftuleac/BundleLocalization

此实现通过在内部进行调整NSBundle。这个想法是您在NSBundle对象的实例上重写方法localizedStringForKey,然后在使用不同语言的其他包中调用此方法。简单优雅完全兼容所有类型的资源。

评论


该项目中的这段代码对我帮助很大。如何找到特定语言代码的捆绑软件--- NSString * path = [[[NSBundle mainBundle] pathForResource:lang ofType:@“ lproj”];

–尼尔
16年4月12日在9:26

此类运行良好,但是将语言更改为另一种语言后,它没有效果。

– Anilkumar iOS-ReactNative
16年8月4日在7:09

#23 楼

基于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


像下面那样内联更改语言或更新上面类中的“ changeCurrentLanguage”方法以采用引用新语言的字符串参数。

#24 楼

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

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


#25 楼

我想添加对iOS官方不支持的语言(系统设置下“语言”部分未列出)的支持。通过遵循Apple的国际化教程以及Brian Webster和geon的一些提示,我想到了这段代码(将其放在main.m中):

这对于Storyboard和NSLocalizedString代码都适用。该代码假定用户以后可以选择在应用程序内部手动更改语言。以了解具体操作方法。)

评论


我看到您也遇到了斯洛文尼亚语言的问题:)为了改善iOS不支持的语言的答案,您是否想知道我们是否可以设置自定义可本地化的字符串,该字符串将用于应用程序中的系统控件(编辑,完成, ...)?

– miham
16年7月18日在11:40

#26 楼

无论您做什么,最好的方法是采用指定语言的short_name,即:fr,en,nl,de,it等,然后将其分配给全局值。

使选择器视图像下拉菜单一样弹出(单击时会从下面显示选择器视图的按钮与语言列表结合在一起),然后选择所需的语言。
创建一个名为LocalisedString的.h + .m文件。

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

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

没有规则坏了。

#27 楼

对于Swift,您可以覆盖main.swift文件,并在应用运行之前在其中设置UserDefaults字符串。这样,您无需重新启动应用程序即可看到所需的效果。