文本不含数字时,如何正确本地化并复数化Swift字符串?
无数字场景下的字符串本地化与复数化解决方案
问题背景
我们需要实现列表表头根据条目数量,显示符合本地化复数规则的字符串(比如无数字的「Chief-of-staff」或「Chiefs-of-staff」)。已知带数字的场景可以通过AttributedString的inflect: true直接实现复数化:
var count = 3 AttributedString(localized: "^[\(count) Chief-of-staff](inflect: true)") // 输出:"3 Chiefs-of-staff"
但无数字时,现有两种尝试都存在缺陷:
- 手动扩展
Morphology的方式:仅支持单复数两种形式,无法适配俄语、阿拉伯语等有pluralTwo、pluralFew等多复数规则的语言,因为复数判断逻辑硬编码,不遵循本地化规则。 - 生成带数字字符串再移除数字的方式:属于临时 hack,存在数字格式本地化后匹配失败的风险,不够稳健。
简洁且稳健的解决方案
利用系统本地化字符串字典(.stringsdict)定义复数规则,结合AttributedString的本地化选项关联计数概念,直接生成符合要求的无数字复数字符串。
步骤1:定义本地化复数规则
在项目的Localizable.stringsdict文件中添加对应键的复数配置(以英语为例,其他语言可按各自规则扩展):
<dict> <key>chiefOfStaffHeader</key> <dict> <key>NSStringLocalizedFormatKey</key> <string>%#@COUNT@</string> <key>COUNT</key> <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> <key>NSStringFormatValueTypeKey</key> <string>d</string> <key>one</key> <string>Chief-of-staff</string> <key>other</key> <string>Chiefs-of-staff</string> </dict> </dict> </dict>
步骤2:代码中关联计数并生成字符串
通过LocalizedStringResource引用字典中的键,同时在本地化选项中传入计数概念,让系统自动处理复数化:
func staffListHeader(for count: Int) -> AttributedString { let resource = LocalizedStringResource( "chiefOfStaffHeader", defaultValue: "^[Chief-of-staff](agreeWithConcept: 1)", comment: "Header for staff list based on item count" ) var localizationOptions = AttributedString.LocalizationOptions() localizationOptions.concepts = [.count(count)] return AttributedString(localized: resource, options: localizationOptions) } // 使用示例 let multipleHeader = staffListHeader(for: 5) // 输出:"Chiefs-of-staff" let singleHeader = staffListHeader(for: 1) // 输出:"Chief-of-staff"
方案优势
- 完全适配本地化规则:自动遵循目标语言的复数规则,包括多复数形式的语言,无需手动判断计数。
- 简洁稳健:直接生成无数字的目标字符串,无需后续字符串修改操作,避免hack带来的潜在问题。
内容的提问来源于stack exchange,提问作者AndrewC
相关产品推荐
相关产品推荐

