Appleはこれをお勧めしません).
一般に、アプリケーション内から(AppleLanguages prefキーを使用して)iOSシステム言語を変更しないでください。これは、設定アプリで言語を切り替えるための基本的なiOSユーザーモデルに反し、ドキュメント化されていない設定キーも使用します。つまり、将来、キー名が変更され、アプリケーションが破損する可能性があります。
ただし、これはオンザフライで言語を変更することが理にかなっているアプリケーションです。私はまた、この質問がここで尋ねられたことを知っています: オンザフライで言語を変更する、プログラムで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?())
}
}
例:
@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 。がんばって!
基本的には、異なるバンドルファイルをロードして言語を切り替える方法をバンドルに教える必要があります。
私は Objective-Cコード をSwiftに翻訳しました— 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のサブクラスを使用する代わりに、ビューコントローラは「LANGUAGE_WILL_CHANGE」を投稿して「LANGUAGE_DID_CHANGE」をリッスンすることもできます
私はここに完全なプロジェクトをプッシュしました: ImmediateLanguageSwitchSwift
私にとって、 " Swift Localize "ライブラリはオンザフライの言語切り替えを解決しました。
"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」で述べたものと同じです
訂正はいつでも歓迎です:)
このコード行を使用すると、アプリケーションを閉じずにレイアウトが変更されます。右から左へ
UIView.appearance().semanticContentAttribute = .forceRightToLeft
そして、左から右へのフリップ
UIView.appearance().semanticContentAttribute = .forceLeftToRight
テキストフィールドのレイアウトまたはテキストの変更を変更する場合は、この問題に直面したため、このコードを使用します。テキストフィールドのテキストはレイアウトを変更していませんでした。このコードをチェックして、テキストフィールドテキストのレイアウトを変更します。
extension UITextField {
open override func awakeFromNib() {
super.awakeFromNib()
if UserDefaults.languageCode == "ar" {
if textAlignment == .natural {
self.textAlignment = .right
}
}
}
}