以编程方式在运行iOS时即时更改语言

我已经堆积并search了几个小时。 而且我现在有点绝望。 我想改变我的应用程序内的语言不仅在默认的语言。

从我试过的东西,我坚持每个人都重启一步。 意思是,苹果迫使你手动重启应用程序。 这意味着你必须退出应用程序,然后重新启动它。

那么,谷歌search后,我试图设置一个警报,然后迫使应用程序退出

exit(0); 

我的坏,苹果似乎不喜欢这个,并阻止开发人员使用它…我想我没有指向正确的方向。

最后,尽pipe所有的问题,我可以见面,我想讨论一下。

任何提示?


编辑,从苹果的信息

通常,您不应该在应用程序中更改iOS系统语言(通过使用AppleLanguages首选项)。 这违背了在“设置”应用程序中切换语言的基本iOS用户模型,并且还使用了未logging的首选项,这意味着在将来的某个时刻,关键名称可能会改变,这将会破坏您的应用程序。

如果您想在应用程序中切换语言,可以通过手动加载资源文件到您的软件包中来实现。 您可以使用NSBundle:pathForResource:ofType:inDirectory:forLocalization:为此目的,但请记住,您的应用程序将负责所有本地化数据的加载。

关于exit(0)问题,Apple DTS无法评论应用程序审批stream程。 你应该联系appreview@apple.com得到这个问题的答案。

那么,我必须select到目前为止。

这是一个相当古老的问题,但我只是同样的问题挣扎,发现这个解决scheme:

http://aggressive-mediocrity.blogspot.com/2010/03/custom-localization-system-for-your.html

这正是你所需要的(并可能有助于其他同样的问题:)

是的,我有同样的问题,然后我用我自己的语言设置在我的prefFile,我设置一个variables的语言设置:

 // write a new value in file and set the var - (void)changeLangInPrefFile:(NSString *)newLanguage { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *path = [documentsDirectory stringByAppendingPathComponent:@"myPreference.plist"]; NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: path]; //here add elements to data file and write data to file [data setObject:newLanguage forKey:@"language"]; [data writeToFile:path atomically:YES]; [data release]; // NSString *chosenLang; <- declared in .h file if (chosenLang != nil){ [chosenLang release]; chosenLang = nil; } chosenLang = [[NSString alloc] initWithString:(@"%@",newLanguage)]; } // read the language from file and set the var: - (void)readFromFileInBundleDocuments { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *path = [documentsDirectory stringByAppendingPathComponent:@"myPreference.plist"]; NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile:path]; NSString *chosenLangTemp = [savedStock objectForKey:@"language"]; NSLog (@"read in file: %@", chosenLangTemp); if (chosenLang != nil){ [chosenLang release]; chosenLang = nil; } chosenLang = [[NSString alloc] initWithString:(@"%@",chosenLangTemp)]; [savedStock release]; } 

然后我加载所有的内容从不同的文件取决于语言,例如我可以加载“an_image_eng.png”或“an_image_ita.png”,或有2个不同的.xib文件,并加载文本我使用不同的字典文件,每个语言一个,所有的单词/expression式翻译,我只是加载所选的一个,并在其中读入正确的expression为每个文本加载(代码来加载它是类似于我写在这个例子中的方法,你可以只是安排它为每个expression式读正确的单词:只要看右边的字典文件中的objectForKey的值,其中objectForKey是要翻译的单词,它的值是翻译的单词)…

下面的链接有一个很好的实现在应用程序中使用自定义语言。

iOS-App(iPhone和iPad)中的手动语言select

尝试一个SWIFT版本在这里findLanguageSettings_Swift

LanguageChange

-anoop

一般来说,用户看到的语言是由区域设置决定的,这是一个系统范围的设置。 只有用户可以修改,SpringBoard和设备上的每个正在运行的应用程序都必须重新启动。 没有办法解决这个问题,因为所有的系统应用程序和框架都假定一旦开始运行,语言环境就不会改变。 改变应用程序和框架,不需要重新启动,对苹果来说是非常困难的。

我猜你要么完全独立于系统区域设置来改变应用程序界面的语言,要么默认使用系统区域设置,但是允许用户只为你的应用程序覆盖它。

您可以使用+[NSLocale currentLocale]获取当前语言环境并检查其各种值。 要以独立于系统语言环境的语言显示应用程序的用户界面,您需要完全避免使用NSLocalizedString() ,并使用某种自定义状态来确定向用户显示哪些string,以及如何修改界面以适应您的应用程序的语言。 这将取决于你保持你的应用程序的语言状态,并适当修改其用户界面。

