Gnome shell extensions的國際化(International)方法
起因於想要一個簡單的外掛顯示中文,一開始以為js檔案,應該可以接受unicode文字,直接將英文改為中文,結論是想的太美好了...Orz。一些關於Gnome shell extensions(之後簡稱GSE)的介紹與知識皆列在後面的參考,這裡就不介紹了。另一個快速了解的方法就是看別人寫的,這一直都是不錯的方法。
首先, GSE使用GNU gettext來處國際化,Linux上很多套件也用這,所以主要使用的工具都有內建。PS. 我的OS是Mint。先簡單介紹一下,要使用gettext,程式內就必須使用gettext來取得國際化的文字(感覺像在廢話),例如:gettext("hello")或_("hello"),第二種是使用"_"標記語法,為較簡潔的共通寫法。xgettext指令是讀取並掃描程式原始碼的檔案來產生.po檔,換句話說,xgettext會找出所有的gettext(),如果要用"_"或其他符號標示的寫法,必須給xgettext帶上一個keyword的參數,用法如下
po檔其實是個文字檔,可以直接用vim、gedit或其他可編輯文字的編輯器觀看和編輯。在po檔裡可看到許多配對的設定,類似如下:
msgid就是從程式裏面掃描到gettext("hello")或_("hello")所得到的,因此只要程式中指要使用gettext("hello")或_("hello"),就可以得到msgstr的值,如果msgstr為空值,則直些返回msgid。這作法就等於是開發者可選定一樣語言或自訂符號或縮寫作為國際化的識別ID,msgid不會重複,因此相同的msgid都可得到相同的文字結果。
接著,使用msginit產生語系檔(.po),例如:
如果不給locale,則會自動抓取OS所使用的locale。
msginit只是幫忙填入.po檔裡面的一些資訊,如content-type、last-translator、language等,並不會幫忙自動翻譯喔,沒有那麼厲害。接著就可以開始編輯填入msgstr。
編輯完後,使用msgfmt將.po檔編譯成附檔名為mo的binary檔,.mo檔才是GSE真正讀取的檔案。
接著將mo檔放到extension自己目錄下的locale/[LOCALE]/LC_MESSAGES/下(目錄需要自行建立)。接下來就是編輯extension.js設定extension可以正確讀取到這些mo檔案。
extension.js的init function是extension啟動時第一個讀取的function,國際化的設定必須在init裡呼叫。首先必須先宣告gettext物件。
DOMAIN是字串,也就是目錄locale/[LOCALE]/LC_MESSAGES/下的mo檔名,通常會用extension的名稱來取名。接著在init function裏面填入
DOMAIN同上,LOCALE DIR PATH是locale的目錄路徑,有兩種方法可取得。首先,init function會傳入一個metadata的物件,這個metadata即extension目錄裡的metadata.json。metadata包含有path的屬性可以知道extension所在的路徑,兩種方式如下:
以上的設定等同於告訴gettext該從什麼路徑讀取和檔名是什麼。以上就是GSE設定國際化的過程了。
Reference:
首先, GSE使用GNU gettext來處國際化,Linux上很多套件也用這,所以主要使用的工具都有內建。PS. 我的OS是Mint。先簡單介紹一下,要使用gettext,程式內就必須使用gettext來取得國際化的文字(感覺像在廢話),例如:gettext("hello")或_("hello"),第二種是使用"_"標記語法,為較簡潔的共通寫法。xgettext指令是讀取並掃描程式原始碼的檔案來產生.po檔,換句話說,xgettext會找出所有的gettext(),如果要用"_"或其他符號標示的寫法,必須給xgettext帶上一個keyword的參數,用法如下
~ $ xgettext [FILE] # 使用"_" ~ $ xgettext --keyword=_ [FILE]
po檔其實是個文字檔,可以直接用vim、gedit或其他可編輯文字的編輯器觀看和編輯。在po檔裡可看到許多配對的設定,類似如下:
msgid "hello" msgstr ""
msgid就是從程式裏面掃描到gettext("hello")或_("hello")所得到的,因此只要程式中指要使用gettext("hello")或_("hello"),就可以得到msgstr的值,如果msgstr為空值,則直些返回msgid。這作法就等於是開發者可選定一樣語言或自訂符號或縮寫作為國際化的識別ID,msgid不會重複,因此相同的msgid都可得到相同的文字結果。
接著,使用msginit產生語系檔(.po),例如:
~ $ msginit --locale=[LOCALE NAME] --input=[INPUT FILE]
如果不給locale,則會自動抓取OS所使用的locale。
msginit只是幫忙填入.po檔裡面的一些資訊,如content-type、last-translator、language等,並不會幫忙自動翻譯喔,沒有那麼厲害。接著就可以開始編輯填入msgstr。
編輯完後,使用msgfmt將.po檔編譯成附檔名為mo的binary檔,.mo檔才是GSE真正讀取的檔案。
~ $ msgfmt [PO FILE]
接著將mo檔放到extension自己目錄下的locale/[LOCALE]/LC_MESSAGES/下(目錄需要自行建立)。接下來就是編輯extension.js設定extension可以正確讀取到這些mo檔案。
extension.js的init function是extension啟動時第一個讀取的function,國際化的設定必須在init裡呼叫。首先必須先宣告gettext物件。
const _ = imports.gettext.domain([DOMAIN]).gettext;
DOMAIN是字串,也就是目錄locale/[LOCALE]/LC_MESSAGES/下的mo檔名,通常會用extension的名稱來取名。接著在init function裏面填入
imports.gettext.bindtextdomain([DOMAIN], [LOCALE DIR PATH])
DOMAIN同上,LOCALE DIR PATH是locale的目錄路徑,有兩種方法可取得。首先,init function會傳入一個metadata的物件,這個metadata即extension目錄裡的metadata.json。metadata包含有path的屬性可以知道extension所在的路徑,兩種方式如下:
// 利用字串組合 metadata + "/locale" // 利用GLib GLib.build_filenamev([metadata.path, "locale"])
以上的設定等同於告訴gettext該從什麼路徑讀取和檔名是什麼。以上就是GSE設定國際化的過程了。
Reference:
留言