向sanitize_title()堅決鬥爭到底!

簡單說一下來龍去脈,sanitize_title()是在WordPress系統中所大量使用的一個function,這個function用途,在於將各式各樣的資料,包括文章標題、分類名稱等,轉換成一個內部使用的欄位,比方說,把文章標題的內容,轉換成PostSlug之類的代稱,將post_title當中的資料,轉換成post_name,轉換過程包括將所有的大寫英文轉成小寫,去除不必要的標點符號以及將空白轉換成底線等。這個內部使用的代稱,主要應用在產生文章的網址上,比方說,如果你寫了一篇叫做Hello! World!的文章,便可以產生如http://example.com/2004/07/09/hello_world之類的網址。

在中文使用上,sanitize_title()有嚴重的問題,那就是在於無法處理中文,中文標題在處理之後只會得到空白字串,所以,如果當你在WordPress開啟了permalink功能的話,便可能因為這個函數無法正確處理中文,而造成一些問題。比方說在對岸的簡體「中文WordPress」計畫網站的〈文章分類中不支持中文〉這篇文章,當中所描述的問題,就是因此產生的。從WordPress五月份釋出1.2版以來,我嘗試了幾種作法,企圖產生中文相容的sanitize_title()處理結果,包括先把中文文字urlencode()處理過,還有很蠢的,用一個很大的迴圈,把所有的中文UTF-8字元代換成漢語拼音(註:最近發現,那個外掛程式會在某些PHP環境中,例如裝了turck-mmcache之後,就會爛掉)等。

這兩天我把這個問題想通了(或是說,想開了?),要解決這個中文使用上的問題,不一定要產生要非常符合原本中文標題、或中文分類文義相關的英文代稱,而是,只要是在sanitize_title()傳回空白數值的時候,直接填寫一些其他的資料進去,讓$post_name或供文章分類名稱使用的$cat_name,不要是空白即可。比方說,在post.php裡頭,原本的設計是:

if (empty($post_name))
$post_name = sanitize_title($post_title);
else
$post_name = sanitize_title($post_name);

這種想法實在是太天真了,以為只要是sanitize_title傳回來的資料,就一定不會是空白,所以,我繼續加了一些檢查的小程式:

if (empty($post_name))
$post_name = sanitize_title($post_title);
else
$post_name = sanitize_title($post_name);

if (empty($post_name)) {
$post_ID = $wpdb->get_var("SELECT ID FROM $tableposts ORDER BY ID DESC LIMIT 1");
$post_name = "post-".$post_ID + 1;
}

如果$post_name還是空的,我就把$post_name變成「post-123」這類,以文章在資料庫當中的ID,當作$post_name。我最近弄好了一個WordPress 1.2中文安裝包測試版六(下載),就已經放進了這些修改。另外,我也將這個問題,傳回WordPress官方的「臭蟲回報系統」,這個bug在一個小時內就修好了,真是迅速,不過,想想我都已經說了應該要怎麼改,快速解決好像也很正常,呵。

這邊說的是中文文章標題,在分類名稱方面,目前在安裝包測試版六中,是把之前所做的將「分類敘述」代替「分類名稱」的修改,放了進去,也就是,你可以在「分類名稱」中打英文,在「分類敘述」打中文,以英文名稱產生網址,另外,在頁面上,則是顯示中文分類敘述。不過,這種作法感覺還是很不好,要繼續解決這個問題,應該是要讓使用者可以自己調整用來產生網址的category_nicename欄位。目前已經有人回報無法直接修改category_nicename欄位的問題,應該日後可以解決。

在安裝包測試版當中,另外放進了Mike Lu所抓出的錯誤,包括月曆功能的一些錯誤,另外我最近也發現「前一篇文章」與「下一篇文章」的連結功能(previous_post以及next_post)有些錯誤,也改正了。這兩天有空的話,繼續來把這些錯誤回報給官方。

Be Sociable, Share!

4 thoughts on “向sanitize_title()堅決鬥爭到底!

  1. Pingback: 中文WordPress

  2. Pingback: wordpress实现中文昵称nicename和作者author页中文网址 - 张立志中文博客

Comments are closed.