In short
与货币相关的区域设置有两种:
-
依赖货币: 这些都与货币价值仅取决于货币,并且无论您在何处使用该货币,都保持有效。这只是国际 ISO 代码和小数位数,定义为ISO 4217.
-
文化背景:这些取决于与语言和国家/地区相关的用法和实践users而不是直接兑换成货币。通常,它是货币代码或符号相对于值的位置,以及小数点和千位分隔符。
幸运的是,Swift 很好地改变了这一点。这里有一些代码,允许您调整货币相关设置,而无需触及对用户重要的文化设置。我还将解释为什么您不应该更改所有本地设置。
The code
这是演示代码,其中包含几种代表性货币:
let value: Double = 1345.23
for mycur in ["USD", "TND", "EUR", "JPY" ] {
let myformatter = NumberFormatter()
myformatter.numberStyle = .currencyISOCode
let newLocale = "\(Locale.current.identifier)@currency=\(mycur)" // this is it!
myformatter.locale = Locale(identifier:newLocale)
print ("currency:\(mycur): min:\(myformatter.minimumFractionDigits) max:\(myformatter.maximumFractionDigits)"
print ("result: \(myformatter.string(from: value as NSNumber) ?? "xxx")")
}
对于代表性演示,我使用了:
- 美元和欧元,与大多数货币一样,可以分为 100 个子单位(美分),
- the TND(突尼斯第纳尔),与少数其他第纳尔货币一样,可以分为 1000 个子单位(磨坊),
- the JPY(日元),过去可以分为价值很小的子单位(Sens),以至于日本政府决定不再使用它们。这就是为什么日元金额不再有小数的原因。
结果
对于用户来说,将受益于最小惊讶原则,并查看小数点和千位分隔符以及他/她习惯的定位。
在我当前的语言环境中(在我的语言中,货币代码位于右侧,小数点用逗号分隔,千位用硬空格分隔)结果将是:
cur:USD: min:2 max:2 result: 1 345,23 USD
cur:TND: min:3 max:3 result: 1 345,230 TND
cur:EUR: min:2 max:2 result: 1 345,23 EUR
cur:JPY: min:0 max:0 result: 1 345 JPY
但如果您通常在英语环境中工作,例如在美国文化中,您会得到:
cur:USD: min:2 max:2 result: USD 1,345.23
cur:TND: min:3 max:3 result: TND 1,345.230
cur:EUR: min:2 max:2 result: EUR 1,345.23
cur:JPY: min:0 max:0 result: JPY 1,345
怎么运行的:
该代码的技巧是创建一个新的区域设置,只需更改货币设置,但保留所有其他国家和语言相关参数不变。
let newLocale = "\(Locale.current.identifier)@currency=\(mycur)" // this is it!
myformatter.locale = Locale(identifier:newLocale)
为什么你不应该完全实现你想要的
如果您开始调整定位以采用货币来源国语言的做法,您可能会激怒用户,他们不再在他们期望的位置看到货币代码。幸运的是,它不会造成真正的混乱。
示例:欧元是文化截然不同的国家的货币。因此,有关货币或货币符号定位的规则被定义为取决于金额出现的文本语言。官方参考
现在,如果你想开始采用千位和小数分隔符另一种语言或国家的货币,因为它是货币的母国,这会造成真正的混乱,特别是对于较小的金额。而且,这并不总是可能的。
示例:在加拿大,相同的货币金额由讲法语的加拿大人使用逗号小数分隔符书写,但由讲英语的加拿大人使用点小数分隔符书写。这清楚地表明,决定使用分隔符的不是货币,而是用户的语言。
因此,您应该尊重用户在这方面的设置,并且仅调整特定于货币的设置。