iOS应用程序中的手动语言选择(iPhone和iPad)

iOS应用程序中的手动语言选择(iPhone和iPad),ios,localization,selection,appsettings,Ios,Localization,Selection,Appsettings,我的问题: cell.textLabel.text = @"nice title"; cell.textLabel.text = LocalizedString(@"nice title"); 我的iPhone应用程序如何告诉iOS,用户确实在应用程序首选项中选择了一种不同于常规设置中设置的语言 同一问题的其他表述: 我如何告诉系统,NSLocalizedString(@“text”,@“comment”)不应访问系统范围内的选定语言,而应访问应用程序内的选定语言 背景,例如: cell.t

我的问题:

cell.textLabel.text = @"nice title";
cell.textLabel.text = LocalizedString(@"nice title");
我的iPhone应用程序如何告诉iOS,用户确实在应用程序首选项中选择了一种不同于常规设置中设置的语言

同一问题的其他表述:

我如何告诉系统,
NSLocalizedString(@“text”,@“comment”)不应访问系统范围内的选定语言,而应访问应用程序内的选定语言

背景,例如:

cell.textLabel.text = @"nice title";
cell.textLabel.text = LocalizedString(@"nice title");
请以这种情况为例: 一个德国移民的儿子住在法国东北部,毗邻卢森堡和德国。他的母语是法语,所以他将iPhone的用户界面语言设置为法语(设置)→ 一般的→ 国际的→ 语言→ 法国)。但由于他的文化背景和他居住的地区是双语的,他德语也讲得很好。但他不会说十个英语单词。在iPhone(以及iPad)上,他没有选择第二语言的机会,所以手机只知道他会说法语。它不了解其他语言的用户技能

现在我的应用程序来了:我确实用英语和德语开发了它(德语是我的母语,英语是它的标准语言)。我确实根据多语言iOS应用程序的所有规则和最佳实践开发了它。我的应用程序的“第一”语言(默认语言)是英语

这意味着:

如果有人在其设置中选择了英语或德语,则应用程序用户界面将自动使用所选语言。用户甚至不会注意到还有其他可用语言

但如果他在常规设置中选择了任何其他语言(如汉语、波兰语或法语),他将获得应用程序的默认语言,在我的例子中,是英语。但对我的法德朋友来说,这不是最好的选择。他希望使用现有的德语版本,但似乎没有办法让用户选择此版本

添加法语翻译可以解决我们的法德朋友的问题,但不能解决说其他两种语言(如意大利语和德语)的人的问题,而且我无法支持我的应用程序使用这个星球上所有的语言。 将默认语言设置为德语也不是最佳选择,因为这会给说法语(作为母语)和英语(作为第二语言)的人带来同样的问题


因此,我认为我的应用程序必须能够手动选择与预先选择的语言不同的语言。将语言选择添加到“应用程序设置”面板不是问题所在。但是我如何告诉系统,
NSLocalizedString(@“text”,@“comment”)
不应访问系统范围内选定的语言,而应访问应用程序内选定的语言?

只需使用语言选项将以下内容添加到屏幕上即可:

    NSString *tempValue = //user chosen language. Can be picker view/button/segmented control/whatever. Just get the text out of it
    NSString *currentLanguage = @"";
    if ([tempValue rangeOfString:NSLocalizedString(@"English", nil)].location != NSNotFound) {
        currentLanguage = @"en";
    } else if ([tempValue rangeOfString:NSLocalizedString(@"German", nil)].location != NSNotFound) {
        currentLanguage = @"de";
    } else if ([tempValue rangeOfString:NSLocalizedString(@"Russian", nil)].location != NSNotFound) {
        currentLanguage = @"ru";
    }
    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:currentLanguage, nil] forKey:@"AppleLanguages"];
    [[NSUserDefaults standardUserDefaults]synchronize];
然后让他们重新启动应用程序,应用程序将使用其他语言


希望它能帮助我

与此同时,我自己也找到了解决问题的办法:

我创建了一个新类“LocalizeHelper”:


标题本地化helper.h

//LocalizeHelper.h

#import <Foundation/Foundation.h>

// some macros (optional, but makes life easy)

// Use "LocalizedString(key)" the same way you would use "NSLocalizedString(key,comment)"
#define LocalizedString(key) [[LocalizeHelper sharedLocalSystem] localizedStringForKey:(key)]

// "language" can be (for american english): "en", "en-US", "english". Analogous for other languages.
#define LocalizationSetLanguage(language) [[LocalizeHelper sharedLocalSystem] setLanguage:(language)]

@interface LocalizeHelper : NSObject

// a singleton:
+ (LocalizeHelper*) sharedLocalSystem;

// this gets the string localized:
- (NSString*) localizedStringForKey:(NSString*) key;

//set a new language:
- (void) setLanguage:(NSString*) lang;              

@end
/* English - English */

/* for debugging */
"languageOfBundle" = "English - English";

/* Header-Title of the Table displaying all lists and projects */
"summary" = "Summary";

/* Section-Titles in table "summary" */
"help" = "Help";
"lists" = "Lists";
"projects" = "Projects";
"listTemplates" = "List Templates";
"projectTemplates" = "Project Templates";

对于要支持的每种语言,都需要一个名为
Localizable.strings
的文件。这与苹果本地化文档中描述的完全一样。唯一的区别是:现在你甚至可以使用苹果不支持的印地语或世界语

举个例子,下面是我的英语和德语版本的Localizable.strings的第一行:

英语

//LocalizeHelper.h

