互連網讓世界變得越來越小,大多數WEB網站不得不考慮適應各種編碼的問題。本文結合Google的做法,簡單談談如何讓網站有效支援多種語言,暫且先不談各種編碼的背景知識。
通常一個提供搜尋服務的網站涉及編碼主要在以下幾點:
一、介面語言顯示
中文使用者瀏覽google.com通常會直接顯現中文介面。Google如何?的呢。看一下瀏覽器發出的請求:
GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: www.google.com
Connection: Keep-Alive
HTTP1.1協議規定了 Accept-Language節,可以使支援多語言的伺服器根據此項返回正確的結果。如果沒有指定 Accept-Language呢。telnet連上去試試看:
[fancao@free:~] $ telnet www.google.com 80
Trying 64.233.189.104...
Connected to www-china.l.google.com.
Escape character is '^]'.
GET / HTTP/1.1
HTTP/1.1 302 Found
Location: http://www.google.com/intl/zh-CN/
Cache-Control: private
Set-Cookie: PREF=ID=01710c01d6f2632d:NW=1:TM=1144067151:LM=1144067151:S=r3D24oIQQIa9u6I_; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Content-Type: text/html
Server: GWS/2.1
Content-Length: 230
Date: Mon, 03 Apr 2006 12:25:51 GMT
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.com/intl/zh-CN/">here</A>.
</BODY></HTML>
Google還是導向到了中文網站 http://www.google.com/intl/zh-CN/。可以看到實際請求是串連到了 www-china.l.google.com。
再通過瀏覽器測試一下,這次去掉瀏覽器中語言設定,也就是不指定Accept-Language,分別瀏覽www.google.com.cn、www.google.com.tw、www.google.co.jp、www.google.co.kr,可以看到不同語言的結果。也就是說不同的伺服器提供的預設介面語言是不一樣的。
如果指定了Accept-Language=zh,然後再次瀏覽http://www.google.co.kr/,這次看到的結果就不是韓文了,而是簡體中文內容。可見對Accept-Language的判斷優先順序是要高於伺服器預設語言的。
Google可以讓使用者設定介面語言,設定到哪裡了。再來看看設定了簡體中文介面後的瀏覽器請求(Cookie部分):
Cookie: PREF=ID=6f389883f4bc8b9b:LR=lang_ja|lang_zh-CN|lang_zh-TW:LD=zh-CN:NR=10:NW=1:TM=1144071286:LM=1144071338:S=91yUwz0pwGg8eb0W
原來是在用戶端種植了Cookie,這樣不管IP在何方,也不管 Accept-Language是什麼,都可以按照使用者的設定來顯示。
參照Google的做法,總結為以下3點:
·根據使用者設定種Cookie,讀Cookie
·沒有Cookie時,判斷http請求中的Accept-Language
·部署不同預設語言的伺服器,根據IP位址解析到本地區語言的伺服器
二、輸入內容的編碼識別
編碼的識別實際是很困難的,瀏覽器對網頁的識別主要依據兩點:
·HTTP協議回應標頭中的charset
·HTML頁面中的charset項
HTTP協議頭中charset優先順序要高於HTML檔案中的charset,可以做個小小測試:
<?php
header("Content-Type: text/html; charset=iso-8859-1");
?>
<html>
<head>
<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=GB2312">
</head>
<body>
漢字常值內容
</body>
</html>
上面的php程式無法正確顯示漢字,是因為在HTTP頭中指定了 charset=iso-8859-1
如果兩項都沒指定呢。瀏覽器也會比較難辦。通常識別編碼的方法是根據位元組碼去猜,看放在那個編碼區中解釋更合理。
那麼一個搜尋網站如何判斷使用者輸入字元的編碼呢。再來做測試,
在一個UTF-8頁面的FORM中提交了“中國”,會被解釋為:
http://localhost/test.php?test=%E4%B8%AD%E5%9B%BD
在一個GB2312頁面的FORM中提交了“中國”,會被解釋為:
http://localhost/test.php?test=%D6%D0%B9%FA
%E4%B8%AD%E5%9B%BD 是“中國”兩字的UTF-8編碼做了urlencode之後的結果,而%D6%D0%B9%FA則是“中國”兩字的GB2312編碼做了urlencode之後的結果。這樣我們就很清楚了,瀏覽器會根據當前頁面語言GET或者POST資料。
這樣的話,只要頁面編碼為UTF-8,然後按照UTF-8來解析查詢資料就可以解決了。
再來看看Google是怎麼玩的。Google頁面的編碼為UTF-8,在Google中搜尋“中國”,看到的URL為:
http://www.google.com/search?sourceid=navclient&hl=zh-CN&ie=UTF-8&rls=AMSA,AMSA:2006-11,AMSA:zh-CN&q=%E4%B8%AD%E5%9B%BD
好面熟的%E4%B8%AD%E5%9B%BD。
上面的URL中有ie=UTF-8一項,分析了一下發現ie就是input encode。這次難為一下Google,不指定input encode,再分別按照UTF-8和GB2312編碼查詢一下Google:
http://www.google.com/search?q=%E4%B8%AD%E5%9B%BD
http://www.google.com/search?q=%D6%D0%B9%FA
Google是在預設語言編碼和UTF-8兩種編碼直接做了識別。如何做到的呢。UTF-8編碼有一定的規則,可以按照此規則做個判斷,Google正是如此判斷的。但這種判斷有時會出錯,例如:
http://www.google.com/search?q=%D1%A7%CF%B0
%D1%A7%CF%B0是“學習”兩字的GB2312編碼做了urlencode。錯誤的原因是誤把“學習”的GB2312編碼當作了UTF-8。
參照Google的做法,可以提出如下方案:
·統一用UTF-8編碼:頁面用UTF-8編碼並且按照UTF-8編碼解析查詢資料
·複雜一些,嘗試按照UTF-8規則分析查詢資料,如果不符合規則,就認為是當前語言編碼
三:更有效搜尋結果
使用者總是希望得到更多的搜尋結果。中文網頁內容有GBK、Big5、UTF-8等編碼,日韓各種編碼中還有一部分漢字。如何才能讓使用者的搜尋更有效涵蓋這些網頁呢。這次不拿Google做測試了。根據編碼的背景知識,提出如下解決方案:
·簡繁轉換
簡繁轉換主要是將使用者搜尋請求按照兩種方式來搜尋。無論使用者輸入“大眾”還是“福士”,都按照這兩個請求同時來搜尋。
·原始網頁轉為UTF-8編碼做索引
原始網頁轉為UTF-8來做索引有很大的便利,這樣有效地將各種編碼統一來處理。