排除代用码点是否也会妨碍输入汉字?

Will precluding surrogate code points also impede entering Chinese characters?

我在应用程序中有一个名称输入字段,想阻止用户输入表情符号。我的想法是过滤掉 Unicode 规范中一般类别 "Cs" 和 "So" 中的任何字符,因为这将防止大量不适当的字符,但允许大多数字符用于编写自然语言。

但在阅读规范后,我不确定这是否会阻止例如拼音键盘提交需要补充代码点的汉字。 (我的理解还很粗糙。)

排除代理人后,大多数中国用户是否仍会保留他们输入姓名所需的字符,或者原始 Unicode space 不够大,不足以成为合理的期望?

Will precluding surrogate code points also impede entering Chinese characters? […] if this would preclude, for example, a Pinyin keyboard from submitting Chinese characters that need supplemental code points.

您无法拦截字符的输入方式,无论是通过输入法编辑器、复制粘贴还是其他多种方式。您只能在字符完成(并且 IME 的工作已完成)或取决于小部件工具包时才能看到字符,即使只有在提交文本之后。这给你留下了验证。让我们考虑一个现实的案例。来自 Unihan_Readings.txt 12.0.0 (2018-11-09):

U+20009 ‹› (the same as U+4E18 丘) a hill; elder; empty; a name
U+22218 ‹› variant of 鹿 U+9E7F, a deer; surname
U+22489 ‹› a surname
U+224B9 ‹› surname
U+25874 ‹› surname

假设用户输入 ,然后你的未命名 - 但希望 Unicode 兼容 - 编程语言 必须 考虑字素级别(1 个字素簇)或字符级别(1 个字符),而不是代码单元级别(代理项对 0xD840 0xDC09)。这意味着可以排除带有 Cs 属性.

的字符

你的方法既无效又过度。

并非所有表情符号都在基本多语言平面之外(因此首先不需要代理),并且并非所有表情符号都属于一般类别 So。仅过滤掉这两组字符将完整保留以下表情符号:

#️⃣ *️⃣ 0️⃣ 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ ‼️ ⁉️ ℹ️ ↔️ ◼️ ◻️ ◾️ ◽️ ⤴️ 1️⃣ ][⤵️

同时,这种方法还将排除大约 79,000 个(还在增加)非表情符号字符,涵盖几十个脚本——其中许多是历史性的,但有些具有活跃的用户社区。例如,大多数汉(中文)字符都是在 BMP 之外编码的。虽然其中大部分仅具有学术意义,但无论如何 尤其是 当您处理个人姓名时,您都需要支持它们。您永远不会知道您的用户名可能有多么不常见。

整个考验还取决于您应用的技术细节。仅当您使用的框架以实际使用代理项的格式(即 UTF-16 编码字符串时,如果您的框架同时不知道 UTF- 16 确实有效(例如 Java 或 JavaScript)。代理人 永远不会 被视为实际角色;它们是特别保留的代码点,其存在的唯一目的是允许 UTF-16 处理更高平面中的字符。其他 Unicode 编码甚至根本不允许使用它们。

如果您的应用程序使用的语言使用不同的编码(如 UTF-8 或足够智能以正确处理代理项),则删除输入中的 Cs 个字符永远不会有任何效果,因为没有任何代理人会接触到您的程序。用户如何输入这些字符并不重要,因为您的应用程序只能看到成品(实际字符代码点)。

如果您的目标是删除所有 表情符号和 表情符号,那么您将不得不投入大量精力来设计您的表情符号代码,因为 Unicode 表情符号规范非常复杂。现在大多数表情符号都是由多个字符构成的,并不是所有的字符都被单独归类为表情符号。除了维护每个官方表情符号的明确列表之外,没有简单的方法可以从字符串中过滤出表情符号,这需要不断更新。