WordPress的中文支持有问题,特别是在使用Permalink的时候,这个大家都知道。本文将分析其中的原因和网上流传的多种解决方案,并给出一个具体的解决结论。
这个问题主要表现为,在默认情况下,Wordpress对于形如这样的链接(链接1):
www.example.com/tag/中文
不能正常访问,会产生404或500错误,或者其他的错误。
而对于这样的链接(链接2):
www.example.com/?tag=中文
WordPress就能够正确解析。
原因:参见这篇文章和这篇文章,这是URL编码问题造成的。对于上面的链接1,这是一个PathInfo,对于链接2,这是一个QueryString。事实证明,对于UTF-8的页面,IE和FF都会正确发送PathInfo和QueryString(而不像有些文章中说的,他们在不同的设置下会有错误的反应),但服务器端,IIS会将PathInfo转换成GBK编码从而造成错误,于是Windows下的此类问题只需要转回来就行了;但是Linux下,Apache不支持中文PathInfo,要么通过这篇文章中的方法来对Apache进行改造,要么只能像我一样,Linux主机无法使用中文permalink。于是,我们只能寻找绕路的方法。
解决方案分析:
一、转换编码(参见这篇文章)
原理是,IIS会将PathInfo中的UTF-8转换成GBK,而QueryString中就不会转换,故而为了使用Permalink,采用以下方法:
打开wp-includesclasses.php文件,找到第44行和第50行:
if ( isset($_SERVER['PATH_INFO']) ) $pathinfo = $_SERVER['PATH_INFO']; else $pathinfo = ''; $pathinfo_array = explode('?', $pathinfo); $pathinfo = str_replace("%", "%25", $pathinfo_array[0]); $req_uri = $_SERVER['REQUEST_URI'];
改为
if ( isset($_SERVER['PATH_INFO']) ) $pathinfo = mb_convert_encoding($_SERVER['PATH_INFO'], "UTF-8", "GBK"); else $pathinfo = ''; $pathinfo_array = explode('?', $pathinfo); $pathinfo = str_replace("%", "%25", $pathinfo_array[0]); $req_uri = mb_convert_encoding($_SERVER['REQUEST_URI'], "UTF-8", "GBK");
局限:只对Windows主机、且必须是Windows下的IIS主机有效。
二、修改rewrite.php(参见这篇文章)
这是网上最常见的方法,原理是,让WordPress在对其他内容使用Permalink的时候,对tag不使用,而使用链接2的QueryString模式发送中文编码:
1 2 3 4 5 6 7 8 | function get_tag_permastruct() { if (isset($this->tag_structure)) { return $this->tag_structure; } if (empty($this->permalink_structure)) { //-----this line need change------ $this->tag_structure = ”; return false; } |
把第5行改为
if (!empty($this->permalink_structure)) {
局限:没有起到Permalink的“漂亮”作用,如果不能自己修改WP的文件就没办法了。
三、修改tag base(参见这篇文章,经过我研究改造)
原理同上,只要让WordPress在打开了Permalink功能后继续对tag不理不问就行了。那么,欺骗WordPress,让它用链接2的格式来显示Permalink,可行么?可行,因为WordPress可以自定义Permalink的形式:
在WordPress的 Settings – Permalinks – Tag base 中填上
/?tag=
注意”"不能少,引用原文中的写法不对。另外要注意每次输入”",WP都会再次转义为”\”,所以每次点提交都会把”"翻一倍,点两次就是”\\”,所以不要多点,一次就对了。
这个方法的结果是使得链接变成这个样子
www.example.com/?tag=/中文/
多出来的斜杠对于服务器丝毫没有影响,还是被视为QueryString,效果同上。
局限是链接变得更加不好看了,更为致命的是插件生成的Sitemap中,tag链接会变成错误的形式,如果你很在乎Sitemap,请不要使用这个方法,除非你真的无法修改自己的rewrite.php文件。
但是当你使用WP-SuperCache或者类似的缓存插件时,它会加入自己的rewrite规则,所有请求先由自己判断,不在缓存中或者不符合缓存规则才交由WordPress处理。但问题在于,它不支持中文URL的解析,哪怕是QueryString也不行。于是我们必须绕过它。
这是WP-SuperCache在.htaccess文件里所添加的rewrite规则
RewriteEngine On RewriteBase / RewriteCond %{REQUEST_METHOD} !=POST RewriteCond %{QUERY_STRING} !.*s=.* RewriteCond %{QUERY_STRING} !.*p=.* RewriteCond %{QUERY_STRING} !.*attachment_id=.* RewriteCond %{QUERY_STRING} !.*wp-subscription-manager=.* RewriteCond %{HTTP_COOKIE} !^.*(comment_author_|wordpress|wp-postpass_).*$ RewriteCond %{HTTP:Accept-Encoding} gzip RewriteCond %{DOCUMENT_ROOT}/wp-content/cache/supercache/%{HTTP_HOST}/$1/index.html.gz -f RewriteRule ^(.*) /wp-content/cache/supercache/%{HTTP_HOST}/$1/index.html.gz [L] RewriteCond %{REQUEST_METHOD} !=POST RewriteCond %{QUERY_STRING} !.*s=.* RewriteCond %{QUERY_STRING} !.*p=.* RewriteCond %{QUERY_STRING} !.*wp-subscription-manager=.* RewriteCond %{QUERY_STRING} !.*attachment_id=.* RewriteCond %{HTTP_COOKIE} !^.*(comment_author_|wordpress|wp-postpass_).*$ RewriteCond %{DOCUMENT_ROOT}/wp-content/cache/supercache/%{HTTP_HOST}/$1/index.html -f RewriteRule ^(.*) /wp-content/cache/supercache/%{HTTP_HOST}/$1/index.html [L]
我们要做的就是不让它去判断中文tag链接,在两个 RewriteCond %{REQUEST_METHOD} !=POST 后面分别加入这样一句:
RewriteCond %{QUERY_STRING} !.*tag=.*
含义是如果QueryString中含有tag字样,请不要解析(交给下一条规则,一般来说就是WordPress的index.php了)。
结论:
Windows+IIS主机下,通过方案一可以完美解决中文tag问题
Linux+Apache主机下,不能使用中文Permalink,除非修改Apache,否则只有用方案二和方案三绕行。
方案二是较为推荐的方法,但是搭配WP-SuperCache使用的时候,需要自己在.htaccess文件中加入一条不处理tag链接的规则。
Related posts:
January 27th, 2009 at 7:29 pm
いくつかの非常に興味深いと洞察力に考え。私はこのように。
July 15th, 2009 at 3:07 pm
wp处理标签云是在那个文件?
May 26th, 2010 at 12:02 pm
试过,方法2可用,谢谢
June 11th, 2010 at 1:36 pm
Endlich ein guter Beitrag zum Thema. Sitze grad im Internetcafe in der Karibik und schreibe meinen Reisebericht, wenn ich nicht grade sonstwo im Netz rumturne und mich von Blogs wie diesen ablenken lasse ;-) bis bald mal
July 25th, 2010 at 4:57 pm
[...] 具体做法可参考这里。 [...]