Cod*_*kes 261 localization objective-c internationalization nslocalizedstring ios
在iPhone上NSLocalizedString
返回iPhone 语言的字符串.是否可以强制NSLocalizedString
使用特定语言使应用程序使用与设备不同的语言?
Bri*_*ter 259
NSLocalizedString()
(及其变体)访问"AppleLanguages"键NSUserDefaults
以确定用户对首选语言的设置.这将返回一组语言代码,第一个是用户为其手机设置的语言代码,如果资源不是首选语言,则后续用作后备.(在桌面上,用户可以在"系统偏好设置"中使用自定义排序指定多种语言)
如果您希望使用setObject:forKey:方法设置自己的语言列表,则可以覆盖自己应用程序的全局设置.这将优先于全局设置值,并返回到应用程序中执行本地化的任何代码.这个代码看起来像这样:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate
Run Code Online (Sandbox Code Playgroud)
这将使德语成为您的应用程序的首选语言,英语和法语作为后备.您可能希望在应用程序启动时的某个时间调用它.您可以在此处阅读有关语言/区域设置首选项的更多信息:国际化编程主题:获取当前语言和区域设置
Gil*_*vik 146
我最近遇到了同样的问题,我不想启动并修补我的整个NSLocalizedString,也不强迫应用程序重启以使新语言工作.我希望一切都按原样运作.
我的解决方案是动态更改主bundle的类并在那里加载适当的bundle:
头文件
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end
Run Code Online (Sandbox Code Playgroud)
履行
#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
Run Code Online (Sandbox Code Playgroud)
所以基本上,当您的应用程序启动时以及加载第一个控制器之前,只需调用:
[NSBundle setLanguage:@"en"];
Run Code Online (Sandbox Code Playgroud)
当您的用户在设置屏幕中更改其首选语言时,只需再次调用它:
[NSBundle setLanguage:@"fr"];
Run Code Online (Sandbox Code Playgroud)
要重置回系统默认值,只需传递nil:
[NSBundle setLanguage:nil];
Run Code Online (Sandbox Code Playgroud)
请享用...
对于那些需要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)
}
}
Run Code Online (Sandbox Code Playgroud)
Mau*_*rio 137
我通常以这种方式执行此操作,但您必须在项目中拥有所有本地化文件.
@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
Run Code Online (Sandbox Code Playgroud)
Tud*_*dor 41
不要在iOS 9上使用.对于通过它传递的所有字符串,它返回nil.
我找到了另一种解决方案,允许您更新语言字符串,无需重新启动应用程序并与genstrings兼容:
将此宏放在Prefix.pch中:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
Run Code Online (Sandbox Code Playgroud)
以及在哪里需要使用本地化字符串:
NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")
Run Code Online (Sandbox Code Playgroud)
要设置语言使用:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
Run Code Online (Sandbox Code Playgroud)
即使连续语言跳跃也能正常工作:
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, @""));
Run Code Online (Sandbox Code Playgroud)
小智 32
如前所述,只需:
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];
Run Code Online (Sandbox Code Playgroud)
但是为了避免重新启动应用程序,请将行放在main方法main.m
之前UIApplicationMain
(...).
Bar*_*zyk 13
您对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)
}
}
Run Code Online (Sandbox Code Playgroud)
用法简单:
"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.
Run Code Online (Sandbox Code Playgroud)
geo*_*eon 12
正如Brian Webster所提到的那样,语言需要"在应用程序启动的早期"设置.我想到applicationDidFinishLaunching:
的AppDelegate
应该是一个合适的地方做,因为这就是我做的所有其他初始化.
但正如William Denniss所提到的那样,只有在应用程序重新启动后才会产生影响,这有点无用.
如果我把代码放在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;
}
Run Code Online (Sandbox Code Playgroud)
我对此表示感谢.
小智 11
我最喜欢Mauro Delrio的方法.我还在Project_Prefix.pch中添加了以下内容
#import "Language.h"
#define MyLocalizedString(key, alt) [Language get:key alter:alt]
Run Code Online (Sandbox Code Playgroud)
因此,如果您想使用标准方法(使用NSLocalizedString),您可以在所有文件中进行快速语法替换.
Mec*_*cki 11
NSLocalizedString()
AppleLanguages
从标准用户默认值([NSUserDefaults standardUserDefaults]
)读取键的值.它使用该值在运行时在所有现有本地化中选择适当的本地化.当Apple在应用程序启动时构建用户默认字典时,他们会在系统首选项中查找首选语言键并从中复制值.这也解释了为什么更改OS X中的语言设置对运行应用程序没有影响,仅限于此后启动的应用程序.复制后,仅因为设置更改而不更新该值.这就是为什么iOS重新启动所有应用程序,如果您更改当时的语言.
但是,用户默认字典的所有值都可以被命令行参数覆盖.请参阅有关的NSUserDefaults
文档NSArgumentDomain
.这甚至包括从app首选项(.plist)文件加载的值.如果您想要仅为测试更改一次值,这真的很好.
因此,如果您只想更改语言以进行测试,您可能不希望更改代码(如果您以后忘记删除此代码...),而是告诉Xcode使用命令行参数启动您的应用程序(例如使用西班牙本地化):
根本不需要触摸您的代码.只需为不同的语言创建不同的方案,您只需切换方案,就可以用一种语言快速启动应用程序,再用另一种语言启动一次.
小智 10
我想出了一个允许你使用的解决方案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
Run Code Online (Sandbox Code Playgroud)
实现是这样的.
// 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
Run Code Online (Sandbox Code Playgroud)
而不仅仅是将import添加NSBundle+RunTimeLanguage.h
到使用的文件中NSLocalizedString
.
如您所见,我将languageCode存储在属性中AppDelegate
.这可以存储在您喜欢的任何地方.
我唯一不喜欢的是NSLocalizedString
马克重新定义的警告.也许有人可以帮我解决这个问题.
Swift版本:
NSUserDefaults.standardUserDefaults().setObject(["fr"], forKey: "AppleLanguages")
NSUserDefaults.standardUserDefaults().synchronize()
Run Code Online (Sandbox Code Playgroud)
您要做的第一件事就是使用至少两种语言(本例中为英语和法语)本地化您的应用程序.
在您的代码中NSLocalizedString(key, comment)
,使用如下MYLocalizedString(key, comment)
定义的宏而不是使用:
#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];
这个MYLocalizationSystem
单身人士将:
当用户用法语更改应用程序语言时,请致电 [[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];
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,此方法将本地化的bundle设置为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];
}
Run Code Online (Sandbox Code Playgroud)
希望这会帮助你.
您可以在NSWinery.io的这篇文章中找到更多细节
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
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
Locale.preferredLanguage = "uk"
label.text = "localizedKey".localized
Run Code Online (Sandbox Code Playgroud)
小智 6
在 swift 4 中,我已经解决了它而无需重新启动或使用库。
在尝试了很多选项后,我找到了这个函数,在那里你传递了你想翻译的 stringToLocalize(Localizable.String,字符串文件),以及你想翻译的语言,它返回的是你在字符串文件中的字符串:
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)
}
Run Code Online (Sandbox Code Playgroud)
考虑到这个函数,我在一个 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!)!
}
}
Run Code Online (Sandbox Code Playgroud)
要从整个应用程序以及在其余 ViewControllers 的每个字符串中访问,而不是放置:
NSLocalizedString ("StringToLocalize", comment: “")
Run Code Online (Sandbox Code Playgroud)
我已将其替换为
let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()
NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: “”) //use in each String
Run Code Online (Sandbox Code Playgroud)
我不知道这是否是最好的方法,但我发现它非常简单,并且对我有用,希望对您有所帮助!
小智 5
在文件.pch中定义:
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
139926 次 |
最近记录: |