在HTML中呈现以下Unicode文本时,事实证明浏览器(谷歌浏览器)可以采用某种形式 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和歌剧没有。
我还用拉丁字母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规范化常见问题。
常见问题解答条目声称圣经希伯来语的问题已经通过COMBINING 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尝试对其进行字符串化并撤消所有辛苦工作。
您可以在提交之前操作客户端上的文本。如果插入Combining Grapheme Joiner,则可以通过JavaScript插入。
作为一个注意点,但这里是一个JSFiddle,逐个字母地获取字符(在Safari中测试,它不规范化文本): http://jsfiddle.net/TmtnA/