本地化 API 数据的自然格式列表

Localizing a naturally-formatted list of API data

假设我从 API:

下载了这个数据列表
[
    "Anita",
    "Jean",
    "Peter"
]

我想以自然句子格式列出这些数据。例如,在美国英语中,这个字符串应该显示给用户:

Anita, Jean, and Peter

但是,如果用户是瑞典人,他们应该看到这个字符串:

Anita, Jean och Peter

请注意,牛津逗号丢失了,而瑞典语对 "and" 使用了不同的词,这正是瑞典用户希望看到的。如何以尊重用户所在地的自然语言方式格式化这些数据?可以有可变数量的数据,不一定只有 3 个项目。我的本能是继承 Formatter/NSFormatter,但我想以一种可以轻松扩展它以支持我不会说的语言的方式构建它,所以我想知道是否有我无法在搜索中找到的 iOS-标准或第 3 方格式化程序

在 iOS 的早期版本中,此问题仍未解决,如果您有答案,我将不胜感激。然而,iOS 13 公开了 NSListFormatter,它可以用来做这件事。例如:

Swift:

ListFormatter().localizedString(byJoining: ["Anita", "Jean", "Peter"])

Objective-C:

[[NSListFormatter new] localizedStringByJoiningStrings:@["Anita", "Jean", "Peter"]];

从 iOS 13 开始,Foundation 有一个 ListFormatter 类型。根据您的需要,您可以以不同的方式使用它来获取数组的文本表示。


使用ListFormatter最简单的方法是使用它的静态localizedString(byJoining:)方法。以下 Swift 5.1 / iOS 13 Playground 示例代码显示了如何实现此方法以将数组转换为本地化字符串表示形式:

import Foundation

let array = [
    "Anita",
    "Jean",
    "Peter"
]

let string = ListFormatter.localizedString(byJoining: array)
print(string) // prints: Anita, Jean, and Peter (for en_US locale)

作为 localizedString(byJoining:) 的替代方法,您可以创建 ListFormatter 的实例并使用 string(from:) 方法。如果您需要为文本表示指定语言环境,这会很有用:

import Foundation

let array = [
    "Anita",
    "Jean",
    "Peter"
]

let listFormatter = ListFormatter()
listFormatter.locale = Locale(identifier: "fr_FR") // set only if necessary

let string = listFormatter.string(from: array)
print(String(describing: string)) // prints: Optional("Anita, Jean et Peter")

如果需要,您还可以使用专门的格式化程序类型设置 ListFormatter 实例的 itemFormatter 属性:

import Foundation

let array = [
    55,
    112,
    8
]

let locale = Locale(identifier: "es_ES") // set only if necessary

let numberFormatter = NumberFormatter()
numberFormatter.locale = locale
numberFormatter.numberStyle = NumberFormatter.Style.spellOut

let listFormatter = ListFormatter()
listFormatter.locale = locale
listFormatter.itemFormatter = numberFormatter

let string = listFormatter.string(from: array)
print(String(describing: string)) // prints: Optional("cincuenta y cinco, ciento doce y ocho")