根据Apple guidelines这不是一个好主意,以应用程序的方式改变语言,但如果你没有权力改变请求的行为,你可以做下一个:

  1. 准备一些服务来pipe理你的语言,即使重启应用程序

     enum LanguageName: String { case undefined case en case es } let DynamicLanguageServiceDidDetectLanguageSwitchNotificationKey = "DynamicLanguageServiceDidDetectLanguageSwitchNotificationKey" func dynamicLocalizableString(_ key: String) -> String { return LanguageService.service.dynamicLocalizedString(key) } class LanguageService { private struct Defaults { static let keyAppleLanguage = "AppleLanguages" static let keyCurrentLanguage = "KeyCurrentLanguage" } static let service:LanguageService = LanguageService() var languageCode: String { get { return language.rawValue } } var currentLanguage:LanguageName { get { var currentLanguage = UserDefaults.standard.object(forKey: Defaults.keyCurrentLanguage) if let currentLanguage = currentLanguage as? String { UserDefaults.standard.set([currentLanguage], forKey: Defaults.keyAppleLanguage) UserDefaults.standard.synchronize() } else { if let languages = UserDefaults.standard.object(forKey: Defaults.keyAppleLanguage) as? [String] { currentLanguage = languages.first } } if let currentLanguage = currentLanguage as? String, let lang = LanguageName(rawValue: currentLanguage) { return lang } return LanguageName.undefined } } func switchToLanguage(_ lang:LanguageName) { language = lang NotificationCenter.default.post(name: NSNotification.Name(rawValue: DynamicLanguageServiceDidDetectLanguageSwitchNotificationKey), object: nil) } private var localeBundle:Bundle? fileprivate var language: LanguageName = LanguageName.en { didSet { let currentLanguage = language.rawValue UserDefaults.standard.set([currentLanguage], forKey:Defaults.keyAppleLanguage) UserDefaults.standard.setValue(currentLanguage, forKey:Defaults.keyCurrentLanguage) UserDefaults.standard.synchronize() setLocaleWithLanguage(currentLanguage) } } // MARK: - LifeCycle private init() { prepareDefaultLocaleBundle() } //MARK: - Private fileprivate func dynamicLocalizedString(_ key: String) -> String { var localizedString = key if let bundle = localeBundle { localizedString = NSLocalizedString(key, bundle: bundle, comment: "") } else { localizedString = NSLocalizedString(key, comment: "") } return localizedString } private func prepareDefaultLocaleBundle() { var currentLanguage = UserDefaults.standard.object(forKey: Defaults.keyCurrentLanguage) if let currentLanguage = currentLanguage as? String { UserDefaults.standard.set([currentLanguage], forKey: Defaults.keyAppleLanguage) UserDefaults.standard.synchronize() } else { if let languages = UserDefaults.standard.object(forKey: Defaults.keyAppleLanguage) as? [String] { currentLanguage = languages.first } } if let currentLanguage = currentLanguage as? String { updateCurrentLanguageWithName(currentLanguage) } } private func updateCurrentLanguageWithName(_ languageName: String) { if let lang = LanguageName(rawValue: languageName) { language = lang } } private func setLocaleWithLanguage(_ selectedLanguage: String) { if let pathSelected = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj"), let bundleSelected = Bundle(path: pathSelected) { localeBundle = bundleSelected } else if let pathDefault = Bundle.main.path(forResource: LanguageName.en.rawValue, ofType: "lproj"), let bundleDefault = Bundle(path: pathDefault) { localeBundle = bundleDefault } } } 
  2. 添加一些规则,以确保您的UI组件将始终更新:

     protocol Localizable { func localizeUI() } 
  3. 实施它们

     class LocalizableViewController: UIViewController { // MARK: - LifeCycle override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(self.localizeUI), name: NSNotification.Name(rawValue:DynamicLanguageServiceDidDetectLanguageSwitchNotificationKey), object: nil) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) localizeUI() } deinit { NotificationCenter.default.removeObserver(self) } } extension LocalizableViewController: Localizable { // MARK: - Localizable func localizeUI() { fatalError("Must Override to provide inApp localization functionality") } } 
  4. inheritance任何控制器你想符合dynamic应用程序切换function,并实现localizeUI()function

     final class WelcomeTableViewController: LoadableTableViewController 
  5. 根据需要切换语言:

     LanguageService.service.switchToLanguage(.en) 
  6. 所有可本地化的string应设置为:

     label.text = dynamicLocalizableString(<KEY_IN_STRINGS>) 

注意:不要忘记用LanguageName相同代码添加Localizable.strings

在这里输入图像说明