複数の言語1に対応したアプリケーションを作成する際、多くの場合用いられるのがGNU gettext (以下gettext)と呼ばれるツールセットです。 gettextは様々なプログラミング言語に対応した国際化ツールです。公式のツールでも一般的なプログラミング言語が多数サポートされている他、公式ツールでサポートされていないプログラミング言語についても有志が対応ツールを作成しています。

gettextを用いたアプリケーションの国際化はgettext - Wikipedia を読むのがわかりやすいと思います。

扨、gettextを用いて国際化を行う場合、最終的な翻訳ファイルは .mo という拡張子を持ったバイナリファイルとなります。これを読み込むため2には、ファイルの構造がどうなっているのかを知らなければなりません。

基本的には公式のドキュメント に載っている通りですが、日本語の情報が少ないため、まとめておきます。

MOファイルは大きく分けて次の4つのパートに分かれています。

  • ヘッダー
  • 文字列情報
  • ハッシュテーブル
  • 文字列

このうち、とりあえずMOファイルを読むために必要な、ヘッダー、文字列情報、文字列の部分について解説します。

ヘッダー

ヘッダーはファイルの頭から4bytes区切りで読み込みます。 基本的には、次の7つの情報が含まれています。

  • マジックナンバー
  • ファイルフォーマットリビジョン
  • N: 文字列数
  • O: オリジナル文字列テーブルのオフセット
  • T: 翻訳文字列テーブルのオフセット
  • S: ハッシュテーブルの大きさ
  • H: ハッシュテーブルのオフセット

このほか、場合により追加でヘッダーが存在する場合もあります。 ハッシュテーブル情報とハッシュテーブルの開始点はO及びHで表現されるため、任意のヘッダーを追加することが可能です。

ヘッダーの各情報について、それぞれ見てみます。

マジックナンバー

おそらく、名前だけを見て一番よくわからないのがこの 「マジックナンバー」 だと思われます。 ここには、0x950412de もしくは 0xde120495 が入っています。 これはMOファイルが生成された時のバイトオーダーを示しており、 0x950412de の場合はビッグエンディアン0xde120495 の場合はリトルエンディアン で生成されたことを示しています。

ファイルフォーマットリビジョン

ファイル形式のリビジョンを示します。現状3、通常は0が入っています。

文字列数 N

公式ドキュメント では変数名Nとして説明されています。 本記事でもNとして説明します。 翻訳対象の文字列の数です。

オリジナル文字列テーブルのオフセット O

公式ドキュメント では変数名Oとして説明されています。 本記事でもOとして説明します。 翻訳前のオリジナル文字列テーブルの開始地点を示す32bit intの値です。 MOファイルのObyte目からオリジナルの文字列が格納されているということを表します。

翻訳文字列テーブルのオフセット T

公式ドキュメント では変数名Tとして説明されています。 本記事でもTとして説明します。 翻訳後の文字列テーブルの開始地点を示す32bit intの値です。 MOファイルのTbyte目から翻訳文字列が格納されているということを示します。

ハッシュテーブルの大きさ S

公式ドキュメント では変数名Sとして説明されています。 使用しなくてもMOファイルを読み解くことができるため、本記事では省略します。

ハッシュテーブルのオフセット H

公式ドキュメント では変数名Hとして説明されています。 使用しなくてもMOファイルを読み解くことができるため、本記事では省略します。

文字列情報

文字列情報部分は、MOファイルのObyte目からオリジナル文字列情報が、Tbyte目から翻訳文字列情報が始まり、8bytes区切りで値が格納されています。 さらに、8bytesのうち、前半4bytesが文字列の長さ、後半4bytesがオフセットを示します。

文字列情報部分にはN個のオリジナル文字列情報と、N個の翻訳文字列情報、あわせて2N個の文字列情報が含まれています。 文字列情報はオリジナル文字列情報と翻訳文字列情報が一対一で同じ添字を持つ様に並べられています。

文字列

文字列情報から得られたオフセットが示す位置から、得られた長さの部分に文字列が格納されています。 オリジナルの文字列情報と翻訳文字列情報を同じ添字で取り出すことで、対になった文字列を取り出すことができます。



  1. ここで「言語」は自然言語を意味します。本記事中では、プログラミング言語は「プログラミング言語」と表記します。 ↩︎

  2. 専用のライブラリを使わず、自力で処理する場合。 ↩︎

  3. 2017年11月6日現在。 ↩︎