我的应用程序必须支持阿拉伯语(从右到左方向)和英语(从左到右方向)语言,我需要设置UI并基于用户 从我的应用程序中选择的语言。
我将使用NSLayoutConstraint实现UI,以便它可以根据前导和尾随约束自动更新UI 。
现在我的问题是我该如何实现?由于我的设备语言是英语,并且从我的应用程序用户中选择阿拉伯语(仅限于我的应用程序),因此我的Flow,UI,动画等应从右到左。
最重要的是,您可以在应用程序内部更改语言。但是,需要额外的 工作。我列出了每个iOS 版本的限制背景,然后提供了解决方案。因为在解释 解决方案时,您需要了解其背后的原因。
更新(iOS 9+) 解决方案密钥:semanticContentAttribute
有人说这种方式不是官方的,可能会导致效率问题。
现在可以在不关闭应用程序的情况下强制执行UI方向:
UIView.appearance().semanticContentAttribute = .forceRightToLeft
请注意,iOS 9中的条不能强制为RTL(导航和TabBar)。尽管它 在iOS 10中被强制使用。
iOS 10中唯一不能强制使用RTL的功能是默认的 后退按钮。
更改应用程序的语言以及强制布局不会 自动强制系统使用 与该语言关联的本地化字符串文件。
在iOS 9以下 简短答案:
更改应用程序语言将不会在 不重新启动应用程序的情况下根据所选语言强制布局方向。
苹果的指导方针:
苹果公司不提供这种服务,因为他们不喜欢允许用户 从应用程序内部更改语言。苹果公司要求开发人员使用 设备语言。而不是完全从应用程序内部进行更改。
工作伤口:
某些支持阿拉伯语言的应用程序会在设置页面 (该页面中用户可以更改语言)中向用户提示,如果不 重新启动应用程序,布局将不会生效。存储示例 应用程序的链接
将应用程序语言更改为阿拉伯语的示例代码:
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"ar", @"en", nil] forKey:@"AppleLanguages"];
That won’t take effect without a restart
Solution is to provide your own localization solution:
ViewController
unwindSegue
viewDidLoad
Don’t satisfy points 5 and 6 if you are not supporting below iOS 9
Set the constraints for your views in viewDidLoad method for all view controllers.
When you set the constraints use right/left according to the language selected instead of leading/trailing.
Language class sample (Swift): Initialise an object of this class in your singlton class.
class LanguageDetails: NSObject { var language: String! var bundle: Bundle! let LANGUAGE_KEY: String = "LANGUAGE_KEY" override init() { super.init() // user preferred languages. this is the default app language(device language - first launch app language)! language = Bundle.main.preferredLocalizations[0] // the language stored in UserDefaults have the priority over the device language. language = Common.valueForKey(key: LANGUAGE_KEY, default_value: language as AnyObject) as! String // init the bundle object that contains the localization files based on language bundle = Bundle(path: Bundle.main.path(forResource: language == "ar" ? language : "Base", ofType: "lproj")!) // bars direction if isArabic() { UIView.appearance().semanticContentAttribute = .forceRightToLeft } else { UIView.appearance().semanticContentAttribute = .forceLeftToRight } } // check if current language is arabic func isArabic () -> Bool { return language == "ar" } // returns app language direction. func rtl () -> Bool { return Locale.characterDirection(forLanguage: language) == Locale.LanguageDirection.rightToLeft } // switches language. if its ar change it to en and vise-versa func changeLanguage() { var changeTo: String // check current language to switch to the other. if language == "ar" { changeTo = "en" } else { changeTo = "ar" } // change language changeLanguageTo(lang: changeTo) Log.info("Language changed to: \(language)") } // change language to a specfic one. func changeLanguageTo(lang: String) { language = lang // set language to user defaults Common.setValue(value: language as AnyObject, key: LANGUAGE_KEY) // set prefered languages for the app. UserDefaults.standard.set([lang], forKey: "AppleLanguages") UserDefaults.standard.synchronize() // re-set the bundle object based on the new langauge bundle = Bundle(path: Bundle.main.path(forResource: language == "ar" ? language : "Base", ofType: "lproj")!) // app direction if isArabic() { UIView.appearance().semanticContentAttribute = .forceRightToLeft } else { UIView.appearance().semanticContentAttribute = .forceLeftToRight } Log.info("Language changed to: \(language)") } // get local string func getLocale() -> NSLocale { if rtl() { return NSLocale(localeIdentifier: "ar_JO") } else { return NSLocale(localeIdentifier: "en_US") } } // get localized string based on app langauge. func LocalString(key: String) -> String { let localizedString: String? = NSLocalizedString(key, bundle: bundle, value: key, comment: "") // Log.ver("Localized string '\(localizedString ?? "not found")' for key '\(key)'") return localizedString ?? key } // get localized string for specific language func LocalString(key: String, lan: String) -> String { let bundl:Bundle! = Bundle(path: Bundle.main.path(forResource: lan == "ar" ? lan : "Base", ofType: "lproj")!) return NSLocalizedString(key, bundle: bundl, value: key, comment: "") } }
Language class sample (Objective-c): Swift sample provides full solution. sorry you need to convert it yourself.
@implementation LanguageDetails @synthesize language; @synthesize bundle; #define LANGUAGE_KEY @"LANGUAGE_KEY" // language var is also the strings file name ar or en - (id)init { if (self = [super init]) { language = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]; if (![language isEqualToString:@"ar"]) language = @"en"; language = [Common valueForKey:LANGUAGE_KEY defaultValue:language]; bundle = [NSBundle mainBundle]; } return self; } - (BOOL)rtl { return [NSLocale characterDirectionForLanguage:language] == NSLocaleLanguageDirectionRightToLeft; } - (void)changeLanguage { if ([language isEqualToString:@"ar"]) language = @"en"; else language = @"ar"; [Common setValue:language forKey:LANGUAGE_KEY]; } - (void)changeLanguageTo:(NSString *)lang { language = lang; [Common setValue:language forKey:LANGUAGE_KEY]; } - (NSString *) LocalString:(NSString *)key { return NSLocalizedStringFromTableInBundle(key, language, bundle, nil); } @end