利用英文字符串的 iOS 15 语法协议功能

Taking advantage of the iOS 15 grammar agreement feature for English strings

iOS15 中的新增功能是英语和西班牙语的语法一致功能。例如,我应该可以说

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: 构造函数,因为这是您访问此功能的方式。