在PHP中根据W3C规范Unicode

在W3C validator中验证我的网站的HTML代码时,收到以下警告:

Line 157, Column 220: Text run is not in Unicode Normalization Form C.

…i͈̭̋ͥ̂̿̄̋̆ͣv̜̺̋̽͛̉͐̀͌̚e͖̼̱ͣ̓ͫ͆̍̄̍͘-̩̬̰̮̯͇̯͆̌ͨ́͌ṁ̸͖̹͎̱̙̱͟͡i̷̡͌͂͏̘̭̥̯̟n̏͐͌̑̄̃͘͞…

我在PHP 5.3.x中开发它,所以我可以使用Normalizer类。

因此,为了解决此问题,我应该在显示用户输入(例如评论)时使用Normalizer::normalize($output),还是在将其存储到数据库之前对任何用户输入使用Normalizer::normalize($input)

tl;dr:应该在将用户输入存储到数据库之前使用Unicode normalization还是只在显示时使用?


解决方案

您可以根据应用程序的用途和性质来决定是在读取用户输入时应用规范化,还是将其存储到数据库中,还是在写入输入时应用规范化。要总结对问题的评论中提到的长线索,也可以在官方清单档案中找到http://validator.w3.org/feedback.html

  • 警告消息来自实验性的"HTML5验证"(这实际上是一个临界点,除了一些正式的测试外,还应用主观规则)。
  • 此消息不是基于HTML5草案中的任何要求,而是基于对某些软件中可能导致问题的原因的意见。
  • 该意见最初使"HTML5验证"发出错误消息,现在是警告。
获取非标准化数据作为用户输入当然是可能的,尽管这并不常见。这不依赖于浏览器执行的标准化(它们不做这样的事情,尽管可以想象它们将来可能会这样做),而是依赖于输入方法和习惯。例如,输入字母ü的方法(u元音,或u加分音符)往往会生成标准形式的预先拼写的字符。人们可以将其生成为非标准化的分解形式,如字母u后跟组合分音符,但他们通常没有理由这样做,而且大多数人甚至不知道如何做到这一点。

如果您在软件中进行字符串比较,它们可能会也可能不会(取决于使用的比较例程)将预先合成的ü视为等于分解后的表示。简单的实现将它们视为不同,因为它们在简单字符级别(Unicode代码点)上是完全不同的。

在某个时刻(最晚在书写阶段)进行标准化的一个原因是,预先编写的字符通常可以更可靠地显示。要呈现标准化ü,程序只需从字体中提取字形即可。要呈现分解的ü,程序必须要么将其识别为规范等同于标准化ü,要么在字母u的上方适当放置一个分音符,并适当注意u字形的图形属性,而许多程序在这方面做不到。

另一方面,在极少数情况下,非标准化数据被接收为用户输入,用户很可能有理由生成这些数据。他可能认为标准化ü和非标准化ü是不同的,需要这样对待。

相关文章