Ich hatte kürzlich das gleiche Problem und wollte nicht meinen gesamten NSLocalizedString starten und patchen noch die App zum Neustart zwingen, damit die neue Sprache funktioniert. Ich wollte, dass alles so funktioniert, wie es ist.
Meine Lösung bestand darin, die Klasse des Hauptpakets dynamisch zu ändern und das entsprechende Paket dort zu laden:
Header-Datei
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end
Implementierung
#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
Wenn Ihre App gestartet wird und bevor Sie Ihren ersten Controller laden, rufen Sie einfach an:
[NSBundle setLanguage:@"en"];
Wenn Ihr Benutzer seine bevorzugte Sprache in Ihrem Einstellungsbildschirm ändert, rufen Sie ihn einfach erneut auf:
[NSBundle setLanguage:@"fr"];
Um auf die Systemstandards zurückzusetzen, übergeben Sie einfach nil:
[NSBundle setLanguage:nil];
Genießen...
Für diejenigen, die eine Swift-Version benötigen:
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)
}
}