Daily Grind

システム開発関連の忘備録です

gettextによる多言語化

目次
1.gettextによる多言語化の基本的な処理手順
2.サンプル
3.懸念事項



1.gettextによる多言語化の基本的な処理手順
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄

(1) ソースコードに、"xgettext"で検出する為のマクロ定義を埋め込む。
  setlocale()など必要な前処理やヘッダファイルインクルードを組み込む。
(2) xgettextでメッセージを抽出し、翻訳のためのテンプレートファイル(.potファイル)を作成
(3) テンプレートファイルを基に各言語に翻訳し、テンプレートカタログ(.poファイル)を作成
(4) メッセージカタログをバイナリファイル(.moファイル)に変換する
(5) 作成したバイナリファイルをロケールディレクトリに置く。


2.サンプル
 ̄ ̄ ̄ ̄ ̄ ̄
以下のソースを多言語化してみる。

 【test.c】

#include <stdio.h>                     
                                       
char *msg = "GNU gettext excersize";   
                                       
int main() {                           
    puts("Hello, World!");             
    puts(msg);                         
    return 0;                          
}                                      

(1) ソースコードに、"xgettext"で検出する為のマクロ定義を埋め込む。
  setlocale()など必要な前処理やヘッダファイルインクルードを組み込む。

 【test.c】

#include <stdio.h>                                                                      
                                                                                        
/* setlocale() */                                                                       
#include <locale.h>                                                                     
                                                                                        
/* bindtextdomain(), textdomain() */                                                    
#include <libintl.h>                                                                    
                                                                                        
#define _(String) gettext(String)                                                       
#define N_(String) gettext_noop(String)                                                 
#define gettext_noop(String) (String)                                                   
                                                                                        
char *msg = N_("練習サンプル");                                                         
                                                                                        
int main() {                                                                            
    /* ロカール名を環境変数から取得 */                                                  
    setlocale(LC_ALL, "");                                                              
    /* ドメイン名"test"のメッセージカタログディレクトリをカレントディレクトリに設定 */  
    bindtextdomain("test", ".");                                                        
    /* ドメイン名を"test"に設定 */                                                      
    textdomain("test");                                                                 
	                                                                                     
    puts(_("こんにちは、世界!"));                                                      
    puts(_(msg));                                                                       
    return 0;                                                                           
}                                                                                       

コンパイル

	$ gcc -Wall -o test test.c   
	$ ./test                     

(2) xgettextでメッセージを抽出し、、翻訳のためのテンプレートファイル(.potファイル)を作成する

	$ xgettext -k"_" -k"N_" -o test.pot test.c --from-code=UTF-8  
	$ ./test                                                      

  ※キーワードに"_", "N_"の二種類を指定することで、両方のマクロが適用された翻訳対象文字列を抽出できる。

(3) テンプレートファイルを基に各言語に翻訳し、テンプレートカタログ(.poファイル)を作成する

$ cp test.pot en.po

  en.poを編集して英訳する。

 【en.po】

	"Content-Type: text/plain; charset=UTF-8\n"   ※今回のサンプルではUTF-8を指定した。
	...                                           
	#: test.c:13                                  
	msgid "練習サンプル"                          
	msgstr "GNU gettext excersize"                
	                                              
	#: test.c:23                                  
	msgid "こんにちは、世界!"                    
	msgstr "Hello, World!"                        


(4) メッセージカタログをバイナリファイル(.moファイル)に変換する

	$ msgfmt -o test.mo en.po           

(5) 作成したバイナリファイルをロケールディレクトリに置く。

	$ mkdir -p ja/LC_MESSAGES             
    $ cp test.mo en/LC_MESSAGES/test.mo   

(6) 動作確認

	$ LANG=C ./test                       
	こんにちは、世界!                    
	練習サンプル                          
	                                      
	$ LANG=en_US.UTF-8 ./test             
	Hello, World!                         
	GNU gettext excersize                 


3.懸念事項
 ̄ ̄ ̄ ̄ ̄ ̄
(1) LANG=Cの場合の表示。

 「LANG=C」では、動作的にはmsgidがそのまま出力されます。
 今回は、_("日本語")のメッセージカタログを持つことになるので
 「LANG=C」だと日本語リテラルで出力されます.

(2) ソースの文字コード

 ソースファイルの文字コードは統一しておく必要があります。
 既存ソースの文字コードが統一されていない場合は文字コードの変更が必要です。