使用 Unicode 提交表单时如何避免浏览器 Unicode 规范化



当以HTML格式呈现以下Unicode文本时,事实证明浏览器(Google Chrome)在将数据发布回服务器时会进行某种形式的Unicode规范化。(可能在表格C中)。

但是当使用圣经希伯来语(בְּרִיכְ ׾וּא)文本时,这很容易破坏文本,正如这里(第9页)所概述的那样。

有没有办法避免浏览器自动文本规范化?

写了一篇博客文章,更详细地描述了我面临的问题:http://blog.hibernatingrhinos.com/12449/would-it-be-possible-to-have-a-web-browser-based-editor-for-an-hebrew-text

这似乎是WebKit浏览器(Chrome,Safari)中的一个功能/错误;它们将表单数据规范化为NFC,这意味着,除其他外,将连续的组合标记重新排序为"规范"顺序。这对我来说是新的,在这样的情况下也是坏消息。最糟糕的是,不同的浏览器行为不同。

使用测试用例 http://blog.hibernatingrhinos.com/12449/would-it-be-possible-to-have-a-web-browser-based-editor-for-an-hebrew-text 的简化版本(使用仅回显原始数据的服务器端脚本),我注意到Chrome和Safari在U + 05E9 U + 05C1 U + 05B5(SHIN,SHIN DOT,TSERE)中重新排序变音符号,而IE,Firefox和Opera则没有。

我还用拉丁字母e进行了一个简单的测试,然后组合了diaeresis U + 0308。WebKit 浏览器根据 NFC 规则将其转换为单个字符 ë,而其他浏览器则保持字符对不变。

自 2006 年以来,这似乎是一个有意为之的功能; https://bugs.webkit.org/show_bug.cgi?id=8769 自豪地宣布这是错误修复的一部分!这可以解释 W3C 策略文档的状态;它的当前版本在这个问题上是WebKit的,但其他浏览器供应商要么不感兴趣,要么故意反对"早期规范化"的想法。

我认为没有办法防止这种情况。但是您可以警告用户不要使用Chrome和Safari。您甚至可以使用包含简单问题案例的隐藏字段,然后检查服务器端是否按原样传输,如果不是,则告诉用户更改浏览器。

在服务器端修复订单并不简单,因为常见的规范化例程显然不支持所需的顺序。您可以规范化为完全分解形式 (NFD),然后为此目的使用您自己的代码对组合标记进行重新排序。也许更简单、更安全,您可以运行一个临时替换例程,将组合标记的序列替换为其他序列。这会更安全,因为它不会影响您想要影响的字符以外的字符,而 NFD 会用变音符号分解拉丁字母等。

根据 Unicode 原则,规范等效字符串(例如,仅在连续变音符号的顺序上有所不同)是相同数据的不同表示形式,但与 Unicode 字符序列(码位)不同;它们在表示上不会有所不同,但它们可能而且经常如此。通常,您不应期望程序将规范等效的字符串视为不同的字符串,尽管程序可能会有所不同。请参阅 Unicode 规范化常见问题解答。

FAQ条目声称圣经希伯来语的问题已经通过引入COMBINED GRAPHEME JOINER来解决。虽然它可以防止在Chrome中重新排序,但它是一种笨拙的方法,并且可能会弄乱渲染(在Web浏览器中确实如此;变音符号可能会严重放错位置)。

可以通过发送 Uint8Array 而不是字符串来避免字符串规范化。首先,将字符串的 UTF-8 数据作为 Uint8Array 获取,如下所述 @Moshev:

function utf8AbFromStr(str) {
    var strUtf8 = unescape(encodeURIComponent(str));
    var ab = new Uint8Array(strUtf8.length);
    for (var i = 0; i < strUtf8.length; i++) {
        ab[i] = strUtf8.charCodeAt(i);
    }
    return ab;
}

然后你可以用普通的XHR或你最喜欢的Ajax库发布Uint8Array。如果你使用的是jQuery,请记住,你需要指定processData: false以防止jQuery试图将其字符串化并撤消你所有的辛勤工作。

您可以在提交之前在客户端操作文本。如果插入组合字形连接器有效,您可以通过JavaScript插入它。

作为一个凝视点,但这里有一个JSFiddle,它逐个字母地获取字符(在Safari中测试过,它不会规范化文本):http://jsfiddle.net/TmtnA/

最新更新