问题描述
iOS 15 新增了英语和西班牙语的语法协议功能。例如,我应该可以说
You have x apple.
如果 x
是 1,那么“apple”就是“apple”,但是如果 x
大于 1,那么“apple”就会神奇地变成“apples”。
这听起来是摆脱所有代码的好方法,因为我自己正在查看数字并在硬编码的单数和复数选项之间进行选择。
但是,在我看来,此功能仅适用于 localized 应用程序,并且仅适用于 UIKit 中的 attributed 字符串。 (SwiftUI 是不同的,因为字符串是自动本地化的。)对于普通的面向用户的字符串,我该如何做到这一点?
解决方法
您必须使用本地化的属性字符串才能获得此功能。但这并不意味着您提供的字符串必须进行本地化或属性化!
这是一个例子。在某些时候,我们可能会这样说:
let count = 1
let output = String(AttributedString(
localized:"You have ^[\(count) \("apple")](inflect: true).").characters)
print(output) // You have 1 apple.
现在想象一下,在其他时候,我们这样说:
let count = 2
let output = String(AttributedString(
localized:"You have ^[\(count) \("apple")](inflect: true).").characters)
print(output) // You have 2 apples.
请注意,我的属性字符串在两者中是相同的。然而,根据 count
值,运行时已根据需要将“apple”更改为“apples”。这正是我们想要的。
据我所知,这就是交易。
-
您必须使用属性字符串,并且必须将其声明为本地化(在 UIKit 中)。
-
一旦你这样做了,你就可以使用 Markdown。您确实使用 Markdown,使用 Apple 设计的特殊自定义属性语法。通过这种方式,字符串的变形区域对运行时可见。
-
所有相关内容都必须包含在方括号部分中,并且必须使用字符串插值进行标记,如我在此处所示。在这种情况下,“一切相关”是计数数字和名词。使用单数作为名词;如果使用复数,则不会向下变形为单数,如果使用单数,则会向上变形为复数。
-
字符串本身必须是文字才能获得特殊的插值规则;特别是,它必须输入为 StringLocalizationKey。我可以这样构造字符串:
let count = 2 let s : StringLocalizationKey = "You have ^[\(count) \("apple")](inflect: true)."
这为您提供了自动屈折。然后,在本例中,因为我只想要字符串,所以我通过属性字符串的 characters
视图并将其强制转换为字符串。
请注意,我的应用并未在任何有意义的意义上进行本地化。我没有为应用声明其他语言,也没有 .strings 文件或 .stringsDict 文件。我只是通过 localized:
构造函数,因为这是您访问此功能的方式。