复数形式与 Stringsdict
处理不同语言的复数规则。
复数形式与 Stringsdict 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
复数问题
英语有两种形式——1 item、2 items——因此开发人员经常编写 "\(n) item" + (n == 1 ? "" : "s")。这种做法会严重出错:阿拉伯语有六种复数类别,俄语有三种,日语只有一种。硬编码复数逻辑是一个随时可能出现的本地化错误。
// FRAGILE — only works for English
let n = 5
let bad = "\(n) item" + (n == 1 ? "" : "s")
print(bad)复数类别
Unicode 定义了复数类别:零、单个、两个、少量、多量、其他。每种语言使用其中一部分。系统会根据区域设置规则为数字选择正确的类别,您无需自己编写这些规则。
// English uses: one, other
// Russian uses: one, few, many, other
// Japanese uses: other (only)
// You provide a variant string per category needed.字符串目录中的复数变体
在字符串目录中,您可以将字符串标记为具有复数变体。随后,Xcode 允许您为每个类别提供文本。运行时,系统会根据插入的计数和用户的区域设置自动选择正确的变体。
// Catalog entry, key "message_count":
// one: "You have %lld message"
// other: "You have %lld messages"
let count = 1
let text = String(localized: "You have \(count) messages")
print(text)旧版 .stringsdict
在字符串目录出现之前,复数内容存放在 .stringsdict 文件中——这是一个将 key 映射到格式字符串及各类别变体的属性列表。您仍会在较旧的项目中看到这类文件,而且它们仍受到完整支持。
// Localizable.stringsdict (plist) structure:
// key: "items_count"
// NSStringLocalizedFormatKey: "%#@items@"
// items: NSStringPluralRuleType
// one: "%lld item"
// other: "%lld items"stringsdict 条目的结构
每个条目都有一个格式 key,用于引用一个或多个包裹在 %#@name@ 中的命名变量。每个变量都会声明其规则类型(NSStringPluralRuleType)、值类型说明符(%lld),以及每个复数类别对应的字符串。
// The %#@items@ token expands to the chosen
// plural variant. %lld is the integer placeholder
// substituted inside each variant string.
let n = 3
print(String(localized: "\(n) items selected"))查找复数化字符串
从代码来看,调用位置与任何本地化字符串完全相同,只需插入计数即可。复数选择由框架内部完成,因此同一行 Swift 代码可以适用于每种语言。
func messagesLabel(_ count: Int) -> String {
return String(localized: "You have \(count) messages")
}
print(messagesLabel(0))
print(messagesLabel(1))
print(messagesLabel(7))为什么“一”不只是 1
一个常见错误是认为一类别只表示数字 1。在某些语言中,它涵盖所有以 1 结尾的数字(例如 21、31),而零可能有独立的类别,也可能没有。请始终为每个类别提供文本,并让规则决定使用哪一个。
// Russian: 1, 21, 31 -> 'one'
// 2, 3, 4 -> 'few'
// 5..20, 0 -> 'many'
// Never assume one == 1.将复数与其他值结合
一个格式可以包含多个变量,例如计数和姓名。每个变量都可以独立进行复数化。在字符串目录中,您可以标记哪个插值会变化,其余部分会在所有变体中保持不变。
let files = 2
let folder = "Photos"
let text = String(
localized: "\(files) files in \(folder)")
// 'files' drives the plural; 'folder' is substituted as-is
print(text)宽度和设备变体
同一目录机制也支持设备和宽度变体,因此您可以在手表上显示较短的标签,在 iPad 上显示较长的标签,或在空间狭窄时使用缩写。这些变体可以与复数变体配合使用。
// Catalog can vary by:
// plural: one / other
// device: iPhone / iPad / watch
// width: short / medium / long
let label = String(localized: "Notifications")
print(label)测试复数化
要验证变体,请使用 Xcode 的方案本地化覆盖,在每种目标语言中运行应用;或者使用伪语言和按 locale 划分的预览。请重点检查边界数字:0、1、2、5、11、21、100。
let samples = [0, 1, 2, 5, 11, 21, 100]
for n in samples {
print(String(localized: "\(n) items"))
}最佳实践
为了正确处理复数:
- 不要拼接或硬编码
s后缀。 - 提供目标语言所需的每个类别。
- 从插值整数驱动复数选择,而不是使用预先计算的字符串。
- 新代码应优先使用字符串目录;仅为旧版目标保留
.stringsdict。
func cartSummary(_ items: Int) -> String {
String(localized: "Your cart has \(items) items",
comment: "Cart count; pluralized")
}
print(cartSummary(1))快速检查
回顾应该如何处理复数选择。
回顾
您学会了符合 locale 规则的复数化:
- Unicode 复数类别包括零、一、二、少量、多量、其他;每种语言使用其中的一个子集。
- 字符串目录允许您为每个键添加复数变体;旧版
.stringsdict通过 plist 实现相同功能。 - 调用位置保持简单:插入计数,然后由框架选择变体。
- 不要硬编码复数逻辑;一类别并不只是数字 1。
常见问题解答
「复数形式与 Stringsdict」课时是免费的吗?
是的 — 「复数形式与 Stringsdict」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「复数形式与 Stringsdict」这节课中我会学到什么?
处理不同语言的复数规则。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「复数形式与 Stringsdict」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 字符串目录与本地化字符串
- 复数形式与 Stringsdict
- 区域设置感知的格式化
- 从右到左与布局方向