Markdown 的一点翻译

Markdown 是 John Gruber 精心设计的一套文本标记系统,由 Michel Fortin 转换到 PHP 并提供了 WordPress 的插件。这两天抽空翻译了一下 Markdown基本功能以备学习。感谢 hlb 的指点,我想下面要做的大概是翻译完整的 syntax 文件和 PHP Markdown 的扩展功能。此外,MultiMarkdown 也是个有趣的东西。

噢对了,翻译后的文件在这儿

Wrong Encoding? Whose Fault

早在 2004 年,Tim Bray, Nick BradburyMark Pilgrim 这几位大牛就有过一场著名的口水战,围绕着客户端是否应该接受不 valid 的 XML (XHTML) 而展开,这场口水战以 Mark Pilgrim 的一篇堪称经典的 Thought Experiment 而告结束。Mark 举的一个例子就是页面本来是完全 valid 的,但别人发来了一个 trackback,其中包含了非法的字符,导致整个页面都无法通过校验。

时至今日,一年半过去了,乱码的 trackback 仍然随处可见,我们的 blog 工具版本号一升再升,难道就是解决不了这个问题?

为什么要解决这个问题?

有人会问,为什么要解决这种问题呢?人人都用 UTF-8 不就好了么?没错,在一个理想的世界里,UTF-8 解决了一切问题。问题在于,在一个理想的世界里,M$ 不是坏蛋,IE 还支持 CSS 3 呢!所以我们不能依靠这种白日梦。踏实一点来看,我们现在生活的世界情况是这样的:Apache 占据了大部分的市场,PHP 和 Perl 是两种主要的 Web 脚本语言——尤其对 Blog 而言,MySQL 是大部分开源 Web 程序使用的数据库,可是主机服务上还往往不如人意,大部分的用户不能自如的指定自己 Blog 使用的字符编码,转换 MySQL 存储数据的编码也不是天天没事就能转来转去玩儿的。

这个环境,说明我们应该对他人的页面使用的编码宽容一些。

这个问题理应如何解决

Trackback 不是一个标准,更没有标准化组织进行维护,它只是 MovableType 中发明的一种格式,最权威的说明,就是这篇 TrackBack Technical Specification。而这个规范中对编码唯一的说明是:

The client SHOULD include the character encoding of the content being sent (title, excerpt, and weblog name) in the charset attribute of the Content-Type header.

例如:

POST http://www.example.com/trackback/5
Content-Type: application/x-www-form-urlencoded; charset=utf-8

但接收这个 trackback 的那一方如何获取这个 charset 的值呢?如果在 PHP 中,唯一的方法是用 getallheaders() 函数,但这是在“PHP 作为 Apache 模块安装时才可使用”——事实上许多主机提供商是以 CGI 方式安装 PHP 的。

所以此路不通,我们应该对 Trackback 的协议进行扩展,在 POST 的数据中添加关于字符编码的一项,WordPress 就是以这种方式来实现的,让我们先打开 wp-trackback.php,这是接收 trackback 用的:

$charset   = $_POST['charset'];

if ($charset)
    $charset = strtoupper( trim($charset) );
else
    $charset = 'ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS';

if ( function_exists('mb_convert_encoding') ) {
    $title = mb_convert_encoding($title, 
    get_settings('blog_charset'), $charset);
    ...

上面的代码说明,WP 会从 POST 数据的 charset 一列中取得 trackback 发送者使用的字符编码,如果找不到就使用一套预设的编码 (从这个预设的编码我们可以肯定,90% 的可能是有个日本人给 WordPress 官方报告了 trackback 错误的问题,所以它们头痛医头,只加上了三个日文编码),然后使用 mb_convert_encoding 函数把这个编码转换为 blog 当前使用的编码。

让我们注意三点:

  1. 每个 PHP 安装不一定都启用了 mbstring 模块,也就是说,不一定能进行这个转换,例如,我自己的电脑上安装的 PHP 5,默认就没有打开这个模块。
  2. 当给出一列来源编码时,转换函数以一种猜测的方式来尝试转换 (我在 Planet 的 patch 中描述了这种转换的原理),但这种猜测未必是对的,例如,Big-5 的编码和 GB2312 的编码有部分是重合的,此时无论把 Big-5 列在前还是 GB2312 列在前,都无法同时正确解码这两种编码的文档。
  3. 我们有理由相信这是 WP 私自作出的扩展,MT 不知道这一点 (我手头没有 MT 的代码,使用 MT 的朋友若有兴趣,请帮忙查查)。

WP 糟糕在哪里和我们如何改进

WP 的问题是,它使用 POST 数据中的 charset 一栏来分辨编码,但它自己发送的 trackback 中,不包含这一栏 (trackback() 函数在 wp-includes/functions.php 中),我必须承认我搞不懂这是为什么。

有了上面的解释,我们很容易提出下列的改进:

  1. 提出更改 Trackback 的规范,增加 charset 这一项。
  2. 建议 WP 和 MT 都在发送 Trackback 时,包含这一项。
  3. 建议 WP 和 MT 在发送 Trackback 时,先转换成 UTF-8 再发送。

Vanilla 的本地化

这个东东本来已经快写完了,结果 Firefox 居然崩溃了,前边写的全丢失,打倒 Firefox!

Vanilla 是个新出的论坛系统,里边有不少新概念,比如 AJAX 的运用,Atom 1.0,OO 的 PHP 开发方式,CSS 中对手持设备的支持,等等。可惜作者的水平显然还不算老练,本地化特别不方便,而是性能特别差,三是 bug 还很多,作者改 bug 又很慢。所以注定是个玩具了。建议认真想开论坛的现在别用。

昨天看了 Jedi 的 Vanilla 的中文化,便手痒找来玩玩,有几个小 bug,原来详细写了,刚才丢了数据,也懒得重新写,简单说说吧。

  1. 配置文件不支持中文,解决方法看这里
  2. MySQL 4.1,论坛内容不支持中文,解决方法看这里
  3. PHP 5,扩展列表有错,解决方法看这里
  4. 中文化中遇到的问题,过几天整理一下再细写。