在iPhone上NSLocalizedString返回iPhone语言的字符串。 是否有可能强制NSLocalizedString使用特定语言来拥有应用程序 用不同的语言吗?
当前回答
也许你应该补充这个(在.pch文件#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]
其他回答
我最近也遇到了同样的问题,我不想启动和修补我的整个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)
}
}
你可以这样做:
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];
NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):
你觉得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.
根据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"];
斯威夫特版本:
NSUserDefaults.standardUserDefaults().setObject(["fr"], forKey: "AppleLanguages")
NSUserDefaults.standardUserDefaults().synchronize()
推荐文章
- Xcode构建失败“架构x86_64未定义的符号”
- 如何使用Xcode创建。ipa文件?
- 动态改变UILabel的字体大小
- registerForRemoteNotificationTypes: iOS 8.0及以上版本不支持
- 新的自动引用计数机制是如何工作的?
- 如何测试对象在Objective-C中的类?
- 在iPhone上确定用户是否启用了推送通知
- 是否有可能禁用浮动头在UITableView与UITableViewStylePlain?
- 从Cocoa应用程序执行一个终端命令
- 错误ITMS-9000:“冗余二进制文件上传。火车1.0版本已经有一个二进制版本上传。
- Swift -转换为绝对值
- Swift编译器错误:“框架模块内的非模块化头”
- 从父iOS访问容器视图控制器
- 自定义dealloc和ARC (Objective-C)
- 调整UITableView的大小以适应内容