现在我知道苹果不推荐这个。
通常,您不应在应用程序中更改iOS系统语言(通过使用AppleLanguages pref键)。这违反了在Settings应用程序中切换语言的基本iOS用户模型,并且还使用了未记录的首选项密钥,这意味着在将来的某个时刻,密钥名称可能会更改,这会破坏您的应用程序。
然而,这是一个应用程序,即时更改语言是有道理的,只要相信我。我也知道这个问题在这里被问到:Changing language on the fly, in running iOS, programmatically。然而,这已经老了,我想知道是否有更新,更好或更简单的方法来做到这一点。目前在我的应用程序中,我有一个语言选择屏幕。单击此视图中的按钮将使用与该按钮关联的语言调用以下函数:
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?())
}
}
示例:
@IBAction func english(sender: UIButton) {
changeLang("en")
}
如果用户选择的语言与他们自己的语言不同,则会收到确认提示,然后请求重新启动设备。这就是我想要改变的。在应用程序重新启动之前,NSUSerDefaults的这一部分似乎不会同步。证据:
let currentLang: AnyObject? = NSLocale.preferredLanguages()[0]
println(currentLang)
// Prints english
changeLang("zh-Hans")
println(currentLang)
// Prints english still until restart
Apple目前的国际化系统很棒,我打算使用它。但是,如何通过强制更新NSUSerDefaults来动态更改语言?
修改:我建议现在使用此library执行此操作。祝你好运!
答案 0 :(得分:26)
基本上你必须教你如何通过加载不同的捆绑文件来捆绑语言。
我将Objective-C code翻译成斯威夫特 - 并保持NSBundle类别不变。
结果是一个视图控制器类,它提供了一个languageDidChange()
方法来覆盖。
一个NSBundle + Language.h
#import <Foundation/Foundation.h>
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end
一个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
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
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
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: "")
}
}
而不是使用BaseViewController的子类,您的viewcontrollers也可以发布“LANGUAGE_WILL_CHANGE”并监听“LANGUAGE_DID_CHANGE”
我在这里推送完整的项目:ImmediateLanguageSwitchSwift
答案 1 :(得分:6)
对我来说,“Swift Localize”库解决了即时语言切换。
答案 2 :(得分:3)
如上面“ 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)
}
}
剩余代码将与“ vikingosegundo”中提到的相同
始终欢迎更正:)
答案 3 :(得分:0)
使用此行代码,它将更改布局而无需关闭应用程序。 从右到左
<?php
public function store(Request $request)
{
$this->validate($request, array(
'date_input' => 'required|date',
'number_of_mortality' => 'required|numeric',
) );
$cycle = Cycle::select('id', 'date_start_raise')
->where('date_start_raise','<=',$request->get('date_input'))
->where('date_end_raise','>=',$request->get('date_input'))
->orderBy('date_end_raise desc') //not sure, I've never used laravel
->limit(1) //not sure, I've never used laravel
->get();
$id = 0;
$chickenAge = 0;
foreach($cycle as $value){
$id = $value->id;
}
if ($id) {
$start = new Carbon($value->date_start_raise);
$chickenAge = $start->diffInDays(request('date_input')) ;
}
return Mortality::create([
'date_input' => request('date_input'),
'number_of_mortality' => request('number_of_mortality'),
'chicken_age' => $chickenAge,
'cause_of_death' => request('cause_of_death'),
'cycle_id' => $id,
'user_id' => Auth::id()
]);
}
从左向右翻转
console.clear();
const array = [
{id: 1, parent: 0},
{id: 2, parent: 1},
{id: 3, parent: 1},
{id: 4, parent: 1}
];
const newArray = array.filter(el => el.id === 2 && {...el});
const newArray2 = array.map(el => ({...el}));
newArray[0].children = 3; // mutation of initial array
const newEl = {...array[2]};
console.log('Array: ', array);
console.log('newArray2: ', newArray2);
console.log('array[1] === newArray[0]: ', array[1] === newArray[0]); // WTF???
console.log('array[1] === newArray2[1]: ', array[1] === newArray2[1]);
console.log('newEl === array[2]: ', newEl === array[2]);
,如果您想更改文本字段布局或更改文本,请使用此代码,因为我遇到了这个问题。 textfield的文本未更改布局。检查此代码以更改文本字段文本的布局。
UIView.appearance().semanticContentAttribute = .forceRightToLeft