(wrong string) Nƽ棨non-BMP)字符支援 (原: 字符编码)

我知道这不对。我的意思是按照他们的逻辑,代理对应该算一个全角字。

参见:http://hax.iteye.com/blog/696089


2011/6/9 Timothy Chien <timdream@gmail.com>

> 用「半角」「全角」來計算文字長度不對呀 ... 螢幕上的寬度除非用 monospace 字型不然不會是「算半個」,中文不用 Big5 /
> GB 等 DBCS 編碼儲存的話,在記憶體也不是佔英文字母的兩倍。
>
> 都 2011 年了 ....
>
> 2011/6/9 John Hax <johnhax@gmail.com>:
> > twitter做这个事情显然只是因为“好玩”吧。倒是新浪微博之类的应该认真考虑加入这个计算,因为既然英数算半个(半角的意思)。
> >
> > 2011/6/8 Timothy Chien <timdream@gmail.com>
> >>
> >> 1. 我一定要特別指出來以表達我對 Twitter 竟然有考慮這個東西的震驚
> >>
> >> 2. str.codePointCount() 可以用 String.prototype 實做吧?Kenny 寫個 library
> >> 丟出來吧,哪天真的大家覺得不夠快就會被瀏覽器實做了?
> >> (JSON,arr.forEach ... 等等好像都是這樣被實做的?)
> >>
> >> > HTML5 規範的 4.1.1 [4] 提到,腳本的編碼判斷的優先序是:
> >> > 腳本的 "Content-Type" 標頭 > charset > HTML 的編碼(若完全沒有任何資料的話繁體中文的瀏覽器 用
> >> > Big5,簡體中文用 GB18030)
> >>
> >> 3. 最後的()有誤,「HTML 的編碼」就是 .html 檔案的編碼,跟瀏覽器的語言無關。
> >> 即便瀏覽器的語言是繁中也不一定會把最後的預設值設在 Big5,像我在 Fx3.6 的時候就把它改成 UTF-8 了(為了和英文版行為相同)
> >>
> >> 4. 贊成標準實作內嵌編碼,優先順序可以改成
> >>    腳本的 "Content-Type" 標頭 > 內嵌編碼 > charset > HTML 的編碼
> >> 不然每次都要把中文字改成 \x12ab 真的很煩....
> >>
> >> RFC2616 那種問題是因為當初寫標準的時候沒想清楚,實做了反而會有問題。實做 Unicode
> >> 應該不會有問題吧(沒處理好可能會導致相容問題就是)。
> >>
> >>
> >> 2011/6/8 Kang-Hao (Kenny) Lu <kennyluck@w3.org>:
> >> > 做了一點實驗 行內回文
> >> >
> >> > 2011/5/9 Timothy Chien <timdream@gmail.com>:
> >> >
> >> > 那是記憶體內部處理文字的標準吧?與檔案的編碼無關。
> >> > 意思是說,
> >> >
> >> > ('字').charCodeAt(0)
> >> >
> >> > 會傳回 UCS-2 code point。
> >> >
> >> > 我用這個字試了幾的瀏覽器:
> >> >
> >> > 「𠂇」 U+20087 &#131207;
> >> > 代理對(surrogate pair): D870 DC87
> >> > 十進位: 55360 56455
> >> >
> >> > (不要問我這個字是什麼,隨便找的。我只知道這字讓我想到娜美(ナミ)xd)
> >> >
> >> > 基本上 Firefox, Chrome, Safari 都說 "𠂇".length = 2
> >> >
> >> > 不信的在瀏覽器 URL 條打 「javascript:alert("𠂇".length)」 試試看
> >> >
> >> >
> >> > 比較有趣的是,Twitter 在那個限制輸入 140 字的做法竟然把 "𠂇"  的長度算對成 1 了。他們的源碼是這樣寫的:
> >> >
> >> > displayLength:function(string){
> >> >   if(typeof string!=="string"){throw new Error("displayLength()
> requires
> >> > a
> >> > single input of type string")}
> >> >   var i=0,length=0;
> >> >   var getWholeChar=function(str,i){
> >> >     var code=str.charCodeAt(i);
> >> >     var next="",prev="";
> >> >     if(55296<=code&&code<=56319){
> >> >       if(str.length<=(i+1)){throw"High surrogate without following low
> >> > surrogate"}
> >> >       next=str.charCodeAt(i+1);
> >> >       if(56320>next||next>57343){throw"High surrogate without
> following
> >> > low
> >> > surrogate"}
> >> >       return str.charAt(i)+str.charAt(i+1)}
> >> >     else{
> >> >       if(56320<=code&&code<=57343){
> >> >         if(i===0){throw"Low surrogate without preceding high
> surrogate"}
> >> >         prev=str.charCodeAt(i-1);
> >> >       if(55296>prev||prev>56319){throw"Low surrogate without preceding
> >> > high
> >> > surrogate"}
> >> >       return false}}
> >> >     return str.charAt(i)
> >> >   };
> >> >   for(i=0,length=0;i<string.length;i++){
> >> >     if(getWholeChar(string,i)===false){continue}
> >> >     length++
> >> >   }
> >> > return length} (版權所有 Twitter,做這種事有犯法的話麻煩私下指點一下、、、)
> >> >
> >> > 也就是說他有特地去處理代理對的情形。(雖然其實我不太理解為什麼 Twitter 對不同語言同樣是限制 140 字 xdd)
> >> >
> >> > 新浪微博打 "𠂇" 這個字的話就會佔兩個剩下字數,那跟 "𠂇".match(/[^\x00-\x80]/g).length = 2
> 而不是
> >> > 1
> >> > 有關,不過新浪微博還有一些很奇怪的現象(空白不占字數、英字占半個)之類的,所以這種小地方似乎也不需要在意了。
> >> >
> >> >
> >> > 剩下的問題就是,有沒有必要為這種比較罕見的情形弄出新的 JavaScript API (ECMAScript6?)
> >> > 比如說在 Java 裡,除了 length 以外還有 codePointCount、codePoint 這些方法[1]:
> >> >
> >> > String s = "𠂇";
> >> > System.out.println(s.length()); //顯示為 2
> >> > System.out.println(s.codePointCount(0, s.length())); //顯示為 1
> >> > System.out.println(s.codePointAt(0)); // 顯示為 131207 也就是 "𠂇" 的值
> >> > System.out.println(s.codePointAt(1)); // 顯示為 56455 也就是 "𠂇" 的後半部
> >> >
> >> > 也就是說 codePointAt(N) 不是第 N 個字符,而是「若第 N 個 16-bit
> >> > 是某個代理對的前半部,輸出整個字」,是一個不需要掃描整個字串的方式。
> >> >
> >> > [1]
> >> >
> http://download.oracle.com/javase/1,5.0/docs/api/java/lang/String.html
> >> >
> >> >
> >> > 這個問題好像在 3 年前在 Python 社群也論戰過[2],有些人希望:
> >> >
> >> > s = "𠂇"
> >> > len(s) // 輸出為 1
> >> >
> >> > 核心社群的回答是「想都別想」(現在是 2),但是核心社群可以接受跟 Java 一樣多一個 API(不過似乎還沒有人有貢獻 :( )
> >> >
> >> > [2]
> >> >
> http://mail.python.org/pipermail/python-dev/2008-July/thread.html#80886
> >> >
> >> >
> >> > 回到 JavaScript,一般來說,為了向後支援 "𠂇".length 或是 "𠂇".charCodeAt(0)
> >> > 之類的要改也是「想都別想」。不過我們有 "𠂇".codePointCount 跟
> >> > String.prototype.codePointAt(N)
> >> > 的需求嗎?這個需求有夠大嗎?
> >> >
> >> > codePointCout 的好處當然就是用瀏覽器的 C++ code 比 Twitter 那個快,而 codePointAt 就是
> >> > timdream
> >> > 找到的 JavaScript code
> >> >
> >> > 不過後果就是 UCS-2 塞不進去的 Unicode code point,像是 Ext-B 的漢字,
> >> > 在 Javascript 裡面會被拆成兩個字元,這時要找到真正的 Unicode code point 就要把兩個字元的字碼都讀出來處理:
> >> >
> >> >
> >> >
> https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/charCodeAt#Example_2.3a_Fixing_charCodeAt_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_unknown
> >> >
> >> > 的 C++ 版本
> >> >
> >> > (11/05/09 11:05), Ben Luo wrote:
> >> >
> >> > 那也就是说 browser 在载入js文件的时候会自动转换成 UCS-2?它是怎么自动判断文件本身的编码呢?
> >> >
> >> > 2011/5/9 Timothy Chien <timdream@gmail.com>:
> >> >
> >> > <script type="text/javascript" src="script.js" charset="utf-8"
> >> > ></script>
> >> >
> >> > 根據 HTML4 標準設定 charset 屬性
> >> > http://www.w3.org/TR/html401/interact/scripts.html#edef-SCRIPT
> >> >
> >> > HTML5 裡面也有 這個屬性
> >> >
> >> >
> http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#attr-script-charset
> >> > 到這裡為止,可以判斷這個屬性至少在未來可以用。
> >> >
> >> > 不過我不知道哪家瀏覽器吃就是了。
> >> >
> >> > 測試了一下 Firefox4 跟 Chrome11 都可以用。如果我有多一點勇氣相信 W3school
> >> > 的內容[3]我就不需要要做測試了,這似乎是存在很久的東西了。
> >> >
> >> > [3] http://www.w3schools.com/tags/att_script_charset.asp
> >> >
> >> > 最保險的做法是保持和引用的 HTML 同樣的 encoding,
> >> >
> >> > HTML5 規範的 4.1.1 [4] 提到,腳本的編碼判斷的優先序是:
> >> >
> >> > 腳本的 "Content-Type" 標頭 > charset > HTML 的編碼(若完全沒有任何資料的話繁體中文的瀏覽器 用
> >> > Big5,簡體中文用
> >> > GB18030)
> >> >
> >> > 所以這個方法要確保伺服器不會亂傳 "Content-Type"。
> >> >
> >> > [4]
> >> >
> >> >
> http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#execute-the-script-block
> >> >
> >> > 或是只要用到 ASCII 以外的字元通通用 \x12ab 來表示。
> >> > (寫 script 也不該出現那些介面用文字,介面字串資源和程式應該要分開)
> >> >
> >> > 這個方法似乎比較保險,不過不想做英文界面的時候有時候要分開字串跟程式很麻煩的。
> >> >
> >> > (11/05/09 12:12), Ben Luo wrote:
> >> >
> >> > 当然这和 html5 无关,只是好奇,为什么JS只规定内部编码,不规定文件编码,毕竟JS不是凭空生产的。
> >> >
> >> > 我想主要是不實際的關係,大家都知道 JS 最主要的用戶代理(user agent)就是瀏覽器,而瀏覽器一定會決定一個 HTML 的編碼而
> JS
> >> > 的預設文件編碼就會是那個,就算在 JS 的規範定義了一個預設的編碼也可能會被 HTML
> >> > 的編碼蓋掉,就沒有那個預設編碼的意義了。另一方面,要把上面提的優先順序寫進 JS 的規範的話就會變成 JS 依存於 HTTP 及 HTML
> >> > 而破壞這個結構。一個類似的例子是 HTTP 規範(RFC2616[5])定義了 ISO-8859-1 作為預設的編碼,但是這在 HTML
> >> > 下完全不被使用(仍然是用瀏覽器的使用者語言為最終的編碼),變成了不是很有意義的規範敘述。
> >> >
> >> > [5] http://tools.ietf.org/html/rfc2616
> >> >
> >> > 另一方面可以討論的問題是 JS 該不該有類似 Python 的內嵌編碼宣告[6]:
> >> >
> >> > # -*- coding: utf-8 -*-
> >> >
> >> > 畢竟伺服器端用的 JS 可能會越來越多(因為有Node.js)。這個問題就留給大家討論了(有人知道Node.js的情形嗎?),不過對於瀏
> >> > 覽器來說,會需要定義優先序為:
> >> >
> >> > 腳本的 "Content-Type" 標頭 > charset > 內嵌編碼 > HTML 的編碼
> >> >
> >> > 或是
> >> >
> >> > 腳本的 "Content-Type" 標頭 > 內嵌編碼 > charset > HTML 的編碼
> >> >
> >> > 甚至是直接忽略內嵌編碼。恐怕蠻難下一個決定的。
> >> >
> >> > (11/05/09 10:13), Ben Luo wrote:
> >> >
> >> > 昨天看 ECMAScript v5 的标准,字符编码要求是UCS-2 或 UTF-16,
> >> > 在html5中是什么要求?在现实中好像大家都是用utf-8作为字符编码。对此大家有什么心得?
> >> >
> >> > 補個 ECMAScript v5 連結 → http://people.mozilla.org/~jorendorff/es5.html
> >> > 推薦給對 JS 種種奇怪行為感到憤怒的朋友們
> >> >
> >> > 也歡迎大家帶其他標準的心得與討論進來這個討論組(包括IETF),若是有更好的討論地方也歡迎提供連結!
> >> >
> >> >
> >> > 此致
> >> >
> >> > 呂 康豪(Kenny), 中文興趣小組W3C連絡人
> >> > 推特: http://twitter.com/kanghaolu
> >> > 噗浪: http://www.plurk.com/kennyluck
> >> > 新浪微博: http://t.sina.com.cn/1950042164
> >> >
> >> >
> >
> >
>

Received on Wednesday, 8 June 2011 16:51:27 UTC