当前区域设置在设备上报告错误的语言

18

我正在尝试在iOS应用程序中格式化货币值,并且我正在使用设备上的当前区域设置来使用适当的货币格式。

在模拟器中,一切似乎都运行良好:当使用currencyFormatter.locale = Locale.current时,它采用正确的区域设置并以正确的货币格式打印数字。

但是,在我的iPhone上,它配置为使用法语和法语区域设置,我希望使用另一种格式(例如:1 234,56 €)。但它不起作用,似乎使用英语格式样式(例如:€1 234,56)。

事实上,如果我从我的应用程序在设备上打印当前区域设置,它不会返回我期望的fr_FR:

NSLog(Locale.current.identifier)
>>> en_FR

这个地区不错,但语言不好,虽然设备上的 iOS 明显是法语。

有人有关于这个的想法吗?

谢谢!


3
你的应用有法语本地化吗?否则会使用英语作为备选语言。 - Martin R
它没有这样做,但我本来希望能够在用户的区域设置中打印货币数字,而无需为每种语言提供本地化。这可能吗? - Romain
5
例如,请参考 https://dev59.com/5HA75IYBdhLWcg3wfpKr#3328809: "回退语言是用户在设备设置中最近选择的语言,而且也在应用程序包中表示。" - Martin R
谢谢,实际上,Locale.current 返回的语言代码并不一定代表设备当前的语言,而是应用程序支持的第一种语言或回退语言... 我想我必须使用另一种方法来实现我想要的功能。 - Romain
4
细节在这里:https://developer.apple.com/library/content/qa/qa1828/_index.html - 我“推测”意图是提供一致的用户界面,即不像“最后更新:2010年12月22日”这样的内容。 - Martin R
9个回答

36
基于@Romain的答案,可以通过使用Locale.current.identifier作为后备方式来避免强制解包first!
func getPreferredLocale() -> Locale {
    guard let preferredIdentifier = Locale.preferredLanguages.first else {
        return Locale.current
    }
    return Locale(identifier: preferredIdentifier)
}

1
你说得对,那样更安全。将其标记为正确答案! - Romain
3
你好!你找到解决问题的好方法了吗?我也遇到了相同的问题,当使用Locale.preferredLanguages [0]或Locale.current.identifier时,它会返回“en”,但我的手机是设置成法语的。这只在一个应用程序中发生,其他应用程序都返回预期的“fr”。 - Michel
还有一件事可以尝试!请看下面我的帖子 :) - multitudes
我应用了这个答案来展示应用小部件中的正确语言环境。谢谢! - smukamuka
聪明的想法,这正是我寻找的。 - Coder ACJHP

16

@Romain 这里的问题在于你的应用程序并没有为法语进行本地化,而只是针对英语。

进入左上角带有您的应用程序名称的蓝色文件,选择“项目” > “信息”,在“本地化”区域中,您将看到“英语 - 开发语言”。 点击“+”并选择法语(fr)。

就是这样。 现在,您可以使用Locale.current,如果设备(或模拟器)的首选语言是法语,则您的应用程序将显示法国货币格式。


谢谢!这解释了我一开始认为是错误的行为。 - Kirill
1
这个答案必须被标记为解决方案。 但是我有一个评论:它只在您拥有一个或多个本地化资源的情况下才有效,例如Localizable.strings或其他可本地化的内容。 - Sound Blaster

8

@florieger的答案是一个扩展:

import Foundation

extension Locale {
    static func preferredLocale() -> Locale {
        guard let preferredIdentifier = Locale.preferredLanguages.first else {
            return Locale.current
        }
        return Locale(identifier: preferredIdentifier)
    }
}

然后像这样使用它:
dateFormatter.locale = Locale.preferredLocale()
datePicker.locale = Locale.preferredLocale()

7

如果其他方法都失败了

我花了一个小时进行调试。我在德国,我的iPhone语言设置为英语,地区设置为德国。

我正在调试一个应用程序,该应用程序从iPhone中获取语言环境,并将其作为标头传递到服务器的API调用中。我想知道为什么我总是得到所有数据字符串都是德语。检查应用程序后发现一切都做得正确:

    if let deviceLanguageCode = Locale.current.languageCode,
    deviceRegionCode = Locale.current.regionCode {
        // do stuff here
    }

上面的变量deviceLanguageCode始终返回de,但应该是"en"!我尝试了一切。我使用了Locale.autoupdatingCurrent.languageCodeLocale.preferredLanguages.first等,但都不起作用。我检查了我的项目设置,我的Localizable.strings文件,都没有问题。如果我创建一个新的Xcode项目并打印这些变量,我会得到正确的语言环境和区域:en_DE
这太令人恼火了!只有当我尝试了所有可能性后,我才阅读了Paul Hudson的post(还有谁?)在文章末尾,他给出了一个测试本地化的提示:

提示:您可以通过转到“产品”菜单,按住Alt键,然后选择“运行...”来在语言之间切换。查看“选项”选项卡,您将看到应用程序语言默认设置为系统语言,但您可以在此更改以进行测试。

并且... 'quelle horreur!' 有人在我之前已经将应用程序的语言和地区设置为德国!!! 难怪我遇到了困难!

故事结束:确保这些设置为系统,否则什么都不会起作用 ;)

enter image description here


2

在@MartinR的提示下,我现在使用currencyFormatter.locale = Locale(identifier: Locale.preferredLanguages.first!),这与设备当前的语言和地区设置完全对应。

我不确定这段代码是否完全可靠(尤其是因为first!),如果您有其他建议,请随意提出。


0
如果您想根据用户地区和语言环境获取当前语言,请使用以下代码:

Locale.current.languageCode

但是如果你想要设置当前语言,请使用以下代码:

Locale.preferredLanguages.first

0

使用此代码从获取当前系统语言代码

let pre = Locale.preferredLanguages[0]

如果你仍然面临这个问题,可能是因为你使用了错误的语言代码。请从UserDefaults中删除"AppleLanguages"对象,并使用相同的代码Locale.preferredLanguages[0]

供参考

func getSystemLanguageCode() -> String {
    UserDefaults.standard.removeObject(forKey: "AppleLanguages")
    let pref_Language = NSLocale.preferredLanguages[0] as String //"fr-IN"
    let language = pref_Language.components(separatedBy: "-") //["fr","IN"]
    let lang_Code = language.first?.lowercased() ?? "" //"fr"
    UserDefaults.standard.set([lang_Code], forKey: "AppleLanguages")
    
    return lang_Code
}

0

摘要

苹果公司期望当开发者决定支持本地化时,项目应该有可本地化的资源,如字符串或故事板,以提供一致的用户界面(例如不仅仅是以本地格式打印货币),在这种情况下使用 Locale.current 是适当的选择,并且对于支持的本地化工作得很好(正如this answer所述)。

然而,在像 @Romain 的情况下:

"我希望能够在用户的区域设置中打印货币数字,而无需为每种语言提供本地化"

实现此目的的解决方法是使用 Locale.preferredLanguages.first,并在出现 null 的情况下进行回退(正如this answer所述)。


-1
当小部件应该与应用程序具有相同的语言,而 iPhone 的语言不同时,您可以使用这个:

func getPreferredLocale() -> Locale {
    guard let preferredIdentifier = Bundle.main.preferredLocalizations.first else {
        return Locale.current
    }
    return Locale(identifier: preferredIdentifier)
}

Bundle.main.preferredLocalizations.first 返回您的应用支持的本地化,而不是用户设备的首选项... 例如,如果您的应用程序有英语和法语的翻译,但您的设备是中文的,则它将返回“en”... - Aure77

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接