互联网让世界变得越来越小,大多数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来做索引有很大的便利,这样有效地将各种编码统一来处理。