#import <Foundation/Foundation.h>

// some macros (optional, but makes life easy)

// Use "LocalizedString(key)" the same way you would use "NSLocalizedString(key,comment)"
#define LocalizedString(key) [[LocalizeHelper sharedLocalSystem] localizedStringForKey:(key)]

// "language" can be (for american english): "en", "en-US", "english". Analogous for other languages.
#define LocalizationSetLanguage(language) [[LocalizeHelper sharedLocalSystem] setLanguage:(language)]

@interface LocalizeHelper : NSObject

// a singleton:
+ (LocalizeHelper*) sharedLocalSystem;

// this gets the string localized:
- (NSString*) localizedStringForKey:(NSString*) key;

//set a new language:
- (void) setLanguage:(NSString*) lang;              

@end
/* English - English */

/* for debugging */
"languageOfBundle" = "English - English";

/* Header-Title of the Table displaying all lists and projects */
"summary" = "Summary";

/* Section-Titles in table "summary" */
"help" = "Help";
"lists" = "Lists";
"projects" = "Projects";
"listTemplates" = "List Templates";
"projectTemplates" = "Project Templates";
德语

/* German - Deutsch */

/* for debugging */
"languageOfBundle" = "German - Deutsch";

/* Header-Title of the Table displaying all lists and projects */
"summary" = "Überblick";

/* Section-Titles in table "summary" */
"help" = "Hilfe";
"lists" = "Listen";
"projects" = "Projekte";
"listTemplates" = "Vorlagen für Listen";
"projectTemplates" = "Vorlagen für Projekte";

要使用本地化,必须在应用程序中以及在调用宏的语言选择中设置一些例程:

LocalizationSetLanguage(selectedLanguage);
在这之后,你必须记住,所有用旧语言显示的内容现在都会用新语言重新绘制(隐藏的文本一旦再次可见,就必须重新绘制)

要使本地化文本适用于各种情况,您永远不必向对象标题中写入修复文本。始终使用宏
本地化字符串(关键字)

不要:

cell.textLabel.text = @"nice title";
cell.textLabel.text = LocalizedString(@"nice title");
do:

cell.textLabel.text = @"nice title";
cell.textLabel.text = LocalizedString(@"nice title");

并且在每个版本的Localizable.strings中都有一个“好标题”条目

这里有一个准备使用的关于如何在Swift 3中使用Novarg方法的逐步指南:


步骤1:实现语言选择器 如何最好地做到这一点取决于您,并取决于项目。但是使用

Bundle.main.localizations.filter({ $0 != "Base" }) // => ["en", "de", "tr"]
以编程方式获取所有受支持地区的列表。你也可以使用

Locale.current.localizedString(forLanguageCode: "en") // replace "en" with your variable
在应用程序当前语言中显示语言名称

作为一个完整的示例,单击如下按钮后,您可以显示一张popover操作表:

@IBOutlet var changeLanguageButton: UIButton!

@IBAction func didPressChangeLanguageButton() {
    let message = "Change language of this app including its content."
    let sheetCtrl = UIAlertController(title: "Choose language", message: message, preferredStyle: .actionSheet)

    for languageCode in Bundle.main.localizations.filter({ $0 != "Base" }) {
        let langName = Locale.current.localizedString(forLanguageCode: languageCode)
        let action = UIAlertAction(title: langName, style: .default) { _ in
            self.changeToLanguage(languageCode) // see step #2
        }
        sheetCtrl.addAction(action)
    }

    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    sheetCtrl.addAction(cancelAction)

    sheetCtrl.popoverPresentationController?.sourceView = self.view
    sheetCtrl.popoverPresentationController?.sourceRect = self.changeLanguageButton.frame
    present(sheetCtrl, animated: true, completion: nil)
}

步骤#2:解释用户要做什么+重新启动时更改语言 您可能已经注意到,步骤1中的代码调用了一个名为
changetolaguage(langCode:)
的方法。无论您如何设计选择器,当用户选择要更改的新语言时,这也是您应该做的。这是它的实现,只需将它复制到您的项目中即可:

private func changeToLanguage(_ langCode: String) {
    if Bundle.main.preferredLocalizations.first != langCode {
        let message = "In order to change the language, the App must be closed and reopened by you."
        let confirmAlertCtrl = UIAlertController(title: "App restart required", message: message, preferredStyle: .alert)

        let confirmAction = UIAlertAction(title: "Close now", style: .destructive) { _ in
            UserDefaults.standard.set([langCode], forKey: "AppleLanguages")
            UserDefaults.standard.synchronize()
            exit(EXIT_SUCCESS)
        }
        confirmAlertCtrl.addAction(confirmAction)

        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
        confirmAlertCtrl.addAction(cancelAction)

        present(confirmAlertCtrl, animated: true, completion: nil)
    }
}
这将询问并告知用户是否要进行更改以及如何进行更改。此外,它还可以在下一次启动时使用以下设置应用程序语言:

UserDefaults.standard.set([langCode], forKey: "AppleLanguages")
UserDefaults.standard.synchronize() // required on real device

步骤#3(可选):本地化字符串 您可能希望使用
NSLocalizedString
宏(或任何其他增强方法)对字符串进行本地化,如“立即关闭”


现实世界的例子
我正在一个针对iOS 10的应用程序中使用这个精确的实现,我可以确认它在模拟器和设备上对我都有效。该应用程序实际上是开源的,因此您可以找到分布在不同类中的上述代码。

其语言非常简单且易于更改