最近更新: 2012-05-14

gjs - 中文字的處理

gjs/gnome-shell 可以在程式碼中使用中文字以及包含中文字的字串。 但是它的內部編碼方式有點特殊,以至於它不能直接地輸出程式碼中的中文字。 本文採用下列三種不同的方式輸出中文字,並記錄其結果。

試驗程式

以下為本文將試驗的三種處理中文字的方式:

  • In code - 直接寫在程式碼中的中文字
  • Gettext - 透過 GNU Gettext 功能取得的中文字。
  • Read from file - 從外部檔案中讀入的中文字。

最後額外附帶 GLib.convert 的字元集轉碼函數範例。

#!/usr/bin/gjs

// case 1: In code.
print("檔案");  // 輸出結果不正確。


// case 2: Gettext.
const GetText = imports.gettext;
GetText.bindtextdomain('vlc', '/usr/share/locale');
GetText.textdomain('vlc'); // 借用 vlc 這套軟體的訊息包。
const _ = GetText.gettext;

print(_('File'));  // 正確。

// case 3: Read from file.
const GLib = imports.gi.GLib;

var results = GLib.file_get_contents("gjs-chinese.js"); // 讀取檔案內容
if (results && results[0]) {
    print(results[1]);  // 正確。
}
else {
    print("Failed to read from file");
}

// 測試文字轉碼函數是否可發揮作用
print(GLib.convert("檔案", -1, 'utf-8', 'utf-8')); 
// 沒影響,輸出錯誤。

//print(GLib.convert("檔案", -1, 'unicode', 'utf-8')); 
// Error: Failed to convert UTF-8 string to JS string: 轉換輸入資料時遇到不正確的位元組組合

print(GLib.utf16_to_utf8('檔案', -1)); 
// 沒有內容,函數認為輸入內容不是utf-16編碼。

print(GLib.locale_to_utf8('檔案', -1)); 
// 沒影響,輸出錯誤。
結論

根據上述測試得到結論, gjs 不喜歡我們在程式碼中直接撰寫包含中文字的字串,這些字串輸出時不會得到正確的結果。程式中的文字訊息,最好使用 Gettext 功能處理。至於產生 Gettext 訊息包的方式,請參考「Vala with GNU gettext」。

讀自外部檔案的字串內容,若是 utf-8 編碼者,可以正確地輸出。若是屬於其他字元集編碼,則應先用 GLib.convert() 等字元轉碼函數轉換。

附註

Gettext 除了常用的 gettext() 外,還有 dgettext(), ngettext(), dngettext() 函數。其中 ngettext() 也相當常用,它用於處理複數名詞的本地化訊息。使用方式可以參考 PHP 手冊的說明與範例: 「PHP Manual: ngettext」。

Gettext 函數宣告:

  • bindtextdomain(domain, locale_path);
  • textdomain(domain);
  • gettext(msgid);
  • ngettext(msgid1, msgid2, n);
  • dgettext(domain, msgid);

GLib.convert 內部預設採用 iconv 函數庫處理轉碼。那是普遍被採用的字元集轉碼函數庫。函數宣告:

  • convert(str, int len, to_codeset, from_codeset); len 可用 -1。
  • locale_to_utf8(str, len);
  • locale_from_utf8(utf8str, len);
  • filename_to_utf8(str, len);
  • filename_from_utf8(utf8str, len);
  • filename_from_uri(uri);
  • filename_to_uri(filename, hostname);
樂多舊網址: http://blog.roodo.com/rocksaying/archives/19453974.html