寫在前面的話:
- 版權聲明:本文爲博主原創文章,轉載請註明出處!
- 博主是一個小菜鳥,並且非常玻璃心!如果文中有什麼問題,請友好地指出來,博主查證後會進行更正,啾咪~~
- 每篇文章都是博主現階段的理解,如果理解的更深入的話,博主會不定時更新文章。
- 本文最後更新時間:2020.4.29
正文開始
1. 舉個例子
myLang.c
#include <stdio.h>
#include <libintl.h>
#include <locale.h>
#define _(string) gettext(string)
int main()
{
bindtextdomain("myLang", "Lang/locale");
textdomain("myLang");
setlocale(LC_ALL, "zh_CN.UTF-8");
char notice[200] = {0};
sprintf(notice, "%s", _("hello world"));
printf("%s\n", notice);
return 0;
}
編譯並執行:
gcc myLang.c -o myLang #編譯
./myLang #執行
運行結果:
你好,世界
目錄結構:
2. 函數詳解
2.1 bindtextdomain() 函數
bindtextdomain()
- 設置文本域目錄
函數聲明如下:
#include <libintl.h>
char * bindtextdomain (const char * domainname, const char * dirname);
文本域文件
就是 .mo文件
,這個文件是二進制的(基於性能方面的考慮),在開發多語言軟件中會用到。
例如: 在英文環境下,程序打印 “hello world”,而在中文環境中需要打印 “你好,世界”,這時需要將翻譯放在 .po 文件中,再由 .po 文件生成 .mo 文件。
.po文件
格式如下:
msgid "hello world"
msgstr "你好,世界"
其中 msgid
爲原文,msgstr
爲翻譯內容。
.po 文件生成 .mo 文件命令:
msgfmt xxx.po -o xxx.mo
bindtextdomain() 有兩個參數:
- domainname:域名,即指明 .mo 文件將應用在哪個工程中,域名必須是非空字符串。
例如:示例工程叫 myLang,則 domainname 也爲 “myLang”。 - dirname:locale 目錄的路徑,即在這個指定的路徑下尋找 .mo 文件,相對路徑或絕對路徑都可以。
完整存放 .mo 文件的路徑一般爲 dirname/locale/category/domainname.mo
,其中:
- dirname:是我們設置的第二個參數,指定 locale 目錄的路徑。
- locale:指語言環境名稱。下面有各語言目錄,如:zh_CN。設置包含 LC_MESSAGES 分類 (catalog) 的 locale 目錄,程序的 .mo 文件保存在其下的 LC_MESSAGES 目錄中。
- category:是語言環境方面,例如 LC_MESSAGES,LC_MESSAGES 是 locale 的一個分類 (catalog)。
例如,示例程序完整的 .mo 文件路徑:
[程序當前目錄]/Lang/locale/zh_CN/LC_MESSAGES/myLang.mo
而示例代碼爲:
bindtextdomain("myLang", "Lang/locale");
2.2 setlocale() 函數
setlocale()
- 設定locale
函數聲明如下:
#include <locale.h>
char *setlocale(int category, const char *locale);
LC_ALL
適用於所有語言環境
示例代碼爲:
setlocale(LC_ALL, "zh_CN.UTF-8"); //設置爲中文環境
2.3 textdomain() 函數
textdomain()
- 設置文本域文件
函數聲明如下:
#include <libintl.h>
char * textdomain (const char * domainname);
該函數用於設置需要使用的文本域。即設置後來使用 gettext() 函數時的 domain。
即使用順序爲:
如果程序需要用到多個 .mo 文件,那麼需要多次執行 bindtextdomain() 函數,再用 textdomain() 來指定當前需要使用哪一個。
示例代碼爲:
textdomain("myLang");
2.4 gettext() 函數
函數聲明如下:
#include <libintl.h>
char * gettext (const char * msgid);
將程序中的 msgid 替換爲 .mo 中的 msgstr,並返回 msgstr。簡單講就是根據原文找到並返回翻譯的內容。
例如:
gettext("hello world"); //以中文爲例,返回“你好,世界”
示例代碼:
sprintf(notice, "%s", _("hello world"));
sprintf(notice, "%s", gettext("hello world"));
示例代碼中使用了宏 #define _(string) gettext(string)
,這樣可以簡化接下來的寫法,即工程中的 gettext("xxx")
可以用 _("xxx")
替換,兩者效果相同。
參考
bindtextdomain(3) - Linux man page
gettext(3) - Linux man page
textdomain(3) - Linux man page
setlocale(3) - Linux man page
msgfmt(1) - Linux man page