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

时间:2012-06-24 10:12:28

标签: forms unicode normalization unicode-normalization

在HTML中呈现以下Unicode文本时,发现浏览器(Google Chrome)在将数据发回服务器时会执行某种形式的Unicode normalization。 (可能在Form C)。

但是当使用圣经希伯来文(בְּרִיךְהוּא)文本时,这很容易打破文本,如here(第9页)中所述。

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

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

3 个答案:

答案 0 :(得分:10)

这似乎是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进行了一个简单的测试,然后组合了分音符U + 0308。 WebKit浏览器根据NFC规则将其转换为单个字符ë,而其他浏览器保持字符对完整。

自2006年以来,这似乎是一个故意的特征; https://bugs.webkit.org/show_bug.cgi?id=8769自豪地宣布这是错误修复的一部分!这可以解释W3C政策文件的状态;它目前的版本在本期中是WebKit-minded,但其他浏览器供应商要么不感兴趣,要么故意反对“早期正常化”的想法。

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

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

根据Unicode原则,规范等效字符串(例如,仅按连续变音符号的顺序不同)是相同数据的不同表示,但与Unicode字符序列(代码点)不同;他们不会在演讲中有所不同,但他们可能并且经常这样做。通常,您不应该期望程序将规范等效的字符串视为不同的,尽管程序可能会产生影响。请参阅Unicode Normalization FAQ

FAQ条目声称,通过引入COMBINING GRAPHEME JOINER解决了圣经希伯来语的问题。虽然它可以防止Chrome中的重新排序,但它是一种笨拙的方法,它可能会使渲染变得混乱(它在Web浏览器中会出现;变音符号可能会被错误地放错位置)。

答案 1 :(得分:1)

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

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尝试对其进行字符串化并撤消所有您的辛勤工作。

答案 2 :(得分:0)

您可以在提交之前操作客户端上的文本。如果插入Combining Grapheme Joiner,则可以通过JavaScript插入它。

作为一个注意点,但是这里是一个JSFiddle,它逐字逐字地获取字符(在Safari中测试并且没有规范化文本):http://jsfiddle.net/TmtnA/

相关问题