ios 快速更改语言
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31840176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Changing language on the fly in swift
提问by modesitt
Now I know that apple does not recommend this.
现在我知道苹果不推荐这个。
In general, you should not change the iOS system language (via use of the AppleLanguages pref key) from within your application. This goes against the basic iOS user model for switching languages in the Settings app, and also uses a preference key that is not documented, meaning that at some point in the future, the key name could change, which would break your application.
通常,您不应在应用程序中更改 iOS 系统语言(通过使用 AppleLanguages 首选项键)。这与用于在“设置”应用中切换语言的基本 iOS 用户模型背道而驰,并且还使用了未记录的首选项键,这意味着在将来的某个时候,键名称可能会更改,这会破坏您的应用程序。
However, this is an application that changing the language on the fly makes sense, just trust me on that. I also know this question was asked here: Changing language on the fly, in running iOS, programmatically. This however is getting old and I was wondering if there are any newer, better, or easier ways to do this. Currently in my app, I have a language choosing screen. Clicking on of the buttons in this view calls the following function with the language the button is associated with:
但是,这是一个可以即时更改语言的应用程序,请相信我。我也知道这里有人问过这个问题:以编程方式在运行 iOS 时动态更改语言。然而,这已经过时了,我想知道是否有更新、更好或更简单的方法来做到这一点。目前在我的应用程序中,我有一个语言选择屏幕。单击此视图中的按钮会使用与按钮关联的语言调用以下函数:
func changeLang(language: String) {
if language != (currentLang as! String?)! {
func handleCancel(alertView: UIAlertAction!)
{
}
var alert = UIAlertController(title: NSLocalizedString("language", comment: "Language"), message: NSLocalizedString("languageWarning", comment: "Warn User of Language Change Different Than Defaults"), preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler:handleCancel))
alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default, handler:{ (UIAlertAction) in
NSUserDefaults.standardUserDefaults().setObject([language], forKey: "AppleLanguages")
NSUserDefaults.standardUserDefaults().synchronize()
println(self.currentLang)
let alert = UIAlertView()
alert.title = NSLocalizedString("language", comment: "Sign In Failed")
alert.message = NSLocalizedString("languageChangeNotification", comment: "Notify of language change")
alert.addButtonWithTitle(NSLocalizedString("ok", comment: "Okay"))
alert.show()
self.performSegueWithIdentifier("welcome", sender: AnyObject?())
}))
self.presentViewController(alert, animated: true, completion: {
})
} else {
self.performSegueWithIdentifier("welcome", sender: AnyObject?())
}
}
Example:
例子:
@IBAction func english(sender: UIButton) {
changeLang("en")
}
If the user picks a language different than their own, they get a confirmation alert, and then are requested to restart there device. This is what I want to change. It appears that this section of NSUSerDefaults is not synchronized until the app restarts. Evidence:
如果用户选择的语言不同于他们自己的语言,他们会收到确认警报,然后被要求重新启动该设备。这就是我想要改变的。看来 NSUSerDefaults 的这一部分在应用程序重新启动之前不会同步。证据:
let currentLang: AnyObject? = NSLocale.preferredLanguages()[0]
println(currentLang)
// Prints english
changeLang("zh-Hans")
println(currentLang)
// Prints english still until restart
The current internationalization system apple has is great, and I plan on using it. However, how can I change the language on the fly, maybe by forcing an update on the NSUSerDefaults?
苹果目前的国际化系统很棒,我打算使用它。但是,我如何动态更改语言,也许是通过强制更新 NSUSerDefaults?
Edit:I recommend using this libraryto do this now. Best of luck!
编辑:我建议现在使用这个库来做到这一点。祝你好运!
回答by vikingosegundo
Basically you have to teach you bundle how to switch languages by loading different bundle files.
基本上,您必须通过加载不同的捆绑文件来教您捆绑如何切换语言。
I translated my Objective-C codeto Swift — with leaving the NSBundle category untouched.
我将我的Objective-C 代码翻译成 Swift — 保持 NSBundle 类别不变。
The result is a view controller class that offers a languageDidChange()
method for overriding.
结果是一个提供languageDidChange()
覆盖方法的视图控制器类。
NSBundle+Language.h
NSBundle+语言.h
#import <Foundation/Foundation.h>
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end
NSBundle+Language.m
NSBundle+Language.m
#import "NSBundle+Language.h"
#import <objc/runtime.h>
static const char associatedLanguageBundle=0;
@interface PrivateBundle : NSBundle
@end
@implementation PrivateBundle
-(NSString*)localizedStringForKey:(NSString *)key
value:(NSString *)value
table:(NSString *)tableName
{
NSBundle* bundle=objc_getAssociatedObject(self, &associatedLanguageBundle);
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],[PrivateBundle class]);
});
objc_setAssociatedObject([NSBundle mainBundle], &associatedLanguageBundle, language ?
[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
AppDelegate.swift
AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "languageWillChange:", name: "LANGUAGE_WILL_CHANGE", object: nil)
let targetLang = NSUserDefaults.standardUserDefaults().objectForKey("selectedLanguage") as? String
NSBundle.setLanguage((targetLang != nil) ? targetLang : "en")
return true
}
func languageWillChange(notification:NSNotification){
let targetLang = notification.object as! String
NSUserDefaults.standardUserDefaults().setObject(targetLang, forKey: "selectedLanguage")
NSBundle.setLanguage(targetLang)
NSNotificationCenter.defaultCenter().postNotificationName("LANGUAGE_DID_CHANGE", object: targetLang)
}
}
BaseViewController.swift
BaseViewController.swift
import UIKit
class BaseViewController: UIViewController {
@IBOutlet weak var englishButton: UIButton!
@IBOutlet weak var spanishButton: UIButton!
deinit{
NSNotificationCenter.defaultCenter().removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "languageDidChangeNotification:", name: "LANGUAGE_DID_CHANGE", object: nil)
languageDidChange()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func switchLanguage(sender: UIButton) {
var localeString:String?
switch sender {
case englishButton: localeString = "en"
case spanishButton: localeString = "es"
default: localeString = nil
}
if localeString != nil {
NSNotificationCenter.defaultCenter().postNotificationName("LANGUAGE_WILL_CHANGE", object: localeString)
}
}
func languageDidChangeNotification(notification:NSNotification){
languageDidChange()
}
func languageDidChange(){
}
}
ViewController.swift
视图控制器.swift
import UIKit
class ViewController: BaseViewController {
@IBOutlet weak var helloLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func languageDidChange() {
super.languageDidChange()
self.helloLabel.text = NSLocalizedString("Hello", comment: "")
}
}
instead of using subclasses of BaseViewController, your viewcontrollers could also post "LANGUAGE_WILL_CHANGE" and listen for "LANGUAGE_DID_CHANGE"
除了使用 BaseViewController 的子类之外,您的视图控制器还可以发布“LANGUAGE_WILL_CHANGE”并监听“LANGUAGE_DID_CHANGE”
I pushed the complete project here: ImmediateLanguageSwitchSwift
我在这里推送了完整的项目:ImmediateLanguageSwitchSwift
回答by singh.jitendra
As answered by "vikingosegundo" above was having category in Objective c
So here is Swift extension
version
正如“ vikingosegundo”所回答的,上面有类别Objective c
所以这里是Swift extension
版本
import ObjectiveC
private var associatedLanguageBundle:Character = "0"
class PrivateBundle: Bundle {
override func localizedString(forKey key: String, value: String?, table tableName: String?) -> String {
let bundle: Bundle? = objc_getAssociatedObject(self, &associatedLanguageBundle) as? Bundle
return (bundle != nil) ? (bundle!.localizedString(forKey: key, value: value, table: tableName)) : (super.localizedString(forKey: key, value: value, table: tableName))
}
}
extension Bundle {
class func setLanguage(_ language: String) {
var onceToken: Int = 0
if (onceToken == 0) {
/* TODO: move below code to a static variable initializer (dispatch_once is deprecated) */
object_setClass(Bundle.main, PrivateBundle.self)
}
onceToken = 1
objc_setAssociatedObject(Bundle.main, &associatedLanguageBundle, (language != nil) ? Bundle(path: Bundle.main.path(forResource: language, ofType: "lproj") ?? "") : nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
remains code will same as mentioned by "vikingosegundo"
剩余代码将与“vikingosegundo”提到的相同
Corrections are always welcome :)
随时欢迎更正:)
回答by Shahzaib Maqbool
Use this line of code it will change layout without closing application. From right to left
使用这行代码,它将在不关闭应用程序的情况下更改布局。从右到左
UIView.appearance().semanticContentAttribute = .forceRightToLeft
And for Left to Right Flip
对于从左到右翻转
UIView.appearance().semanticContentAttribute = .forceLeftToRight
and if you want to change textfield layout or text change then use this code because i faced this issue . textfield's texts was not changning layout. check this code to change layout of textfield text.
如果您想更改文本字段布局或文本更改,请使用此代码,因为我遇到了这个问题。文本字段的文本没有改变布局。检查此代码以更改文本字段文本的布局。
extension UITextField {
open override func awakeFromNib() {
super.awakeFromNib()
if UserDefaults.languageCode == "ar" {
if textAlignment == .natural {
self.textAlignment = .right
}
}
}
}