GNU gettext tools, version 0.18.3

Native Language Support Library and Tools

Edition 0.18.3, 16 June 2013

日本語訳: Ayanokoji Takesi(綾小路剛志)
日本語訳: Rue. SATOH(佐藤竜一) / Koichi KIMURA(木村浩一)
Ulrich Drepper
Jim Meyering
François Pinard
Bruno Haible

[ < ] [ > ]   [Contents] [Index] [ ? ]

GNU gettext utilities

This manual documents the GNU gettext tools and the GNU libintl library, version 0.18.3.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1 イントロダクション

このチャプターでは、GNU gettextが作られた目的と、フリーの翻訳プロジェクトについて説明します。それから、ネイティブ言語サポート(NLS: Native Language Support)にまつわる広義の概念をいくつか説明します。また国や文化の差異を他の側面から考慮した際に、翻訳したメッセージをプログラムに適用することが、どのような位置づけになるかを説明します。さらに翻訳に使用されるファイルを説明し、最初の翻訳において様々なツールがそれらのファイルをどのように生成、相互作用するのか、そして通常のメンテナンスサイクルにおいてどのように処理されるかについて説明します。

このマニュアルでは、プログラマーやメンテナーを指すときにはという言葉を使用します。そして翻訳者を指すときは彼女、翻訳されたプログラムをインストールする人やエンドユーザーのことを指すときは彼らという言葉を使用します。これの目的はドキュメントを明解にするのが唯一の目的であり、決して各々の役割が男性、もしくは女性に適しているという意味ではまったくありません。あなたが想像するように、GNU gettextは性別、人種、宗教、国籍に関わらず、コンピュータを使用する人にとって有用なものなのです!

提案や訂正は下記にメールしてください:

Internet address:
    bug-gnu-gettext@gnu.org

メールのメッセージに、マニュアルのバージョン番号と更新日付を記入してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1 GNU gettextの目的

プログラムは通常、英語でドキュメントされており、実行時にユーザーと相互作用する場合にも英語が使用されます。これはGNUソフトウェアに限らず、多くのフリーソフトウェアにも当てはまる話です。開発者やメンテナー、すべての国々のユーザー同士でコミュニケーションする場合、共通の言語を使用するほうが便利です。一方、ほとんどの人は英語より自分の母国語を好み、日々の仕事にも可能な限り母国語を使用しています。単純に言うと、ほとんどの人は英語より母国語がコンピューターのスクリーンに表示されるのを愛するのです。

しかし多くの人にとって、これは時間をかけて考える価値がないと片付けてしまう夢かもしれません。彼らは結局、この夢を実現できる自信がないのです。しかし希望を失わずに、組織を作った人たちもいます。この翻訳プロジェクトは、これらの希望を作業可能な形に形式化して、私たちのすべてが真の多言語機能を兼ね揃えたプログラムと呼べるものを手にするチャンスなのです。

GNU gettextは、他の多くのステップを構築する資産であり、翻訳プロジェクトにとって重要なステップです。このパッケージは、プログラマー、翻訳者、そしてユーザーにたいして、統合されたツールとドキュメントを提供します。特に GNU gettextユーティリティーは、他のパッケージに多言語化されたメッセージを生成するためのフレームワークを提供するツール群です。このツールには以下のものが含まれます:

GNU gettextは、プログラムのソースを国際化する際の影響を最小化し、その影響を可能な限り小さく保つようにデザインされています。プログラムソースを見たときに、その影響が軽微、または少なくとも軽微に見えることにより、国際化が成功する可能性が高くなります。

翻訳プロジェクトは、翻訳プロジェクトの構造や手法を記述する手段としても、GNU gettextディストリビューションを使用しています。これは、この文書がGNU gettextの技術面に限定して適切に記述された文書であることを超えるものであることを意味します。そうすることにより、翻訳者は翻訳作業を適切に行うために知る必要のあるすべてのことを、可能な限り単一の場所で見つけることができます。この補足的な文書により、プログラマーさらに好奇心のあるユーザーは、GNU gettextが翻訳プロジェクト以外の場所とどのように関連しているかを理解し、大きな絵を垣間見ることができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2 i18n、l10n、などなど

プログラムによるネイティブ言語サポートを議論する際に、2つの長い単語が出現します。これらの単語には正確な意味づけがあり、このドキュメントでも使用する単語なので、ここで説明しておきましょう。使用される2つの長い単語とは、インターナショナリゼーション(internationalization)ローカリゼーション(localization)です。これらの単語を何度も何度も書くうちに、多くの人たちがi18nl10nと記述するようになりました。この表現は単語の最初と最後の文字と、それらの文字の間にある文字数によって、それぞれの単語を略記したものです。しかしこのマニュアルではわかりやすくするために、略記を用いずに正式な単語を使用することにします。

インターナショナリゼーション(国際化)とは、プログラムやパッケージに含まれるプログラムのセットが多言語を認識しサポートする操作のことを指します。インターナショナリゼーションとは、英語の文字列でしかプログラムがを呼び出せないとか、英語以外の特定の言語の持つ習慣に縛られるといったことなく、同じ操作を一般的な方法で結びつけさせるための汎化のプロセスです。プログラムの開発者は、彼のプログラムをインターナショナライズするために様々なテクニックを使うことでしょう。それらのいくつかは標準化されています。そのうちの1つが GNU gettextなのです。プログラマーの視点を参照してください。

ローカリゼーション(地域化)とは、それを行うことによりすでにインターナショナライズされた一連のプログラムが必要とするすべての情報を受けとることができ、任意のネイティブ言語や文化的な習慣に従った方法による入出力に適応させることができるような操作のことを意味します。ローカリゼーションとは、一般的なメソッドを実装済みのインターナショナライズされたプログラムを特定の方法で使用する、特化のプロセスです。プログラミング環境はプログラマーにたいして、実行時に設定できるいくつかの機能を提供します。翻訳対象の単位として同じネイティブ言語同士をまとめた、任意の国がもつ特定の文化的な習慣の形式的な説明を、その言語や国のlocaleと呼びます。ローカライズされたプログラムを使用するユーザーは、プログラムを実行する前にプログラムがどのlocaleを使用するべきかを、特定の環境変数に設定します。

実際にはlocaleメッセージのサポートとは、特定のlocaleを形成する文化的なデータの単一のコンポーネントのことです。インターナショナライズされたソフトウェアを開発するプログラマーを支援するために、特定のlocale に保存されたデータにアクセスできるルーチンと関数を提供するライブラリーがあります。誰かが特定のlocaleを参照する場合には、特定のlocaleに保存されているデータを参照することになります。同様に、プログラマーが “locale ルーチンへのアクセス” を参照するということは、すべてのlocale情報にアクセスできる完全なルーチンの一式を参照するのと同じです。

ネイティブ言語サポート(Native Language Support、または単にNLS)という表現は、インターナショナリゼーションとローカリゼーションの両方により、プログラムが多言語と相互作用できる動作や機能の全体を指すときに使用します。一言で言うと、インターナショナリゼーションとはローカリゼーションを可能にする操作とも言えます。

大まかに言うと、多言語によるメッセージを処理する場合、インターナショナリゼーションはプログラマーによって処理され、ローカリゼーションは翻訳者によって処理されるとも言えます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3 ネイティブ言語サポートの側面

完全な多言語ディストリビューションを配付するためには、出力メッセージの翻訳以外に多くの事柄があります。

すでに述べたように、翻訳とはlocaleの1つの側面に過ぎません。インターナショナリゼーションの他の側面にはシステムのサービスがあり、これは GNU libcにより処理されます。国々の文化的な慣習を定義するための多くの属性があります。これらの属性には、国々のネイティブ言語に即した日付や、時刻書式と数値表記、通貨記号などが含まれます。これらの地域的なルールは、その国のlocaleと呼ばれます。localeとは、その国のネイティブな属性をサポートするために必要となる知識を表します。

国ごとの差異にしたがってlocaleを記述しなければならない、主要な領域がいくつかあります。以下のリストは、localeに関連したその他のタスクの適切なコンテキストにおいて、多言語メッセージを配置する手助けになるでしょう。詳細については GNU libcのマニュアルを参照してください。

文字とコードセット

米国や世界中の、英語を話す地域で最も一般的に使用されるコードセットは、ASCIIコードセットです。しかしこのコードセットには、様々なlocaleで必要とされる文字が含まれていません。8ビット ISO 8859-1コードセットは主要なヨーロッパの言語で処理する必要がある特殊文字をほとんど持っているにもかかわらず、主要なヨーロッパの通貨を処理することができない等、多くの場合はISO 8859-1を選択するだけでは十分ではないのです。したがってそれぞれのlocaleは、使用するコードセットの選択と、そしてそのコードセットに対処するための適切な文字列処理ルーチンが必要になります。

通貨

通貨記号は国ごとに異なり、それぞれの通貨記号の使用する位置も異なります。それぞれのlocaleにたいするネイティブモードで、ソフトウェアはそれを意識させずに通貨の数字を表示できる必要があります。

日付

日付の書式はlocaleごとに異なります。例えば1994年のクリスマスは、米国では12/25/94と記述し、オーストラリアでは25/12/94、それ以外の国ではISO 8601の日付書式を使用する、といった具合です。

1日の中で使用される時刻も、hh:mmhh.mm、などのように記述されます。あるlocaleでは時刻はAM/PMではなく、24時間制で指定する必要があります。しかも夏時間の補正は国ごとに大きく異なります。

数値

数値の表記はlocaleごとに異なります。以下はそれぞれのlocaleに対応する、正しい数値表記の例です:

12,345.67       English
12.345,67       German
 12345,67       French
1,2345.67       Asia

メートル法とポンドヤード法のように異なる単位系を使用したり、それらの変種で数値表記する方法を採用しているプログラムもあります。

メッセージ

localeによる言語サポートにおいて、最も明確な領域です。GNU gettextは、localeでのメッセージのサポートという領域において、ソフトウェアがユーザーとコミュニケーションするときに使用する言語を、開発者とユーザーが簡単に変更する手段を提供します。

これらの文化的な慣習の領域は、localeカテゴリー(locale categories)と呼ばれます。この用語は、localeの側面(locale aspects)locale機能のカテゴリー(locale feature categories)といった用語よりも劣っているのが残念です。なぜならそれぞれの“localeカテゴリー”は、ローカリゼーションが要求される、ある領域やタスクについて記述するからです。そのような領域や特定の文化にたいして、文化的な慣習を説明する具体的なデータもlocaleカテゴリーと呼ばれます。この意味では、localeとは、コードセットを定義するlocaleカテゴリー、数値の書式を定義するlocaleカテゴリー、翻訳されたメッセージを定義するlocaleカテゴリー、などのように、いくつかのlocaleカテゴリーから構成されているといえます。

メッセージ処理以外のlocaleコンポーネントは、標準ISO CとPOSIX:2001標準(SUSV3 specificationとも呼ばれる)です。GNU libcはこれを完全に実装しており、その他の現代的なシステムも、欠けているコンポーネントにたいする、必要最小限のより実用的なサポートを提供しています。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.4 翻訳を伝達するファイル

.poファイルのPOはPortable Objectの頭文字であり、.moファイルのMOはMachine Objectの頭文字です。このパラダイムはPOファイルのフォーマットと同様に、Uniforumで開発されたNLS標準にもとづき、SunのSolarisシステムで実装されたものです。

POファイルは人間が読んだり編集することを意図しており、あるパッケージの特定のターゲット言語のための、翻訳可能なオリジナル文字列の集まりです。1つの言語にたいして、1つのPOファイルが割り当てられます。パッケージが複数の言語をサポートする場合、サポートする言語ごとにPOファイルを持ち、パッケージごとにパッケージがサポートする言語ごとのPOファイルを持っています。これらのPOファイルはxgettextプログラムによって作成され、アップデートや更新はmsgmergeプログラムによって行われます。xgettextプログラムはCファイルからマークされたメッセージを抽出し、空の翻訳文字列で初期化されたPOファイルを作成します。msgmergeプログラムは、リリースの間に変更されたソースファイルにたいして、不要なエントリーのコメント化や新しい文字列の初期化、および参照するソース行を更新したりします。この種のファイルは配布物中にの.potという拡張子のファイルとして含まれ、書式はPOファイルと同じです。

MOファイルは、プログラムが読み込むことを意図した、バイナリーのフォーマットのファイルです。ネイティブ言語サポートの一部として、MOファイルを作成したり処理することのできる既存のシステムもいくつかありますが、MOファイルのフォーマットがシステムごとに異なっているため可搬性がありません。また、これらのシステムが提供する既存のツールは、GNU gettextのすべての機能をサポートしていません。そのためGNU gettextは、MOファイルに独自のフォーマットを使用しています。拡張子.gmoが実際のMOファイルで、これらのファイルはGNUのフォーマットを使用しています。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.5 GNU gettextの概要

以下は、GNU gettextで処理されるファイル群の関連と、それらを処理するツールをまとめたダイアグラムです。以降の詳細な説明は、このダイアグラムを見ながら読み進めてください。これらのファイルやツールの相互作用への明確な理解は、プログラマー、翻訳者、メンテナーにとって確実に役に立つものです。

Original C Sources ───> Preparation ───> Marked C Sources ───╮
                                                             │
              ╭─────────<─── GNU gettext Library             │
╭─── make <───┤                                              │
│             ╰─────────<────────────────────┬───────────────╯
│                                            │
│   ╭─────<─── PACKAGE.pot <─── xgettext <───╯   ╭───<─── PO Compendium
│   │                                            │              ↑
│   │                                            ╰───╮          │
│   ╰───╮                                            ├───> PO editor ───╮
│       ├────> msgmerge ──────> LANG.po ────>────────╯                  │
│   ╭───╯                                                               │
│   │                                                                   │
│   ╰─────────────<───────────────╮                                     │
│                                 ├─── New LANG.po <────────────────────╯
│   ╭─── LANG.gmo <─── msgfmt <───╯
│   │
│   ╰───> install ───> /.../LANG/PACKAGE.mo ───╮
│                                              ├───> "Hello world!"
╰───────> install ───> /.../bin/PROGRAM ───────╯

プログラマーが自分のパッケージにGNU gettextを導入するときに最初に行うことは、Cソース中のどの文字列が翻訳可能で、どの文字列が翻訳不可かを識別することです。この退屈な作業は、emacsのPO modeを使用することにより多少は快適になりますが、Cソースを編集するのに、あなた自身が慣れ親しんだものを使用することもできます。その他に必要となる標準的な変更としては、翻訳用のライブラリーを正しく初期化することなどです。これらに関する詳細はプログラムソースの準備を参照してください。

新しく記述するソフトウェアについては、ソフトウェアを記述するときにそのような文字列をマークできますし、そうするべきでしょう。このような文字列にたいするgettextのアプローチ方法としては、手始めに各ファイルの先頭または中心的なヘッダーファイルに、以下の行を追加するという、非常に簡単なものです:

#define _(String) (String)
#define N_(String) String
#define textdomain(Domain)
#define bindtextdomain(Package, Directory)

これで、インターナショナリゼーションのためのソースの準備ができました。後で実際にgettextを使う準備ができたら、これらを以下の定義で置き換えてください:

#include <libintl.h>
#define _(String) gettext (String)
#define gettext_noop(String) String
#define N_(String) gettext_noop (String)

libintl.alibintl.soにリンクする必要もあります。GNUシステムでは、gettextライブラリーの関数はGNU libcにすでに含まれているので、libintlにリンクする必要がないことに注意してください。

一度Cソースが変更されると、翻訳可能なすべての文字列を検索、抽出してPO templateファイルに出力するのに、xgettextが使用されます。このpackage.potファイルには、オリジナルのプログラムのすべての文字列が含まれています。これらの文字列は、その文字列がCソース中で使用されている場所へのポインターを持っており、すべての翻訳文字列は空文字列に初期化されています。.pottという文字は、このファイルがテンプレート(Template)のPOファイルであり、まだ特定の言語用ではないことを示します。どのようにxgettextプログラムが呼び出されるかについては、xgettextプログラムの呼び出しを参照してください。もしあなたが本当に怠け者の場合、少し手間をかけてディストリビューション全体をセットアップするのに興味があるかもしれません(メンテナーの視点を参照してください)。この方法では、xgettextコマンドをタイプするのを省略してmakeとタイプするだけで、自動的に適切なものを生成することができます。

最初はまだlang.poがないので、msgmergeのステップはとばして、単にpackage.potlang.poとしてコピーされます。ここでlangは対象となる言語です。詳細については、新しいPOファイルの作成を参照してください。

次はメッセージの最初の翻訳です。翻訳それ自身が全体として今だ人手に頼らねばならないものであり、その複雑さはこのマニュアルの取り扱う範囲を超えるものです。翻訳チームに連絡したり、チームの一員になって、同じネイティブ言語を作業対象とする他の人たちとあなたの翻訳を共有する方法等、いくつかのヒントについては、このマニュアルの他のチャプターで触れています(翻訳者の視点を参照してください)。

POファイルlang.poに翻訳したメッセージを追加するときに、POファイル編集用のエディター(POファイルの編集を参照してください)を使用していない場合は、POファイルのフォーマットに合わせて作業したり、文字列を引用符で括る規則など(POファイルのフォーマットを参照してください)について自分で気を遣わなければなりません。これは不可能な作業ではなく、実際に1995年頃には多くの人がPOファイルを取り扱っていた方法です。一方、POファイルエディターは、POファイルエディター自身の使い方を覚える必要はありますが、あなたにかわってエディターがPOファイルに関する詳細を取り扱ってくれます。

既に何らかの翻訳がCompendium POファイルに保存されている場合、翻訳者はPOモードを使って翻訳されていないエントリーをCompendiumから初期化したり、翻訳を選択してCompendiumに保存したり更新することができます(翻訳compendiaの使用を参照してください)。Compendiumファイルは、翻訳チームのメンバー間で共有するように意図されたものです。

プログラムやプログラムのパッケージは、ユーザーがバグ報告や改良のための提案をして、メンテナーが様々な方法でプログラムを変更して対応するという、動的な性質を持ちます。パッケージがすでにインターナショナライズされているという事実により、メンテナーがパッケージに文字列を追加したり、すでに翻訳された文字列を変更することをためらうようにさせるべきではありません。彼らは、彼ら自身がスムーズに作業できるようにベストを尽くすだけです。メンテナーはすでに負荷の掛かった双肩に、翻訳に関する心配事を背負いこまなないようにしてください。そして翻訳者はプログラミングの心配事からは自由でいるようにしてください。

メンテナーが心配すべきなのは、文字列が翻訳されるべきときに翻訳可能であるように文字列をマークすることであり、文字列がいつ翻訳されるかについては、適切な時がくれば翻訳されるものだと割り切るべきです。xgettextは、時間をかけて進化してきたpackage.potを再び構築し、その結果、翻訳を含んだlang.poは徐々に古くなっていきます。

翻訳者(そしてメンテナー)にとって重要なのは、パッケージの翻訳はパッケージが誕生した時に1度行えばよいというものではなく、パッケージの生涯において繰り替えされる継続的なプロセスだと理解することです。あるパッケージにたいして最初の翻訳を行った後、時々手入れをすることが必要です。なぜなら翻訳が必要な新しい未翻訳の文字列が出現することにより、翻訳された文字列があちこちで古くなっていくからです。

msgmergeプログラムは、すでに存在するlang.poファイルを、xgettextで最新の C ソースから抽出された、より新しいpackage.potテンプレートファイルと比較して更新するという目的を持っています。更新の処理はプログラムの変更により変更された、Cソース中の文字列の位置にたいする参照を調整します。同様に、msgmergeはすでに翻訳されているがプログラムのソースに存在しなくなった、古い翻訳のコメントアウトも行います(陳腐化したエントリーを参照してください)。そして最後に新しい文字列を未翻訳の文字列として、結果であるPOファイルに挿入します(未翻訳エントリーを参照してください)。msgmergeが実際に何を行うかについては、msgmergeプログラムの呼び出しを参照してください。

目的に至る経路と手段が何であれ、翻訳のためのすべての文字列を提供する更新されたlang.poがゴールなのです。

POファイルが変動し流動する一時的なものであるという性質は、翻訳というゲームでの不可欠な部分であり、よく理解して受け入れる必要があります。翻訳プロジェクトに参加する人はこの性質に苦労し、他の翻訳プロジェクトのメンバーに苦労をかけることもあるのです! 特にメンテナーは、たとえ最近は更新されていないディストリビューションでも、翻訳チームに早く仕事を終えるようにプレッシャーを与えず、リラックスして利用可能でオフィシャルなすべてのPOファイルをディストリビューションに含めましょう。プレッシャーを与えるのはむしろ、特定の言語を話すコミュニティーのユーザーなので、メンテナー自身も安心して翻訳ファイルの妥当性を考慮するべきです。一方翻訳者は、パッケージがオフィシャルのディストリビューションに向けた事前テストを行っているときに、自分が担当するPOファイルを合理的に更新する事を試みる必要があります。

1度POファイルが完成して信頼できる物になると、POファイルはmsgfmtプログラムによって、パッケージのプログラムが実行時に必要な時はいつでも効率的に翻訳を取得できるよう、マシン向けのフォーマットに変換されます(GNU MOファイルのフォーマットを参照してください)。msgfmtプログラムのすべての実行モードについては、msgfmtプログラムの呼び出しを参照してください。

最後に、変更およびマークされたCソースがコンパイルされて、GNU gettextライブラリーとリンクされます。これは通常、プロジェクトのための適切なMakefileと共に、makeコマンドを実行することにより行われ、結果としてユーザーが見つけることのできる場所に実行可能ファイルがインストールされます。MOファイル自身も適切にインストールされる必要があります。これで適切な環境変数(環境変数を通じたlocaleのセッティングを参照してください)をセットすると、プログラムを実行すればいつでも自分で自動的にローカライズするようになります。

このマニュアルの残りの部分では、上述の様々なステップを掘り下げて説明することを目的とします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2 ユーザーの視点

最近では、ユーザーがコンピューターにログインしたときには通常、プログラムがネイティブ言語でメッセージを表示するのを目にすることができます – 少なくともフリーソフトウェアやGNUプロジェクトに関わる人が少ないHindiやFilipinoなどの言語ではない、FrenchやGermanなどの言語による活発なフリーソフトウェアコミュニティーのユーザーは目にすることができるでしょう。

これはどのような仕組みで動くのでしょう? ユーザーはどのようにして、プログラムで使用する言語にたいして影響を与えることができるのでしょうか? このチャプターではこれらの疑問にお答えします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.1 オペレーティングシステムのインストール

デフォルトで使用する言語は、すでにオペレーティングシステムのインストールの時点で決定されている場合があります。オペレーティングシステムがインストールされるときは通常、インストーラーがインストール中に使用する言語とは別に、インストールされるシステムで使用する言語を尋ねます。言語を1度しか尋ねないOSインストーラーもあります。

これにより、すべてのユーザーにたいする、システム全体でのデフォルト言語が決定されます。追加の言語としてデフォルト言語以外のローカリゼーションを指定できるインストーラーもあります。たとえばKDE(K Desktop Environment)のローカリゼーションやOpenOffice.orgは、言語ごとにインストールできるパッケージが個別にバンドルされています。

これはマシンの使用目的を考える、よい機会です。個人的に使用するマシンの場合、追加のローカリゼーションはおそらく必要ありません。国際的なつながりをもつ組織や企業で使用するマシンの場合、ゲストユーザーのことも考えられます。海外から1週間程度の予定でゲストを迎える場合、彼のお好みのlocaleは何でしょうか? そのコストがディスクスペースを少し余分に消費するだけならば、あらかじめ追加のローカリゼーションをインストールする価値があるかもしれません。

システム全体のデフォルト言語は、新しいアカウントを作成するときのlocale設定で使用されます。しかしユーザーは同じマシンの他のユーザーとは異なる、自分自身のlocale設定を持つことができます。次のセクションで説明するようにユーザーは通常、最初のログイン後に自分のlocaleを指定することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.2 GUIプログラムを使用したlocaleのセッティング

すぐに利用可能なプログラムは、“デスクトップ環境”とも呼ばれるユーザーのデスクトップで、それにはウィンドウマネージャーやウェブブラウザー、それにテキストエディターなどが含まれます。一般的なデスクトップとしてはKDE、GNOME、Xfceなどがあります。

デスクトップ環境のGUIプログラムで使用されるlocaleは、“control center”、“language settings”、“country settings”などと呼ばれる設定画面で指定できます。

デスクトップ環境に属さない個別のGUIプログラムは、設定パネルや環境変数を通じて、自身のlocaleを持つことができます。

環境変数を通じてlocaleを指定できるプログラムには、デスクトップのlocaleとは異なるlocaleを指定できるものもあります。これはプログラムをメニューやファイルシステムから起動するかわりに、コマンドラインから環境変数を指定した後にプログラムを起動するということです。環境変数の設定については、次のセクション(環境変数を通じたlocaleのセッティング)で説明します。ただしKDEのあるバージョンでは、localeをLANGLC_ALLではなくKDE_LANGで設定します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3 環境変数を通じたlocaleのセッティング

もっとも単純なケースは、あなたの言語がこのパッケージにしたがってインストールされている場合で、環境変数LANGに適切な‘ll_CC’の組み合わせを指定するだけです。たとえばあなたがGermanyに住んでいてGermanを話すとしましょう。この場合はシェルプロンプトで単に、‘setenv LANG de_DE(cshの場合)、‘export LANG=de_DE(shの場合)、‘export LANG=de_DE(bashの場合)と実行します。1度これを.login.profileに記述しておけば、毎回適用することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.1 locale名

localeの名前は通常、‘ll_CC’という形式で表されます。ここで‘ll’はISO 639による2文字の言語コード、‘CC’はISO 3166による国コードを記述します。たとえば国がGermany、言語がGermanの場合、lldeCCDEとなります。言語コードと国コードについては、付表Language Codesと付表Country Codesを参照してください。

国コードも指定するのは冗長だと思うかもしれません。しかし、実際にいくつかの言語は国ごとに方言をもつものがあります。たとえば、‘de_AT’はAustria、‘pt_BR’はBrazilで使用されます。国コードはこの様な方言を区別するのに役立つのです。

多くのlocale名は‘ll_CC.encoding’という拡張形式で文字のエンコーディングを指定できます。これは多くのユーザーが2000年から2005年にかけてUTF-8に移行したためです。たとえば現在のglibcシステムのGerman localeは‘de_DE.UTF-8’です。‘de_DE’という古いlocale名は、2000年時点で使用されていたISO-8859-1(ユーロ通貨記号を持たない)が格納された文字列を参照するのに現在も使用されます。

ll_CC’のかわりに、‘ll_CC.@variant’を使うlocale名もあります。‘@variant’により、言語(ll)と国(CC)では提供できないような特性を示すことができます。これにより特定の通貨単位を示すことができます。たとえばglibcシステムでは‘de_DE@euro’は、2002年以前の通貨記号で使用されていた‘de_DE’ではなく、ユーロ通貨を使用するlocaleを示します。また、言語の方言や筆記に使用される方法(たとえば‘sr_RS@latin’は、‘sr_RS’によりSerbianをCyrillicで筆記するのに、Latin筆記を使用することを示す)、正書法(orthography rule)を使用するか、などを示すことができます。

その他のシステムでは、単に‘ll’と指定したりする等、このスキームの様々なバリエーションが使用されています。あなたの言語でサポートされているlocaleの一覧は、‘locale -a | grep '^ll'’を実行して取得することができます。

C’と呼ばれる特別なlocaleもあります。これはすべてのlocaleを無効にするときに使用します。このlocaleでは、すべてのプログラムがPOSIX標準で指定された英語のメッセージと、指定されていない不特定の文字(たいていはUS-ASCIIですが、オペレーティングシステムによってはISO-8859-1やUTF-8のときもあります)を使用します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.2 localeの環境変数

localeは複数のlocaleカテゴリー(locale categories)から構成されています(ネイティブ言語サポートの側面を参照してください)。プログラムがlocaleに依存する値を参照する場合は、以下の環境変数を優先度順に参照します:

  1. LANGUAGE
  2. LC_ALL
  3. LC_xxxは、xxxに対応するlocaleカテゴリーです: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES, ...
  4. LANG

変数に空の値がセットされている場合は、無視されます。

LANGはlocaleを指定するときに通常使われる環境変数で、通常はユーザーもこの変数にlocaleを設定します(他の変数がシステムにより設定されていなければ、/etc/profileまたはそれに類する初期化ファイルで設定します)。

LC_CTYPELC_NUMERICLC_TIMELC_COLLATELC_MONETARYLC_MESSAGES等は、対応するlocaleのカテゴリーでLANGの設定をオーバーライドするときに使用されます。たとえば、あなたがSpainに住むSwedishのユーザーで、プログラムに数値や日付についてはSpanishの規則で表示し、メッセージだけをSwedishで表示させたいと仮定します。その場合にはlocaledefプログラムで、‘sv_ES’または‘sv_ES.UTF-8’という名前のlocaleを作成する必要があります。しかし、単にLANG変数にes_ES.UTF-8を設定し、LC_MESSAGES変数にsv_SE.UTF-8という、オペレーティングシステムに事前にインストールされている2つのlocaleを設定することで、同じ効果を得ることができます。

LC_ALLは、これらのすべてをオーバーライドするための変数です。これは通常、特定のプログラムを実行するスクリプトで使用されます。たとえばGNU autoconfにより生成されたLC_ALLスクリプトは、configurationのテストがlocaleに依存した方法で行われないように、LC_ALLを使用します。

残念ながらいくつかのシステムでは、/etc/profile等の初期化ファイルでLC_ALLが設定されています。したがってLANGを設定する場合、ユーザーはまずこの設定を解除し、必要なら他のLC_xxxも解除しなければなりません。

LANGUAGE変数については、つぎのセクションで説明します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.3 言語の優先リストを指定する

すべてのプログラムが、すべての言語に翻訳されている訳ではありません。翻訳されたメッセージが存在しない場合、デフォルトでは英語のメッセージが表示されます。あなたが他の言語を理解できる場合は、言語の優先順位のリストを設定することができます。これはLANGUAGEと呼ばれる環境変数で行います。GNU gettextはメッセージを処理するために、LC_ALLLANGに加え、LANGUAGEによる設定を提供します。しかし他のシステムライブラリーで必要となるため、LANG(またはLC_ALL)によるプライマリー言語の設定は、依然として必要です。たとえば、あるSwedishのユーザーは、Swedishの翻訳が存在しないとき、EnglishよりもGermanに翻訳されたものが読みたいとします。そのような場合は、LANGの値は‘sv_SE’のまま、LANGUAGEの値を‘sv:de’に設定します。

Norwegianのユーザーのためのアドバイス: Norwegian言語(bokmål)は最近(2003年)、‘no’から‘nb’に変更されました。移行期間中、いくつかのこの言語のメッセージカタログは、‘nb’と、古い‘no’にインストールされるので、Norwegianユーザーは新旧どちらの翻訳も使用できるように、LANGUAGEを‘nb:no’に設定することをお勧めします。

他の環境変数とは異なり、LANGUAGE環境変数では、‘ll_CC’を‘ll’と省略することにより、その言語で主に使用される方言であることを示します。この事情により、たとえば‘de’は‘de_DE’(Germanyで話されるGermany)、‘pt’は‘pt_PT’(Portugalで話されるPortuguese)と同義です。

注意: LANGUAGE変数は、localeが‘C’に設定されている場合は無視されます。つまり、最初にローカリゼーションを利用可能にする時に、LANGUAGE変数で言語の優先順位リストを使用する前に、まずLANG(またはLC_ALL) を‘C’以外に設定する必要があります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4 特定のプログラムにたいして翻訳をインストールする

GNU gettextを使用するすべてのパッケージが、各言語にたいして同様のサポートを提供している訳ではなく、翻訳は時間をかけて個々に追加されます。パッケージをインストールした後は通常、オペレーティングシステムか個々のパッケージに同梱された翻訳を使用することになります。しかし新しいローカリゼーションを直接インストールすることもできます。これを行うには、ローカリゼーションの各ファイルがファイルシステム上でどのように保存されているかを理解する必要があります。

翻訳プロジェクトに参加しているプログラムは、http://translationproject.org/team/index.htmlで見つけることができます。この情報のスナップショットは、GNU gettextに同梱されているABOUT-NLSで確認することもできます。

KDEプロジェクトのプログラムを探す場合の出発点: http://i18n.kde.org/

GNOMEプロジェクトのプログラムを探す場合の出発点: http://www.gnome.org/i18n/

他のプログラムに関しては、プログラムのソースコードパッケージにll.poのようなファイルが含まれているかどうかでチェックすることができます(po/というディレクトリーに保存されているときもあります)。各ll.poには、llで略記された言語の翻訳されたメッセージが含まれています。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3 POファイルのフォーマット

GNU gettextツールセットは、プログラマーや翻訳者が翻訳のためのファイルを生成、更新、使用する手助けをし、それらのPOファイルは主としてテキスト形式で編集可能なファイルです。このチャプターでは、POファイルのフォーマットについて説明します。

POファイルは多くのエントリーから成り立っており、それぞれのエントリーには翻訳される前の原文の文字列と、それに対応する翻訳された文字列との関連が保持されています。あるPOファイルに含まれるすべてのエントリーは通常、ひとつのプロジェクトに関連し、翻訳されたすべての文字列もひとつの言語を対象に翻訳されたものです。一般的なPOファイルのエントリーは、以下のような構造を持ちます:

white-space
#  translator-comments
#. extracted-comments
#: reference…
#, flag…
#| msgid previous-untranslated-string
msgid untranslated-string
msgstr translated-string

翻訳者は、POファイルの一般的な構造を十分に理解する必要があります。emacsのPOモードを使用すれば、フォーマットの詳細に関する最小限の知識を理解するだけで、あとはPOモードが彼女にかわって面倒を見てくれます。

以下は簡単なエントリの例です:

#: lib/error.c:116
msgid "Unknown system error"
msgstr "Error desconegut del sistema"

エントリーは任意の個数の空白文字から開始することができます。GNU gettextツールで生成された場合、エントリーとエントリーの間には通常、1つの空行があります。#の文字で始まる行はすべてコメント行として扱われます。コメントには2種類のコメントがあります。1つ目はtranslator comments(翻訳者コメント)で、#の直後にいくつかの空白文字があり、これらのコメントは翻訳者により保守、保守されます。2つ目のコメントはautomatic comments(自動コメント)で、これらのコメントはGNU gettextツールにより自動的に挿入、保守されるもので、#の直後に空白文字以外の文字があります。#.で始まるコメントはプログラマーによる翻訳者に向けたコメントを含んでいます。これらのコメントはxgettextプログラムによりプログラムのソースから抽出(extract)されるため、extracted comments(抽出コメント)と呼ばれます。#:で始まるコメントには、プログラムのソースコードへの参照(references)が含まれます。#,で始まるコメントにはフラグ(flags)が含まれています。これらのフラグについては以下で説明します。#|で始まるコメントには、以前のバージョンの翻訳済みメッセージに対応する翻訳前の文字列(previous untranslated string)が含まれています。

すべてのコメントは、オプションです。

空白文字とコメントの後には、2つの文字列を表すための文字列があります。最初の文字列は翻訳前の文字列で、これらの文字列のオリジナルはプログラムのソース中に出現する文字列です。その次の文字列は、この翻訳前の文字列に対応する翻訳後の文字列です。オリジナルの文字列はmsgidというキーワードで識別され、翻訳はmsgstrというキーワードで識別されます。これらの翻訳前と翻訳後の2つの文字列は、POファイル中で"区切りや\エスケープにより、様々な方法で引用されていますが、文字列の引用などについてはPOモードが彼女にかわり面倒をすべて見てくれるので、翻訳者はそれらの正確な引用形式に注意を払う必要がなくなります。

msgidの文字列も自動生成されたコメントと同様、GNU gettextの他のツールにより生成、管理されるので、POモードは翻訳者がそれらを変更するような操作を提供しません。それらの文字列にたいして彼女にできることは、単にそれを削除することだけで、しかもエントリー全体を削除できるだけです。一方、msgstrの文字列については、実際に翻訳者が編集するための翻訳者コメントなので、POモードは彼女の必要に応じて、完全な制御を提供します。

#,で始まるコメントは、一般的なコメントとは違いプログラムにより完全に無視されるものではないという点で、特別なコメントです。カンマで区切られたflagのリストは、ユーザーのためにより良い診断メッセージを提供するために、msgfmtプログラムにより使用されます。現時点では2つの形式のflagが定義されています:

fuzzy

このフラグはmsgmergeプログラムにより生成されるか、翻訳者自身により挿入され、msgstrの文字列が、(もはや)正しい翻訳ではないことを示します。翻訳をさらに修正する必要があるか、そのまま適用できるかは、翻訳者だけが判断できます。翻訳を完成したら、彼女はfuzzy属性を取り除きます。msgmergeは、あいまい検索(fuzzy search)によりmsgidmsgstrエントリーを結びつけた場合のみ、このフラグを挿入します。fuzzyエントリーを参照してください。

c-format
no-c-format

これらは人間によって追加されるフラグではなく、xgettextプログラムだけが挿入するフラグです。ここで提案しているようなPOファイルを自動生成するシステムでは、ユーザーが変更を行っても、xgettextプログラムが新しいテンプレートファイルを生成するたびに、変更は上書きされてしまいます。

c-formatフラグは、翻訳前の文字列と翻訳された文字列が、C形式の文字列であることを示します。no-c-formatフラグは逆に、文字列が一見して(‘%’ディレクティブによる)C形式の文字列に見えても、C形式ではないことを示します。

文字列にc-formatフラグが設定されていると、msgfmtプログラムは、翻訳にたいして妥当性チェックのテストを追加で行います。msgfmtプログラムの呼び出し、およびキーワードの前の特別なコメントCフォーマット文字列を参照してください。

objc-format
no-objc-format

Objective Cの場合も同様です。Objective Cフォーマット文字列を参照してください。

sh-format
no-sh-format

shellの場合も同様です。Shellフォーマット文字列を参照してください。

python-format
no-python-format

Pythonの場合も同様です。Pythonフォーマット文字列を参照してください。

python-brace-format
no-python-brace-format

Python braceの場合も同様です。Pythonフォーマット文字列を参照してください。

lisp-format
no-lisp-format

Lispの場合も同様です。Lispフォーマット文字列を参照してください。

elisp-format
no-elisp-format

Emacs Lispの場合も同様です。Emacs Lispフォーマット文字列を参照してください。

librep-format
no-librep-format

librepの場合も同様です。librepフォーマット文字列を参照してください。

scheme-format
no-scheme-format

Schemeの場合も同様です。Schemeフォーマット文字列を参照してください。

smalltalk-format
no-smalltalk-format

Smalltalkの場合も同様です。Smalltalkフォーマット文字列を参照してください。

java-format
no-java-format

Javaの場合も同様です。Javaフォーマット文字列を参照してください。

csharp-format
no-csharp-format

C#の場合も同様です。C#フォーマット文字列を参照してください。

awk-format
no-awk-format

awkの場合も同様です。awkフォーマット文字列を参照してください。

object-pascal-format
no-object-pascal-format

Object Pascalの場合も同様です。Object Pascalフォーマット文字列を参照してください。

ycp-format
no-ycp-format

YCPの場合も同様です。YCPフォーマット文字列を参照してください。

tcl-format
no-tcl-format

Tclの場合も同様です。Tclフォーマット文字列を参照してください。

perl-format
no-perl-format

Perlの場合も同様です。Perlフォーマット文字列を参照してください。

perl-brace-format
no-perl-brace-format

Perl braceの場合も同様です。Perlフォーマット文字列を参照してください。

php-format
no-php-format

PHPの場合も同様です。PHPフォーマット文字列を参照してください。

gcc-internal-format
no-gcc-internal-format

GCCソースの場合も同様です。GCC internalフォーマット文字列を参照してください。

gfc-internal-format
no-gfc-internal-format

GNU Fortranコンパイラーのソースの場合も同様です。GFC internalフォーマット文字列を参照してください。

qt-format
no-qt-format

Qtの場合も同様です。Qtフォーマット文字列を参照してください。

qt-plural-format
no-qt-plural-format

Qt plural形式の場合も同様です。Qtフォーマット文字列を参照してください。

kde-format
no-kde-format

KDEの場合も同様です。KDEフォーマット文字列を参照してください。

boost-format
no-boost-format

Boostの場合も同様です。Boostフォーマット文字列を参照してください。

lua-format
no-lua-format

Luaの場合も同様です。Luaフォーマット文字列を参照してください。

javascript-format
no-javascript-format

JavaScriptの場合も同様です。Java Scriptフォーマット文字列を参照してください。

以下のように、context specifier(コンテキスト指定子)をともなうエントリーも使用することができます:

white-space
#  translator-comments
#. extracted-comments
#: reference…
#, flag…
#| msgctxt previous-context
#| msgid previous-untranslated-string
msgctxt context
msgid untranslated-string
msgstr translated-string

コンテキスト(context)は、同じuntranslated-stringのあいまいさをなくすために提供されます。これによりPOファイルの中で、異なるcontextで、同じuntranslated-stringを複数もつことが可能になります。contextに空の文字列を指定するのと、msgctxtの行を指定しないのは、同じではないことに注意してください。

他にも、複数形式(plural form)を含む翻訳のために使用されるエントリーがあります。

white-space
#  translator-comments
#. extracted-comments
#: reference…
#, flag…
#| msgid previous-untranslated-string-singular
#| msgid_plural previous-untranslated-string-plural
msgid untranslated-string-singular
msgid_plural untranslated-string-plural
msgstr[0] translated-string-case-0
...
msgstr[N] translated-string-case-n

以下はエントリーの例です:

#: src/msgcmp.c:338 src/po-lex.c:699
#, c-format
msgid "found %d fatal error"
msgid_plural "found %d fatal errors"
msgstr[0] "s'ha trobat %d error fatal"
msgstr[1] "s'han trobat %d errors fatals"

msgidの前に、前述したmsgctxtコンテキストを指定することもできます。

ここで追加のフラグを使用できます:

range:

このフラグは正の数値範囲をともない、range: minimum-value..maximum-valueという書式で使用します。この範囲には、メッセージが受けとることができる数値を指定します。たとえばある言語では、事前に値が0から10だとわかっていれば、よりよい翻訳を生成できます。

previous-untranslated-stringは、msgmergeがメッセージをfuzzyとしてマークするとき同時にオプションとして挿入されます。これは開発者が、untranslated-stringにたいしてどのような変更を行ったかを、翻訳者が知る助けになります。

これは、POファイルの最後のエントリーに続けて、何らかの行(通常は空白文字やコメント)があるときに発生します。これらの行は、どのエントリーの一部でもなく、POファイルがツールにより処理されるときに捨てられるか、POファイルエディターの動作を妨げるときもあります。

このチャプターの残りの部分は、POファイルの正確な書式にたいしてよいアイデアを持つ人は興味があるかもしれませんが、POファイルエディターを使用する場合はスキップして構いません。しかし、POファイルを手で変更したい場合は、注意して読む必要があります。

空のuntranslated-stringは、メタ情報が含まれたヘッダーエントリー(ヘッダーエントリーを入力するを参照してください)のために予約されています。このヘッダーエントリーはファイルの最初のエントリーにすべきです。空のuntranslated-stringは、この目的のために予約されているので、他の場所で使用することはできません。

untranslated-stringtranslated-stringはCの文法に従い、それには文字列の括り方やバックスラッシュによるエスケープシーケンスも含まれます。複数行のメッセージを記述するときは、エスケープされた改行文字を使用せずに、改行する行末の最後の文字で引用符を閉じて、POファイルの次の行で再び引用を開始します:

msgid ""
"Here is an example of how one might continue a very long string\n"
"for the common case the string represents multi-line output.\n"

この例の最初の行には、‘for’のfという文字の上に‘Here’のHを揃えるために、空の文字列が使用されています。また、キーワードmsgidの後ろには3つの文字列があり、それらの文字列は連結して使用されます。空の文字列と連結することにより文字列全体は変更されませんが、msgidの行に連結される文字列を、複数行の表示を維持しつつ左揃え表示して、配置を明確にさせるための方法です。空の文字列は省略できますがその場合、msgidの後ろに記述する最初の行は‘Here’で開始しなければなりません2。それぞれの文字列の括りの終端を改行(‘\n’)の直後にしている理由は、そうしても支障がないからというだけで、任意の文字の後で括りを終端して構いません。

文字列の括りの内側にある、行末を示す‘\n’は文字列の一部で、文字列の括りの外側の改行はPOファイル自身の行末を示し、文字列に影響を与えない点に注意してください。

文字列の外側では、空白文字とコメントを自由に使うことができます。行頭の‘#’から、その行の行末までがコメントとなります。翻訳者が記入するコメントは‘#’の後ろに空白文字をいくつか記述する必要があります。‘#’の後ろに空白文字がない場合、それは特定のGNUツールで生成・管理されるコメントとみなされ、POファイルがmsgmergeで処理されるとき、予期せず削除される可能性があります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4 プログラムソースの準備

プログラマーのために、Cのソースコードの変更を3つにカテゴリーに分けます。1番目は、ローカリゼーション関数にメッセージ翻訳を必要とするすべてのモジュールを教えることです。2番目は、プログラムの初期化(通常はmain関数の内部)で、GNU gettextの操作を的確にトリガーすることです。3番目に、翻訳が必要なプログラム内のすべての文字列定数を識別・調整・マークする必要があります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1 gettext宣言のインポート

GNU gettextが必要とするすべてのファイルが利用可能で、Makefileファイルも調整済み(メンテナーの視点を参照してください)だとすると、翻訳対象の文字列を含むCモジュールには以下の行を含める必要があります:

#include <libintl.h>

翻訳可能なCの書式指定文字列(他のCモジュールで文字列が定義されている場合も含まれます)を引数として呼び出される、printf()/fprintf()/...を含むCモジュールにも以下の行を含める必要があります:

#include <libintl.h>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2 gettext処理のトリガー

すべてのプログラムで、以下で示すようなlocaleデータの初期化の類が必要となります:

int
main (int argc, char *argv[])
{
  …
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);
  …
}

PACKAGELOCALEDIRは、config.hかMakefileで提供される必要があります。詳細については、gettextやGNU helloのソースを眺めてみるとよいでしょう。

この場合、LC_ALLの使用は適切ではないでしょう。LC_ALLLC_ALLにはすべてのlocaleカテゴリー、特にLC_CTYPEが含まれます。この後者のカテゴリーは、プログラムのためにctype.hで定義されている、isalnum関数などで処理する文字列クラスを決定することに責任をもっており、入力される文字列の言語によってはうまく動作しません。たとえばソースコードでç(c-cedilla文字)が使用されている場合、このプログラムはFranceでは問題ありませんがU.S.では動作しません。

LC_ALLというlocaleカテゴリーに他のlocaleが使用された場合、scanf関数による数字の解析に問題が生じるシステムもあります。標準では、このような場合は"C"というlocaleとして知られる追加の書式が認識されるでしょう。しかし"C"というlocaleの書式では、数値を受け付けないシステムもあるようです。状況によっては数値の表示が"C"というlocaleなのか、それともlocalのフォーマットかにより認識できないこともあります。これは千単位の桁区切り文字を使用するときに発生します。いくつかのlocale定義ではnational conventionに従い、桁区切り文字として'.'を使用しますが、この文字は"C"というlocaleでは小数点として使用されます。

これらの理由により、上記のコードのLC_ALLの行は、setlocaleによる行に分けることが必要な場合もあります。

{
  …
  setlocale (LC_CTYPE, "");
  setlocale (LC_MESSAGES, "");
  …
}

POSIX互換のすべてのシステムでは、LC_CTYPELC_MESSAGESLC_COLLATELC_MONETARYLC_NUMERICおよびLC_TIMEが利用できます。ISO C準拠のみのシステムも存在し、それらのシステムにはLC_MESSAGESがありませんが、これらの不足にたいする代替は GNU gettextの<libintl.h>と、GNU gnulibの<locale.h>で定義されています。

LC_CTYPEを変更すると、<ctype.h>という標準ヘッダーファイルで定義されている関数、および<string.h><stdlib.h>という標準ヘッダーファイルで定義されているいくつかの関数が影響をうけることに注意してください。これが望ましくない場合(例えばコンパイラーのパーサー)、GNU gnulibのソースディストリビューションにある‘c-ctype’、‘c-strcase’、‘c-strcasestr’、‘c-strtod’、‘c-strtold’モジュールの、C localeでハードコーディングされている代替の関数を使用することができます。

環境に依存したlocaleとC localeを切り替えて使用することもできますが、この方法はsetlocaleの呼び出しが高価であること、広大なプログラムのソース中でlocaleを切り替える場所を決定するのが退屈であること、localeの切り替えがスレッドセーフではないこと等の理由により、通常は行われません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3 翻訳可能な文字列の準備

文字列が翻訳可能とマークされる前に、調整が必要なこともあります。翻訳可能な文字列の準備は、その文字列をマーク(次のセクションで説明)する前に行います。文字列を準備する際に留意すべきは以下の点です。

上記のガイドラインにたいする例を、いくつか見てみましょう。

翻訳可能な文字列は、正しいEnglishスタイルである必要があります。言語特有のスラングや省略語が使用されている場合、翻訳者がメッセージを理解できずに不適切な翻訳を作成してしまうことがあります。

"%s: is parameter\n"

このメッセージはほとんど翻訳不可能です。表示されるアイテムはa parameter(任意のparameter)なのでしょうか、the parameter(特定のparameter)なのでしょうか?

"No match"

メッセージに含まれるあいまいさにより、メッセージが理解できなくなっています。プログラムはファイルに何かをセットしようとしているのでしょうか? "The given object does not match the template(与えられたオブジェクトがテンプレートにマッチしない)"なのでしょうか、それとも "The template does not fit for any of the objects(そのテンプレートは任意のオブジェクトに適合しない)"なのでしょうか?

どちらのケースも、メッセージに単語を追加することにより、翻訳者とEnglishを話すユーザーの両方を助けることができます。

翻訳可能な文字列は、センテンス全体を含む必要があります。単独の動詞や形容詞を、すべてのメッセージに代替できるように翻訳するのは不可能な場合があります。

printf ("File %s is %s protected", filename, rw ? "write" : "read");

ほとんどの翻訳者はソースを見ないので、"File %s is %s protected"という、それだけでは理解できない文字列しか目にしません。これを以下のように変更します。

printf (rw ? "File %s is write protected" : "File %s is read protected",
        filename);

この方法なら翻訳者はメッセージを理解するだけでなく、適切な文法の組み立て方を見つけることが出きます。たとえばFrenchの翻訳者なら"write protected"を"protected against writing"のように翻訳するでしょう。

多くの言語では、センテンスの他の場所にある性別や数(単数形/複数形)によって、あるセンテンスの単語が変わることがあるという理由からも、センテンス全体を含めることが重要になります。Englishより強い単語間の相互関係を持つ言語もあります。たとえEnglishではうまく動作しても、多くの言語では半分に分割した2つのセンテンスを翻訳者に翻訳してもらってから、2つの翻訳を機械的に結合しても、満足な翻訳とはなりません。これが翻訳者がセンテンス全体を処理する必要がある理由です。

センテンスが1つの行に対応しない場合もあります。これは以下のように、printfステートメントを使って2つの出力により、1つのセンテンスを出力しているような場合です。

printf ("Locale charset \"%s\" is different from\n", lcharset);
printf ("input file charset \"%s\".\n", fcharset);

翻訳者は2つのセンテンスを翻訳する必要があるでしょうが、POTファイル内には2つのセンテンスが分割された1つのセンテンスだと、彼女に教える情報はありません。2つのprintfステートメントを1つにする必要があります。そうすれば翻訳者がセンテンスを一括して処理できるので、翻訳をどの位置で改行すべきか決められるようなります。

printf ("Locale charset \"%s\" is different from\n\
input file charset \"%s\".\n", lcharset, fcharset);

では以下のような隣接した2つのセンテンスの場合はどうなるでしょうか:

puts ("Apollo 13 scenario: Stack overflow handling failed.");
puts ("On the next stack overflow we will crash!!!");

上記の2つのセンテンスは、1つにまとめる必要があるでしょうか? このような場合、2つのセンテンスが互いに関連していて、一緒にしたほうが翻訳者が理解・翻訳しやすくなるようなら、マージすることをお勧めします。一方、2つのメッセージのうち1つが定型的なもので、他の場所でも使用されるようなメッセージの場合は、マージしないほうが翻訳者にとって有益です(同じメッセージが複数の箇所に出現する場合、xgettextがそれらをまとめるので、翻訳者は1度だけそのメッセージを翻訳すればよくなります)。

翻訳可能な文字列は、単一のパラグラフ(段落)に制限すべきです。1つのメッセージの長さは、10行以内にしましょう。その理由は、翻訳可能な文字列が変更されたとき、翻訳者は翻訳済み文字列全体を更新しなければならないからです。たとえ1つの単語を変更しただけでも、(現在の翻訳ツールでは)翻訳者にはそれがわからないので、彼女はメッセージ全体を校正しなければならなくなってしまいます。

多くのGNUプログラムは、‘--help’オプションにより複数画面にまたがる出力を生成します。そのようなメッセージを、1つが5行から10行のメッセージに分割するのは、翻訳者にたいする礼儀です。ドキュメント化するオプションを、入力オプションと出力オプション、情報を出力するオプションのようにグループ分けしてもよいでしょう。グループ分けすることにより、オプションを探すすべてのユーザーを助けることができます。

ハードコーディングされた文字列の結合により、English文字列を生成することがあります:

strcpy (s, "Replace ");
strcat (s, object1);
strcat (s, " with ");
strcat (s, object2);
strcat (s, "?");

翻訳者にセンテンス全体を表示するためという理由だけではなく、object1object2の順番が入れ替わるような言語もあるので、これは以下のような書式文字列を使用するように変更する必要があります:

sprintf (s, "Replace %s with %s?", object1, object2);

似たようなケースとして、コンパイル時の文字列結合があります。ISO C 99のインクルードファイルである<inttypes.h>には、printfで整数型‘int64_t’を出力するためのPRId64マクロが含まれています。このマクロは通常、プラットフォームに応じて "d"、"ld"、"lld" のような文字列定数に展開されます。以下のようなコードがあるとします。

printf ("The amount is %0" PRId64 "\n", number);

gettextツールとライブラリーには、これら<inttypes.h>のマクロにたいする特別なサポートがあるので、上記のような場合は単に以下のように書くことができます。

printf (gettext ("The amount is %0" PRId64 "\n"), number);

この場合、POファイルには"The amount is %0<PRId64>\n"という文字列が含まれます。翻訳者は同様に"%0<PRId64>"と翻訳すれば、実行時にgettext関数が、"d"、"ld"、"lld" などから適切な文字列定数に変換します。

これは事前に定義された<inttypes.h>マクロにたいしてのみ機能します。あなたが‘MYPRId64’のような似たようなマクロを定義した場合、xgettextはそれを知ることができないので、コードを以下のように変更してください:

char buf1[100];
sprintf (buf1, "%0" MYPRId64, number);
printf (gettext ("The amount is %s\n"), buf1);

これでプラットフォームに依存するコードと、インターナショナリゼーションのコードは、別のステートメントに分けられました。バッファーの長さは100バイト以内でよいことに注意してください。なぜなら利用可能なすべてのハードウェアーの整数型は128ビットに制限されており、128ビット整数を出力するには、10進、8進、16進に関わらず最大で54バイトあればよいからです。

これは他のプログラム言語には適用できます。JavaとC#では文字列結合は、それらのコンパイラーのビルトイン操作なのでとても頻繁に使用されます。以下のようなCやJavaのコードがあるとします

System.out.println("Replace "+object1+" with "+object2+"?");

これを以下のような書式師弟文字列を含むステートメントに変更します:

System.out.println(
    MessageFormat.format("Replace {0} with {1}?",
                         new Object[] { object1, object2 }));

C#の場合は以下のように変更します

Console.WriteLine("Replace "+object1+" with "+object2+"?");

これを以下のような書式師弟文字列を含むステートメントに変更します:

Console.WriteLine(
    String.Format("Replace {0} with {1}?", object1, object2));

通常使用しないようなマークアップや制御文字は、翻訳可能な文字列の中に含めるべきではありません。翻訳者はマークアップや制御文字がもつ特別な意味は理解しません。

たとえば‘|’の右側と左側とで何らかのGUI要素を分ける規則があるような場合、翻訳者は特別なコメントなしではその規則を理解することはできません。このような場合は、翻訳者が右側と左側の文字列を個別に翻訳できるようにするのがよいでしょう。

他の例としては、‘argp’で制御文字‘\v’(vertical tab)を使用する場合の規則です。これは1つの文字列を2つのセクションに分ける場合に使用されます。このような文字列をそのまま翻訳可能文字列とするには問題があります。翻訳者によっては、これを単純に改行や空行に置き換えてしまうかもしれません。POファイルエディターの中には、制御文字のvertical tabを入力するのが困難なものもあります。上記の理由により、あなたは翻訳文字列の対応する位置に、‘\v’文字があることを期待できません。この問題にたいする解決策は、繰り返しになりますが、翻訳者が個別に文字列を翻訳できるようにしておいて、実行時に2つの翻訳された文字列を、規則が要求する‘\v’で結合することです。

HTMLマークアップは十分に一般的なマークアップなので、翻訳可能文字列を使用しても大丈夫でしょう。しかしGNU gettextツールは、翻訳された文字列がwell-formedなHTMLであるかは検証しないことに留意してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.4 ソース内でマークはどのように見えるか

Cソース中で翻訳される文字列は、すべてマークする必要があります。マーキングは翻訳可能な文字列を、関数やプリプロセッサーのマクロに、単独の引数として引き渡す方法で行われます。翻訳のために利用可できる関数またはマクロは少なく、マーキングのキーワードとしてそれらの名前が使用されます。マーキングは翻訳される文字列自体に何かを行うよりは、文字列にアタッチすることによりマーキングを行なう方法が、より多く使用されます。明らかな例としては、フォーマット文字列によりエラーメッセージを生成する場合です。フォーマット文字列は翻訳する必要があり、フォーマット文字列の‘%s’で指定した箇所に挿入される文字列も同様だとすると、たとえばsprintfの結果には、‘error_string_out()’のようなルーチンからなる、多くの異なるインスタンスが含まれることになり、これらをすべてリストするのは非現実的です。

マーキングには2つの目的があります。1つ目は実行時に翻訳を取得するトリガーとなることです。キーワードは引数となる文字列にたいして、可能なかぎり(そして望む限り)、動的に適切なトランスレーションを返すルーチンへと解決されます。ローカライズ可能な文字列は、変数にあてがわれていたり、関数の引数になっている場合がほとんどです。しかし翻訳可能な文字列が構造体の初期化時に使用される等の例外もあります。翻訳可能文字列の特別なケースを参照してください。

2つ目の目的は、xgettextが、一連のプログラムソースをスキャンしてPOファイルのテンプレートを生成するときに、翻訳可能な文字列を適切に抽出する手助けをすることです。

翻訳可能な文字列をマークするための標準的なキーワードは‘gettext’で、これはGNU gettextパッケージの名前の由来にもなっています。パッケージで少量の‘gettext’キーワードやマクロ、関数をそのまま使うのは簡単です。しかしgettextインターフェースを多用するパッケージの場合、主要なキーワードには目立つ名前ではなく、より簡潔な名前を使用する方が便利です。キーワードはパッケージ内のすべての文字列の箇所に記述されますが、プログラマーは通常、彼らのプログラムのソースがインターナショナライズされるものだといつも強制的に思い出したいとは望みませんし、その必要もありません。また長いキーワードはより多くの文字数を使用するので、ソースの1行を79から80文字にインデントするための労力が余分にかかるという欠点もあります。

多くのパッケージはキーワードとして‘_’(単なるアンダーライン)を使用して、‘gettext ("Translatable string")’を、‘_("Translatable string")’のように記述しています。またGNU標準のコーディング規約は実際、この特定の用途のためにキーワードと開き括弧の間に、余白としてスペースを要求しています。これにより翻訳可能な文字列のためにかかる文字的なオーバーヘッドは、アンダーラインと2つの括弧というたった3文字に短縮されます。たとえGNU gettextがこの方式を内部的に使用していたとしても、これは公式な提案ではありません。正式なキーワードはあくまでも本物の‘gettext’です。しかし‘gettext’のかわりに‘_’を使用したい人は、以下のように定義すると簡単になります。

#include <libintl.h>
#define _(String) gettext (String)

単に‘#include <libintl.h>’とするのではなく、上記のようにすれば簡単に使用できます。

マーキングのためのキーワードである‘gettext’と‘_’ は、翻訳可能文字列を単一の引数とします。他の位置に引数をするマーキング用の関数を定義することもできます。関数が呼び出されたときの引数の合計数にもとづいた位置のマーク用引数を作ることもできます(通常はC++の場合)。これはxgettextの‘--keyword’により実現されます。xgettextにこのような引数を渡すにはgettextizeが使用されます、その方法についてはpo/内のMakevarspo.m4内のAM_XGETTEXT_OPTIONで説明します。

長い文字列は複数行に分けられることに注意してください。コンパイル時にはISO CおよびISO C++にもとづく文字列の自動連結が行われますが、xgettextもこの構文をサポートしています。

後でメンテナンスするのも簡単になります。もしあなたがプログラマーで、文字列を追加、変更した場合、その文字列が翻訳される必要があると考えた場合は、‘_()’でマークすればよいのです。たとえば‘"%s"’は、翻訳しない文字列だとします。しかし‘"%s: %d"’は翻訳するような場合です(Frenchの場合は通常、Englishとは異なり、コロンの前にスペースを挿入する翻訳が必要になります)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.5 翻訳可能文字列のマーク

POモードには、翻訳者向けというよりはプログラマー向けの一連の機能があります。それらの機能により彼は、プログラムのソース中の文字列が、翻訳可能かどうか、対話的にマークすることができます。彼が選んだ他のエディターでも、それらの文字列を探してマークするのは、プログラマーにとって簡単な作業かもしれませんが、POモードはこれらの作業をより快適にしてくれます。またPOモードは、プログラマーの素養を持つ翻訳者、または翻訳者の素養を持つプログラマーにたいして、プログラムのソース中の翻訳可能な文字列をマークするツールを与えてくれると同時に、インターナショナライズされるパッケージにたいする翻訳を生成するツールを与えてくれるのです。

以下で説明するPOモードのコマンドが対象とするプログラムのソースは、POファイルのコマンドを使う前に、プロジェクト用のEmacs tagsテーブルを生成する必要があります。これは簡単です。任意のシェルウィンドウでプロジェクトのルートディレクトリに移動して、以下のようなコマンドを実行してください:

etags src/*.[hc] lib/*.[hc]

ここではsrc/、およびlib/ディレクトリーにあるすべての.h.cファイルを処理したいとします。このコマンドは指定されたすべてのファイルを検索して、プロジェクトのルートディレクトリーにTAGSという、Emacsが解釈できる要約された形式のファイルを作成します。

GNUコーディング規約に従うパッケージには、すべてのディレクトリーとソースコードを含んだすべてのファイルにたいして、tags、またはTAGSファイルを作成するという目標があります。

1度TAGSを準備すれば、以下のコマンドが彼のソース中の翻訳可能な文字列をマークする手助けをしてくれます。これらのコマンドはPOファイルのウィンドウから実行される必要がありますが、POファイルはまだ作成されていません。しかし新しいウィンドウで空のPOファイルを新規に作成して、そこからコマンドを実行すれば問題ありません。この空のPOファイルの内容は、プログラムのソース中の文字列を翻訳可能にマークするにつれて、徐々に増えていきます。

,

翻訳候補となりそうな文字列をプログラムのソースから検索します(po-tags-search)。

M-,

検索された最後の文字列を‘_()’でマークします(po-mark-translatable)。

M-.

検索された最後の文字列を、利用可能なキーワードによりマークします。プレフィックスと一緒にこのコマンドを使うことにより、キーワードを管理することができます(po-select-mark-and-mark)。

, (po-tags-search)コマンドは、翻訳候補と思われるような次の文字列を検索して、プログラムのソースをEmacsの他のウィンドウで表示します(その文字列がウィンドウの上部にくるように表示されます)。文字列が長くてウィンドウに収まらないような場合は、文字列の最後の部分が表示されます。カーソルは常にPOファイルのウィンドウにあります。その文字列が他の言語に翻訳されたほうがよいと判断したら、M-,、またはM-.により文字列をマークします。翻訳する必要がないと判断した場合は、単に,コマンドで次の文字列を検索してください。

3つ以上の文字の並びは、翻訳候補となります。1行の文字の並びが最大で2つでも、文字の数が非文字より多い場合は、翻訳候補と判断します。文字を含まない文字列、または 孤立した文字だけの文字列は無視されます。コメント文字列、およびPOモードが把握しているキーワード(以下を参照してください)ですでにマークされている文字列も無視されます。

EmacsにたいしてTAGSを指定していない場合、最初にこのコマンドを使うときにミニバッファー(minibuffer)に入力を求められます。TAGSファイルは、Emacsの標準コマンドであるM-x visit-tags-tableを入力して、正しいTAGSファイルを入力することにより、後から変更することができます。Tag Tables in The Emacs Editorを参照してください。

,コマンドは毎回、前回に検索した箇所から検索を再開し、TAGSに従ってすべてのプログラムソースを処理するまで検索します。コマンド(C-u ,)にプレフィクス引数( prefix argument)を与えることにより、プログラムのソースの先頭から検索を再開させることができます。この場合、前回マークした翻訳可能な文字列は自動的にスキップされます。

,コマンドを使用することにより、Emacsの標準コマンドが使用できなくなることはありません。たとえば、標準のtags-search、およびtags-query-replaceコマンドは、,のサーチ順序とは独立して、中断されることなく使用できます。しかし、最初,コマンド(またはコマンド引数をともなう,コマンド)は、Emacsの標準的なtags検索を最初のtagsにリセットしてしまうよう実装されているので、この再初期化は除きます。

M-, (po-mark-translatable)コマンドは、前回検索された文字列を、キーワード‘_’でマークします。M-. (po-select-mark-and-mark)コマンドは、ミニバッファーでキーワードの入力を求めて、文字列をマークするのにそのキーワードを使用します。どちらのコマンドも、マークした文字列に対応する新しい未翻訳のエントリーをPOファイルに作成して、そのエントリーをカレントのエントリーとします(そのエントリーをすぐに翻訳するのが簡単になります)。M-,M-.によるプログラムソースの変更により、ソース1行の文字数が80文字を超えてしまうような場合もありますが、これにたいする再インデントなどは別の作業になります。プログラムソースのウィンドウから、Emacsの別のウィンドウに移ったりするために、POモードからOコマンドを使う場合もあるでしょう。,コマンドに次の文字列を告げるような場合、POファイルのウィンドウにカーソルを戻すには、なんらかのEmacsの標準コマンドを使う必要があります。

M-.には、キーワードをいちいち全部入力しなくてもよいような、スピードアップのための機能がいくつかあります。1つ目は、プロンプトで単にRETを押すだけで、好ましいキーワードが表示されるというスピードアップ機能です。2つ目は、入力したいキーワードにたいして、そのキーワードの先頭部分を一意に特定できる分だけ入力すれば、コマンドが残りの部分を補完してくれるスピードアップ機能です。これはPOモードが利用可能なキーワードを知っていて、ミスタイプによる誤ったキーワードは受け付けられないことを意味します。

キーワードの入力を求められたときに?を入力すると、コマンドは既知のキーワードのリストを表示し、そこから選択して入力することができます。(C-u M-.)によりコマンドが引数が指定された場合、単純なキーワード管理以外による、プログラムのソースとPOファイルのバッファーの更新が禁じられます。この場合、コマンドはキーワードの完全な入力を求め、そのキーワードは以降のM-.コマンドで使用されます。さらに、この新しいキーワードは自動的に、以降のコマンド用のお好みのキーワードに追加されます。C-u M-.にたいして既知のキーワードを答えた場合、単にお勧めのキーワードが1つ変更されるだけで、他には何もしません。

M-.により認識されるすべてのキーワードは、,コマンドによる文字列検索時に再編成されます。この時、これらのキーワードですでにマークされている文字列は自動的にスキップされます。同時に複数のPOファイルを開いている場合、それぞれが個別に既知のキーワードを保有します。現在のところPOモードにキーワードを削除するための機能はないので、(qを使用するなどして)ファイルを一旦閉じてから、再度開く必要があります。Emacs のウィンドウにPOファイルを新規に開いたときは、‘gettext’と‘_’だけがキーワードで、M-.コマンドのお好みのキーワードは‘gettext’になっています。実際のところ、‘_’はビルトインのM-,コマンドに割り当てられているので、お勧めにするには便利ではありません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.6 キーワードの前の特別なコメント

Cプログラム中の文字列は、しばしばprintfファミリーと呼ばれる関数呼び出しで使用されます。これらで使用される書式指定文字列に関して特筆すべきは、%で始まる書式指定子が含まれていることです。以下のようなコードがあるとしましょう。

printf (gettext ("String `%s' has %d characters\n"), s, strlen (s));

上記の文字列にたいして、以下のようなGermanの翻訳が考えられます:

"%d Zeichen lang ist die Zeichenkette `%s'"

Germanを話せないCプログラマーでも、まずい点があることに気がつくでしょう。文字列中の書式指定子の順序が変更されていますが、printfの引数の順序は変更されません。一番問題なのは、文字列のアドレスが期待されている箇所に、文字列の長さが渡していることです。

翻訳に起因する実行時のエラーを防ぐために、msgfmtは翻訳前の文字列と、翻訳後の文字列に含まれる引数のタイプと数を、静的にチェックすることができます。このチェックを満足しないような場合、msgfmtに‘-c’が指定されていると、msgfmtはエラーを発生させてMOファイルを生成しません。‘msgfmt -c’を使用することにより、エラーを事前に検出して、実行時の問題を防ぐことができます。

Germanの翻訳で上述の単語順が正しい場合は、以下のように記述する必要があります

"%2$d Zeichen lang ist die Zeichenkette `%1$s'"

msgfmtルーチンは、この特別な表記法を認識できます。

プログラムのすべての文字列が書式文字列というわけではないので、.poファイルの中のすべての文字列をmsgfmtがテストする必要はありません。また文字列の中に書式指定子と似た文字列が含まれるが、その文字列がprintfで使われる文字列ではないような場合は、問題が発生します。

そのためxgettextは、それらの書式文字列と思われるメッセージに特別なタグを付与します。このタグ付けは絶対的なルールではなく、発見的なルールです。.poファイルの中のそれらのエントリーには、#,によるコメント行で、c-formatというフラグによりマークされます(POファイルのフォーマットを参照してください)。

注意深い読者は、まだ問題があると気づくでしょう。発見されたものが間違っている場合です。これは真実であり、そのためにxgettextは、プログラマーが意志決定すべき特別な種類のコメントを認識することができるのです。gettextキーワードと同じ行、またはそれに続く行にxgettext:c-formatという単語を含むコメントを発見すると、xgettextはどのような場合であれ、文字列をc-formatフラグでマークします。この種のコメントは、xgettextが文字列を書式文字列と認識しない場合(テストしてみて実際に認識されない場合)に使う必要があります。gettextキーワードと同じ行にコメントがある場合、翻訳される前にコメントを挿入しなければならないことに注意してください。

このような状況は頻繁に発生します。printf関数にわたされる文字列に書式指定子が含まれない場合もあります。そのようなケースでは通常、fputsを使用するのでしょうが、それでもこのような状況はあり得ます。このような場合、xgettextはそれを書式文字列として認識しませんが、翻訳に書式指定子として認識されるような文字列が含まれていると何が起こるでしょうか? printf関数はパラメーターにアクセスしようとしますが、翻訳前の文字列には何も引数がわたされないため、パラメーターは存在しません。

もちろん他の原因により、xgettextが間違って書式文字列ではない文字列を、書式文字列と認識することがあります。このような場合、msgfmtは多くの警告を出力し、.poファイルへの変換は失敗します。このように間違って書式文字列と認識されるのを防ぐには、上記と同様にxgettext:no-c-formatという文字列を含むコメントを使用します。

文字列がc-formatと間違ってマークされている場合、ユーザーは何が原因なのか調べることができます。--debugオプション使用して、どのように問題を解決するかについては、xgettextプログラムの呼び出しを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.7 翻訳可能文字列の特別なケース

注意深い読者なら、常に翻訳可能な文字列をgettext(または同様のもの)でマークすることはできないことに気づくでしょう。たとえば以下のようなケースです:

{
  static const char *messages[] = {
    "some very meaningful message",
    "and another one"
  };
  const char *string;
  …
  string
    = index > 1 ? "a default message" : messages[index];

  fputs (string);
  …
}

文字列"a default message"にたいするマーク付けは問題ありませんが、配列messagesを初期化する文字列はマークできません。どうすればよいのでしょうか? このような場合は2つのタスクを達成する必要があります。最初にxgettextプログラムが文字列を見つけ出せるように文字列をマークします(xgettextプログラムの呼び出しを参照してください)。次に実行時に文字列を出力する前に、文字列を翻訳するのです。

最初のタスクは、no-opという新しいキーワードを作ることにより達成できます。2番目のタスクは、配列の文字列にたいするすべてのアクセスポイントをマークします。考えられる解決策の1つは、以下のようなものです:

#define gettext_noop(String) String

{
  static const char *messages[] = {
    gettext_noop ("some very meaningful message"),
    gettext_noop ("and another one")
  };
  const char *string;
  …
  string
    = index > 1 ? gettext ("a default message") : gettext (messages[index]);

  fputs (string);
  …
}

どのようなケースでも、fputsに記述された文字列は翻訳されると思ってください。どのようにしてxgettextが、追加のキーワードgettext_noopを認識するかについては、xgettextプログラムの呼び出しを参照してください。

もちろん、これが唯一の解決策という訳ではありません。以下の方法のうちのいずれかを使用することもできます:

#define gettext_noop(String) String

{
  static const char *messages[] = {
    gettext_noop ("some very meaningful message",
    gettext_noop ("and another one")
  };
  const char *string;
  …
  string
    = index > 1 ? gettext_noop ("a default message") : messages[index];

  fputs (gettext (string));
  …
}

しかしこの方法には欠点があります。プログラマーは文字列"a default message"にもgettext_noopを使うよう留意する必要があります。gettextを使用することにより、予期しない結果となる場合もあります。

利点の1つは、どのようなケースでも出力が翻訳されるようにするために、制御フローを分析する必要がないことです。この分析は一般的に難しいものではありませんが、これにあてはまらないような状況では、2番目の方法を使用することもできます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.8 翻訳バグの報告をユーザーに奨励する

コードにはバグが付き物ですが、翻訳も同様です。ユーザーがそれらのバグを報告できるようにする必要があります。メンテナーが同時に翻訳者であるような場合を除き、メンテナーが翻訳を変更することはないため、プログラマーやパッケージのメンテナーに翻訳のバグを報告するのは得策ではありません。したがって翻訳のバグは翻訳者に報告されなければなりません。

ここで紹介する方法で組織化することにより、メンテナーが翻訳のバグ報告をどこかへ転送したり、翻訳者や翻訳チームのアドレスのリストを維持する必要もなくなります。

すべてのプログラムには、バグを報告するためのアドレスを示す場所があります。GNUプログラムの場合、“–help”オプションにより表示される、“usage”(使用方法)とよばれる機能が該当する場所です。この場所に翻訳のバグ報告のためのアドレスを追加するよう、翻訳者に示すのです。たとえば以下のようなコードがあるとします

printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);

以下のように、翻訳者への指示を追加することができます:

/* TRANSLATORS: The placeholder indicates the bug-reporting address
   for this package.  Please add _another line_ saying
   "Report translation bugs to <...>\n" with the address for translation
   bugs (typically your translation team's web or email address).  */
printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);

これらは‘xgettext’により抽出され、以下のようなエントリーを含む.potファイルとなります:

#. TRANSLATORS: The placeholder indicates the bug-reporting address
#. for this package.  Please add _another line_ saying
#. "Report translation bugs to <...>\n" with the address for translation
#. bugs (typically your translation team's web or email address).
#: src/hello.c:178
#, c-format
msgid "Report bugs to <%s>.\n"
msgstr ""

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.9 翻訳にたいして正確な名前をマークする

人や都市、場所の名前などは翻訳用にマークする必要があるでしょうか? Latin文字で記述する言語(English、Spanish、French、German等)しか知らない人は、“no”と言いたいでしょう。なぜなら通常は、それらの言語間で名前は変更されないからです。しかし一般的には、ある文字体系から他の文字体系に変換するときには、音声表記や音訳により名前も変換されます。たとえばRussianやGreekの名前は、Englishに変換されるときにLatinのアルファベットに変換され、EnglishやFrenchがJapaneseに変換されるときはKatakana文字に変換されます。対象となる言語を話す人たちは、一般的には翻訳前の文字で記述された元の名前を読めないので、これらの変換が必要になります。

それゆえプログラマーとしては、名前を翻訳用にマークするとともに、翻訳者にたいしてそれが元の正確な名前であることと、どのように取り扱うかについての特別なコメントを付与する必要があります。以下は簡単な例です:

printf (_("Written by %s.\n"),
        /* TRANSLATORS: This is a proper name.  See the gettext
           manual, section Names.  Note this is actually a non-ASCII
           name: The first name is (with Unicode escapes)
           "Fran\u00e7ois" or (with HTML entities) "Fran&ccedil;ois".
           Pronunciation is like "fraa-swa pee-nar".  */
        _("Francois Pinard"));

GNU gnulibは、オリジナル名にカッコ内に翻訳された名前を自動的に追加する‘propername’ (http://www.gnu.org/software/gnulib/MODULES.html#module=propername)というモジュールを提供しています。これによりスクリプトを変更しなくてもよいような場合には、翻訳者がASCIIで記述できないような名前にたいして、適切な非ASCII文字を入力するというタスクから開放されます。この、より快適な形式は以下のようなものです:

printf (_("Written by %s and %s.\n"),
        proper_name ("Ulrich Drepper"),
        /* TRANSLATORS: This is a proper name.  See the gettext
           manual, section Names.  Note this is actually a non-ASCII
           name: The first name is (with Unicode escapes)
           "Fran\u00e7ois" or (with HTML entities) "Fran&ccedil;ois".
           Pronunciation is like "fraa-swa pee-nar".  */
        proper_name_utf8 ("Francois Pinard", "Fran\303\247ois Pinard"));

元の名前を、(UnicodeエスケープやHTMLエンティティーとしてではなく)直接Unicodeで記述して、IPA(International Phonetic Alphabet: 国際音標文字。http://www.wikipedia.org/wiki/International_Phonetic_Alphabet)を参照してください)により発音を示すこともできます。

翻訳者としては、名前を翻訳するときは注意深く行う必要があります。なぜなら名前がバラバラに翻訳されたり、間違って翻訳されることは、人を不快にさせるからです。

あなたの言語がLatin文字を使用している場合、必要なのはその言語で普段使用している文字で名前を再構築することだけです。これはc-cedilla文字を含む翻訳を提供するような場合です。あなたの言語がLatin文字とは異なる文字を使用していて、人がそれを通常Latin文字として読まれるようには話していない場合、それは翻訳を意味しています。プログラマーが簡単な方法を使用している場合でも、Latin文字を読む人のために、括弧付きで元の名前を記述する必要があります。プログラマーが上述の‘propername’モジュールを使用している場合は、元の名前を括弧付きで記述するのはプログラムが行うので、あなたが記述する必要はありません。以下は対象言語がGreekの場合の例です:

#. This is a proper name.  See the gettext
#. manual, section Names.  Note this is actually a non-ASCII
#. name: The first name is (with Unicode escapes)
#. "Fran\u00e7ois" or (with HTML entities) "Fran&ccedil;ois".
#. Pronunciation is like "fraa-swa pee-nar".
msgid "Francois Pinard"
msgstr "\phi\rho\alpha\sigma\omicron\alpha \pi\iota\nu\alpha\rho"
       " (Francois Pinard)"

このように名前の翻訳は微妙な領域に属する話題なので、翻訳を提出する前にテストすることをお勧めします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.10 ライブラリーソースの準備

あなたがプログラムではなくライブラリーを作成する場合、gettextの使用方法にはわずかな違いしかありません。ここでは前提として、ライブラリーが自分自身の翻訳ドメインとPOTファイルを持つとします(ライブラリーがメインプログラムの翻訳ドメインとPOTファイルを使用する場合は、前のセクションを変更なしに適用できます)。

  1. ライブラリーのコードでは、setlocale (LC_ALL, "")を呼び出しません。localeのセットはメインプログラムの責任です。ライブラリーのドキュメントにはこの事実を明記して、ライブラリーを使用するプログラム開発者が認識できるようにする必要があります。
  2. ライブラリーのコードでは、textdomain (PACKAGE)を呼び出しません。text domainのセットはメインプログラムの責任です。
  3. プログラムのための初期化は以下のようなコードでした
      setlocale (LC_ALL, "");
      bindtextdomain (PACKAGE, LOCALEDIR);
      textdomain (PACKAGE);
    

    ライブラリーの場合は以下のコードだけになります

      bindtextdomain (PACKAGE, LOCALEDIR);
    

    ライブラリーのAPIにまだ初期化の関数が無いなら、bindtextdomain呼び出しを含む初期化関数を作成する必要があります。しかし通常、この初期化関数をエクスポートしたりドキュメント化する必要はありません。初期化関数がまだ呼び出されていない場合は、ライブラリーのすべてのエントリーポイントとなる関数から初期化関数を呼び出すだけで十分です。これを満足するような典型的な例は、初期化関数が呼び出し済みかどうかを保持するブール値の静的な変数を使用する方法です:

    static bool libfoo_initialized;
    
    static void
    libfoo_initialize (void)
    {
      bindtextdomain (PACKAGE, LOCALEDIR);
      libfoo_initialized = true;
    }
    
    /* This function is part of the exported API.  */
    struct foo *
    create_foo (...)
    {
      /* Must ensure the initialization is performed.  */
      if (!libfoo_initialized)
        libfoo_initialize ();
      ...
    }
    
    /* This function is part of the exported API.  The argument must be
       non-NULL and have been created through create_foo().  */
    int
    foo_refcount (struct foo *argument)
    {
      /* No need to invoke the initialization function here, because
         create_foo() must already have been called before.  */
      ...
    }
    
  4. プログラムでは通常、各ソースファイル中で、以下のように‘_’マクロを定義しました
    #include <libintl.h>
    #define _(String) gettext (String)
    

    自身の翻訳ドメインを持つライブラリーの場合は、以下のようになります:

    #include <libintl.h>
    #define _(String) dgettext (PACKAGE, String)
    

    別の言い方をすると、gettextのかわりにdgettextを使用するということです。同様に、ngettextが使用される箇所には、dngettextを使用する必要があります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5 POテンプレートファイルのマーク

ソースの準備ができたら、プログラマーはPOテンプレートファイルを作成します。このセクションでは、その目的のためにxgettextをどのように使用するかについて説明します。

xgettextは、domainname.poという名前のファイルを作成します。あなたはそれをdomainname.potという名前にリネームする必要があります(xgettextは、どうして直接domainname.potを作成しないのでしょうか? これは歴史的な理由からです。xgettextが設計されたときはPOファイルとPOテンプレートファイルの区別があいまいで、拡張子の‘.pot’も使用されていなかったからです)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1 xgettextプログラムの呼び出し

xgettext [option] [inputfile] …

xgettextプログラムは、与えられた入力ファイルから、翻訳可能な文字列を抽出します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.1 入力ファイルの位置

inputfile

入力ファイルを指定します。

-f file
--files-from=file

入力ファイルの名前を、コマンドラインからではなく、fileから読み込みます。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストからソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileに‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.2 出力ファイルの位置

-d name
--default-domain=name

出力ファイルとして、(messages.poのかわりに)name.poを使用します。

-o file
--output=file

(name.pomessages.poではなく)指定されたファイルに出力を書き込みます。

-p dir
--output-dir=dir

ファイルはdirに出力されます。

出力のfileに‘-’または‘/dev/stdout’が指定された場合、出力は標準出力に書き込まれます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.3 入力ファイルの言語の選択

-L name
--language=name

入力ファイルの言語を指定します。サポートされている言語は、CC++ObjectiveCPOShellPythonLispEmacsLisplibrepSchemeSmalltalkJavaJavaPropertiesC#awkYCPTclPerlPHPGCC-sourceNXStringTableRSTGladeLuaJavaScriptValaです。

-C
--c++

--language=C++の省略指定です。

デフォルトでは、入力ファイルの言語は拡張子により推測されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.4 入力ファイルの解釈

--from-code=name

入力ファイルのエンコーディングを指定します。このオプションはメッセージ文字列や、それらのコメントに非ASCII文字が含まれている場合のみ必要です。TclとGladeの入力ファイルは、このオプションの指定に関わらず、UTF-8が想定されることに注意してください。

デフォルトでは、入力ファイルのエンコーディングはASCIIであると仮定されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.5 オペレーションモード

-j
--join-existing

既存のファイルのメッセージを結合します。

-x file
--exclude-file=file

fileのエントリーは抽出されません。fileには、POファイルかPOTファイルを指定します。

-c[tag]
--add-comments[=tag]

tagで始まるコメントブロックを、出力ファイル中のキーワード行の前に配置します。このオプションでtagを指定しない場合には、出力ファイル中のすべてのキーワード行の前にコメントブロックが配置されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.6 言語特有のオプション

-a
--extract-all

すべての文字列を抽出します。

このオプションはほとんどの言語、すなわち、C、C++、Objective-C、Shell、Python、Lisp、EmacsLisp、librep、Java、C#、awk、Tcl、Perl、PHP、GCC-source、Glade、Lua、JavaScript、Valaに影響を与えます。

-k[keywordspec]
--keyword[=keywordspec]

検索する追加のキーワードをkeywordspecに指定します。keywordspecを指定しない場合には、デフォルトのキーワードを使用しないことを意味します。

keywordspecとして指定されたidがCのものだった場合、xgettextは関数(またはマクロ)idの各呼び出しの最初の引数から文字列を検索します。keywordspecが‘id:argnum’という形式で指定された場合、xgettextは呼び出しのargnum番目の引数を探します。keywordspecが‘id:argnum1,argnum2’の形式で指定された場合、xgettextは呼び出しのargnum1番目とargnum2番目の引数から文字列を探して、複数形として処理すべきメッセージのsingular(単数形)とplural(複数形)として扱います。同様に、keywordspecが‘id:contextargnumc,argnum’や‘id:argnum,contextargnumc’という形式で指定された場合、xgettextcontextargnum番目の引数の文字列をコンテキスト指定子(context specifier)として扱います。そして GNOME のための特別なサポートとして、keywordspecが‘id:argnumg’という形式で指定された場合、xgettextはargnum番目の引数がcontextを伴う文字列と認識して、GNOME glibの‘"msgctxt|msgid"’という構文を使用します。そしてGNOMEのための特別なサポートとして、keywordspecが‘id:argnumg’という形式で指定された場合、xgettextargnum番目の引数がcontextを伴う文字列と認識して、GNOME glibの‘"msgctxt|msgid"’という構文を使用します。
またkeywordspecが‘id:…,totalnumargst’という形式で指定された場合、xgettextは実際の引数の数がtotalnumargsと等しい場合のみ、この引数指定を処理します。これはC++でのオーバーロードされた関数の呼び出しなどで便利です。
最後に、もしkeywordspecが‘id:argnum...,"xcomment"’という形式で指定された場合、xgettextは指定された引数から文字列を抽出するときに、追加のコメントとしてxcommentをメッセージに追加します。通常のシェルのコマンドラインから使用する場合は、xcommentを括るダブルクォーテーションはエスケープする必要があることに注意してください。

このオプションはほとんどの言語、すなわち、C、C++、Objective-C、Shell、Python、Lisp、EmacsLisp、librep、Java、C#、awk、Tcl、Perl、PHP、GCC-source、Glade、Lua、JavaScript、Valaに影響を与えます。

明示的に無効化されていない限り、常に検索されるデフォルトキーワードの指定は、言語に依存します:

デフォルトキーワードの指定は、‘-k’オプション、‘--keyword’を指定するか、keywordspecを指定せずに‘--keyword=’として無効にすることができます。

--flag=word:arg:flag

関数wordの、arg番目の引数の一部となるような文字列のための、追加のフラグを指定します。‘c-format’や、それの反対の‘no-c-format’のような、利用可能な書式文字列を示すフラグを利用でき、‘pass-’を前置して指定することもできます。
--flag=function:arg:lang-formatは、言語langの関数functionarg番目の引数を書式文字列とみなすという意味です(GCC関数の属性に慣れている人は、--flag=function:arg:c-formatが、Cソース中の関数 functionに付記される‘__attribute__ ((__format__ (__printf__, arg, ...)))’宣言と同様だと思えばよいでしょう)。たとえばGNU libcから、関数‘error’を使用する場合、それの振る舞いについて--flag=error:3:c-formatのように指定することができます。この指定によりxgettextは、すべてのgettext呼び出しのfunctionarg番目の引数に出現する文字列を、書式指定文字列としてマークします。これは書式指定子が含まれていないような文字列にたいして‘msgfmt -c’によりチェックを行う場合に便利です。これにより翻訳者が実行時のクラッシュを引き起こすような書式指定子を意図せずに使ってしまうことを防ぐことができます。
--flag=function:arg:pass-lang-formatは、言語langにおいて、書式文字列が出現しなければいけない位置にfunction呼び出しがある場合、その関数のarg番目の引数には、同じタイプの書式文字列となければならないという意味です。(GCC関数の属性を知っている人は、--flag=function:arg:pass-c-formatが、Cソース中の関数functionに付記される‘__attribute__ ((__format_arg__ (arg)))’宣言と同様だと思えばよいでしょう)。たとえばgettext関数の略記である‘_’を使用している場合は、--flag=_:1:pass-c-formatを使う必要があります。この指定によりxgettextは、_("string")呼び出しの最初の引数"string"には書式指定文字列が必要だと伝えるために、その文字列を書式指定文字列としてマークします。これは書式指定子が含まれていないような文字列にたいして‘msgfmt -c’によりチェックを行う場合に便利です。これにより翻訳者が実行時のクラッシュを引き起こすような書式指定子を意図せずに使ってしまうことを防ぐことができます。
このオプションは、C、C++、ObjectiveC、Shell、Python、Lisp、EmacsLisp、librep、Scheme、Java、C#、awk、YCP、Tcl、Perl、PHP、GCC-source、Lua、JavaScript、Vala(つまり、ほとんどの言語)に影響を与えます。

-T
--trigraphs

入力におけるANSI Cの三連表記(trigraph)を理解します。
このオプションは言語がC、C++、ObjectiveCの場合のみ効果があります。

--qt

Qtの書式指定文字列を認識します。
このオプションは言語がC++の場合のみ効果があります。

--kde

KDE 4の書式指定文字列を認識します。
このオプションは言語がC++の場合のみ効果があります。

--boost

Boostの書式指定文字列を認識します。
このオプションは言語がC++の場合のみ効果があります。

--debug

メッセージ中の書式指定文字列を、c-formatpossible-c-formatフラグでマークすることにより、誰がマークしたかを表示します。後者の形式は、xgettextが決定したときに使用され、前者はプログラマーが決定したときに使用されます。

デフォルトではc-format形式だけが使用されます。翻訳者はそれらの詳細について気にする必要はありません。

このxgettextの実装は、プリプロセッサーのマクロの中の文字列や、ANSIによる隣接した文字列の結合、エスケープ文字による行の継続等の厄介なケースを処理することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.7 出力の詳細

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

何もメッセージが定義されていない場合でも、常に出力ファイルに書き込みます。

-i
--indent

インデントされた形式で.poファイルを書き込みます。

--no-location

#: filename:line’のような行を書き込みません。このオプションを使用することにより、熟練した翻訳者が、どのようなコンテキストでメッセージが使用されるのかを理解するのが困難になることに注意してください。

-n
--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、廃止されたメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

-F
--sort-by-file

ファイルの場所により出力をソートします。

--omit-header

msgid ""’というエントリーにたいして、ヘッダーを書き込みません。

これはソースファイルの変更をテストする等の目的で、.gmoファイルを生成するときに便利です。--omit-headerを使用すると、同じファイルにたいして、同じオプションでxgettextを実行すれば、実行した時が異なっていても同じ結果を得ることができます。

このオプションをASCII以外の文字が含まれたファイルにたいして使用した場合、エラーとなることに注意してください。

--copyright-holder=string

出力に著作権所有者(copyright holder)をセットします。stringにはパッケージの著作権所有者を指定する必要があります(パッケージのソースから抽出されたmsgstr文字列の著作権は、パッケージの著作権所有者に帰属することに注意してください)。翻訳者は、翻訳物の著作権を譲渡、もしくは放棄することが望まれます。これによりパッケージのメンテナーは法的なリスクなしでそれらを配布できるのです。stringが空の場合、出力ファイルはパブリックドメインに属するとマークされます。この場合も翻訳者は著作権を譲渡、もしくは放棄することが望まれます。繰り返しになりますが、そうすることによりパッケージのメンテナーは法的なリスクなしでそれらを配布できるのです。

stringのデフォルト値はFree Software Foundation, Inc.です。これは単にxgettextが最初に使用されたのが GNU プロジェクトであることが理由です。

--foreign-user

出力からFSFの著作権を省略します。これは‘--copyright-holder=''’とするのと同じです。これはGNUプロジェクト以外で、翻訳物をパブリックドメインにしたいときに便利です。

--package-name=package

出力のヘッダーに、パッケージ名をセットします。

--package-version=version

出力のヘッダーにパッケージのバージョンをセットします。このオプションは、同時に‘--package-name’を指定したときだけ効果があります。

--msgid-bugs-address=email@address

msgidに関するバグの報告先アドレスをセットします。このアドレスは、翻訳者が未翻訳文字列のバグを報告するための電子メールのアドレス、またはURLです。

このアドレスは、あなたのメールアドレスでも構いませんし、翻訳者が登録しなくても投稿できるメーリングリストのアドレスや、翻訳者があなたに連絡をとることができるウェブページのアドレスにすることもできます。

デフォルトは空文字列が設定されており、これは翻訳者にはこれらの情報が分からないことを意味します! このオプションを指定するのを忘れないでください。

-m[string]
--msgstr-prefix[=string]

msgstrの値に前置する文字列としてstring(指定されていない場合は"")を使用します。

-M[string]
--msgstr-suffix[=string]

msgstrの値に後置する文字列としてstring(指定されていない場合は"")を使用します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.8 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6 新しいPOファイルの作成

新しい翻訳を開始する場合、翻訳者はpackage.potの初期コメント(ファイルの先頭にあります)とヘッダーのエントリー(最初のエントリーで、これもファイルの先頭付近にあります)に変更を加えたものをコピーして、LANG.poを作成します。

これを行う一番簡単な方法は、‘msginit’を使うことです:

$ cd PACKAGE-VERSION
$ cd po
$ msginit

かわりにコピーしてから手で変更する方法もあります。この場合、翻訳者はpackage.potLANG.poというファイル名でコピーしてから、ファイル内の初期コメントとヘッダーエントリーを修正します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1 msginitプログラムの呼び出し

msginit [option]

msginitプログラムは、新しいPOファイルを作成して、メタ情報をユーザーの環境にもとづいて初期化します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.1 入力ファイルの位置

-i inputfile
--input=inputfile

入力となるPOTファイルです。

inputfileが指定されなかった場合、カレントディレクトリからPOTファイルを検索します。‘-’を指定すると、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.2 出力ファイルの位置

-o file
--output-file=file

指定されたPOファイルに出力を書き込みます。

出力ファイルが指定されなかった場合は、ユーザーのロケール設定の‘--locale’オプションに依存します。‘-’を指定すると、出力は標準出力に書き込まれます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.3 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.4 出力の詳細

-l ll_CC
--locale=ll_CC

対象のlocaleを設定します。llにはlanguage codeを、CCにはcountry codeを設定する必要があります。インストールされているすべてのlocaleのリストを出力するには、‘locale -a’コマンドを使用できます。デフォルトはユーザーのlocale設定が使用されます。

--no-translator

POファイルが翻訳者の手で作成されたものではなく、自動的に生成されたものであることを宣言します。

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、廃止されたメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1.5 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2 ヘッダーエントリーを入力する

新規作成したときに初期値として入力されている、"SOME DESCRIPTIVE TITLE"、"YEAR"、および"FIRST AUTHOR <EMAIL@ADDRESS>、YEAR"などのコメントは、意味のある情報に書き換えるべきです。これはテキストエディターにより行うこともできますが、Emacsを使っていれば(拡張子を識別して)自動的にPOモードに切り替わります。これはM-x fundamental-modeと入力して無効にすることができます。

ヘッダーのエントリーの変更も、POモードで行うことができます。Emacsで、M-x po-mode RETと入力して、さらにRETを押すと、エントリーの編集が開始できるので、以下のフィールドに入力してください。

Project-Id-Version

パッケージの名前とバージョンです。xgettextにより入力されていない場合は入力してください。

Report-Msgid-Bugs-To

これはxgettextによってすでに入力されています。未翻訳の文字列に関するバグを報告するための、電子メールアドレスかURLが含まれています:

POT-Creation-Date

これはxgettextによってすでに入力されています。

PO-Revision-Date

これはPOファイルのためのエディターが、ファイルを保存するときに入力される項目なので、あなたは入力する必要はありません。

Last-Translator

名前と電子メールアドレス(ダブルクォーテーションなし)を入力してください。

Language-Team

言語の英語名と、あなたが所属するlanguage teamの電子メールアドレスか、ホームページのURLを入力してください。

重複して作業するの防ぐためだけではなく、言語に関する難しい問題を調整するためにも、翻訳を開始する前にtranslation teamに連絡することをお勧めします。

フリーな翻訳プロジェクトでは、それぞれの翻訳チームが、チーム自身のメーリングリストを持っています。チームの最新のメーリングリスト一覧は、Free Translation Projectのホームページ(http://translationproject.org/) の"Teams"という場所にあります。

Language

あなたの言語の言語コードを入力してください。以下の3つの形式のいずれかになります:

ll_CC’の命名規則は、システムがGNU libcにもとづいてlocale名を決定する方法でもありますが、重要な違いが3つあります。

そのため、あなたのlocale名が‘de_DE.UTF-8’の場合、POファイルのlanguage specificationは‘de’だけになります。

Content-Type

CHARSET’を、あなたのlocaleのlanguageで使用するcharacter encodingかUTF-8で置き換えてください。この項目は、msgmergemsgfmtの正しい動作のために必要です。同様にlocaleのcharacter encodingが、あなたのものとは異なるユーザーにとっても必要です(gettextが使用する出力文字セットの指定方法を参照してください)。

localeのcharacter encodingは、シェルのコマンド‘locale charmap’を実行して得ることができます。このコマンドの結果が‘C’や‘ANSI_X3.4-1968’の場合のcharacter encodingは‘ASCII’(=‘US-ASCII’) となり、これはあなたのlocaleが正しく設定されていないことを意味します。そのような場合は、あなたの属するtranslation teamに、どのcharset を使用すればよいのか尋ねてください。‘ASCII’は、Latin 以外の language には適用できません。

POファイルは、オペレーティングシステムの高度なインターナショナリゼーションの利便性に依存せずに可搬性を持たなければならないため、使用できるcharacter encodingsは GNU libcと GNU libiconvでサポートされるものに限定されています。使用できるcharacter encodingはASCIIISO-8859-1ISO-8859-2ISO-8859-3ISO-8859-4ISO-8859-5ISO-8859-6ISO-8859-7ISO-8859-8ISO-8859-9ISO-8859-13ISO-8859-14ISO-8859-15KOI8-RKOI8-UKOI8-TCP850CP866CP874CP932CP949CP950CP1250CP1251CP1252CP1253CP1254CP1255CP1256CP1257GB2312EUC-JPEUC-KREUC-TWBIG5BIG5-HKSCSGBKGB18030SHIFT_JISJOHABTIS-620VISCIIGEORGIAN-PSUTF-8です。

GNUシステムでは、対応する言語にたいして以下のエンコーディングが頻繁に使用されます。

あなたの言語の翻訳に、その言語の1重引用符か2重引用符が使用されており、そのlocaleのencodingが ISO-8859-* のいずれかの場合は、POファイルはlocaleのencodingではなくUTF-8 encodingで作成するのが最善です。これはUTF-8では、ISO-8859-*が持っていない実際の引用文字(1重引用符はU+2018とU+2019、2重引用符はU+201CとU+201D)が表現可能だからです。UTF-8のlocale のユーザーは実際の引用符文字列を見ることができますが、ISO-8859-*のlocaleでは垂直方向のアポストロフィーと垂直方向のダブルクォーテーションが(文字セットの変換により)代用で表示されます。

X11でこれらの引用文字を入力するために、xmodmapプログラムでキーボードのマッピングを使用することができます。この場合、X11 での引用文字の名前は"leftsinglequotemark"、"rightsinglequotemark"、"leftdoublequotemark"、"rightdoublequotemark"、"singlelowquotemark"、"doublelowquotemark"になります。

UTF-8 encodingは、新しいバージョンのGNU Emacsでだけサポートされていることに注意してください。たとえばEmacs 20 with Mule-UCSやEmacs 21ではUTF-8 encodingがサポートされていますが、2001年1月時点のXEmacsではサポートされていません。

文字のエンコーディング名は、大文字または小文字で記述することができますが、通常は大文字が好まれます。

Content-Transfer-Encoding

8bitにセットしてください。

Plural-Forms

このフィールドはオプションで、POファイルにplural formがあるときだけ必要です。これは‘msgid_plural’というキーワードを検索すればわかります。plural formのフィールドの書式については複数形(plural forms)にたいする追加の関数複数形の翻訳を参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7 既存のPOファイルの更新


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1 msgmergeプログラムの呼び出し

msgmerge [option] def.po ref.pot

msgmergeプログラムは、Uniforumスタイルの2つの.poファイルをマージして1つにします。def.poファイルは既存のPOファイルで、メッセージが一致していれば既存の翻訳は新しいファイルに引き継がれます。その際、コメントは残されますが、抽出されたコメントやファイル内の位置などは破棄されます。ref.potは、最新のソースより作られたPOファイルですが、古い翻訳や、(通常はxgettextにより作成された)PO Templateファイルを参照するため、ドットコメント(訳注:プログラマーから翻訳者へのコメント#.のこと)やファイル内の位置情報は保存されますが、ファイル内のいくつかの翻訳やコメントは、破棄されるでしょう。完全に一致するメッセージが見つからない場合、より良い結果を生成するためにfuzzy一致が使用されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1.1 入力ファイルの位置

def.po

古いソースを参照する翻訳です。

ref.pot

新しいソースへの参照です。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

-C file
--compendium=file

メッセージを翻訳するための追加のライブラリーを指定します。翻訳compendiaの使用を参照してください。このオプションは複数指定することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1.2 オペレーションモード

-U
--update

def.poファイルを更新します。すでにdef.poが最新の場合は何もしません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1.3 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1.4 更新モードでの出力ファイルの位置

処理結果はdef.poファイルに書き戻されます。

--backup=control

def.poのバックアップを作成します。

--suffix=suffix

通常使用されるバックアップの接尾辞を上書きします。

--backupオプション、もしくは環境変数VERSION_CONTROLを通じてバージョン管理の方式を選択します。以下の値が指定できます:

none
off

(--backupオプションが指定されていたとしても)バックアップを作成しません。

numbered
t

番号付きのバックアップを作成します。

existing
nil

このファイルの番号付きのバックアップがすでに存在する場合、番号付きバックアップを作成し、そうでなければ単純なバックアップを作成します。

simple
never

常に単純なバックアップを作成します。

--suffixまたは環境変数SIMPLE_BACKUP_SUFFIXが設定されていない場合は、バックアップの接尾辞として‘~’を使用します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1.5 オペレーションの修飾

-m
--multi-domain

def.po内の各ドメインにたいして、ref.potを適用します。

-N
--no-fuzzy-matching

完全に一致するものが見つからない場合、fuzzyマッチングを行いません。これにより処理のスピードが大幅に改善されます。

--previous

翻訳されたメッセージをもつ古いmsgidにたいしてfuzzyマーカーを追加するときに、‘#|’マークをつけて古いメッセージを保持します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1.6 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1.7 出力の詳細

--lang=catalogname

ヘッダーのエントリーで使用される‘Language’フィールドを指定します。このフィールドの意味についてはヘッダーエントリーを入力するを参照してください。‘Language-Team’と‘Plural-Forms’のフィールドは変更されないことに注意してください。このオプションを指定しない場合、‘Language-Team’フィールドから最適なものを推測して、‘Language’フィールドに入力します。

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

-i
--indent

インデントされた形式で.poファイルを書き込みます。

--no-location

#: filename:line’という行を書き込みません。

--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、廃止されたメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

-F
--sort-by-file

ファイルの場所により出力をソートします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1.8 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。

-v
--verbose

診断レベルを上げます。

-q
--quiet
--silent

プログレスインジケーターを表示しません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8 POファイルの編集


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1 KDEのPOファイルエディター


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.2 GNOMEのPOファイルエディター


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3 EmacsのPOファイルエディター

幸運にもあなたがEmacsのユーザーならば、POファイルの編集・変更のための快適な環境を提供するために特別に作成されたPOモードがあります。POファイルを編集するときPOモードを使えば、追加のPOファイルやcompendium POファイルを閲覧したり、POファイルの元となるCプログラムのソースへの参照を追跡するのが簡単になります。またプログラム中の文字列にたいして対話的に翻訳可能のマークをつけたり、POファイルを検証してエラーのある行を再配置するための特別な機能があります。

POモードを使うにはまず、主要なPOモードのコマンド(主要なPOモードのコマンドを参照してください)以外に、エントリー間の移動(エントリーの決定を参照してください)や、翻訳されていないエントリーの処理方法(未翻訳エントリーを参照してください)を理解する必要があります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.1 GNU gettextのインストールを完了する

1度GNU gettextディストリビューションを入手して解凍し、configure、コンパイルしてしまえば、‘make install’コマンドでxgettextmsgfmtgettextmsgmergeなどのプログラムや、それらが利用できるメッセージのカタログを所定の場所に配置することができます。快適なインストールの締めくくりとして、EmacsのユーザーのためにPOモードを利用できるようにしましょう。

POモードをインストールしているうちに、あなたは.emacsファイルを修正して、以下のような行を追加したいと思うことでしょう:

(setq auto-mode-alist
      (cons '("\\.po\\'\\|\\.po\\." . po-mode) auto-mode-alist))
(autoload 'po-mode "po-mode" "Major mode for translators to edit PO files" t)

こうしておけば以後、.poのようなファイルや、ファイル名に‘.po.’という文字列が含まれるファイルを編集するとき、Emacs が必要に応じてpo-mode.elc(またはpo-mode.el)をロードして、割り当てられたバッファーにたいするPOモードのコマンドが自動的に利用可能になります。POモードがアクティブな任意のバッファーのモードラインには、POという文字が表示されます。単一のEmacsセッションで、1度に複数のPOファイルをアクティブにすることができます。

Emacsのバージョン20以上を使用していて、システムに適切なインターナショナルフォントがインストールされているなら、様々なPOファイルにたいして自動的にcoding systemを決定する方法をEmacsに指定することもできます。これはEmacsのスクリーンに翻訳を表示する時にしばしば、必要なフォントがロードされ使用されるということです(常にではありませんが)。これを実現するためには、あなたの.emacsファイルに以下の行を追加します:

(modify-coding-system-alist 'file "\\.po\\'\\|\\.po\\."
                            'po-find-file-coding-system)
(autoload 'po-find-file-coding-system "po-mode")

これでもまだinternationalなcharacterのかわりに四角が表示されるようなら、(Shiftキーを押しながらマウスボタン1をクリックして)違うフォントセットを試してみてください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.2 主要なPOモードのコマンド

GNU gettextのインストールを完了するで説明されているような行を追加してEmacsを設定した後は、POファイルを検知するとEmacsがそのウィンドウにたいしてPOモードを有効にします。これによりそのウィンドウは読み取り専用となり、po-mode-mapが設定されます。これはテキストモードから継承されたのではなく、純粋なEmacsのモードです。もしpo-mode-hookに指定された関数があれば、実行されます。

あるウィンドウにたいしてPOモードが有効になると、‘PO’という文字が、そのウィンドウのモードラインに表示されます。モードラインにはPOファイルに含まれている各種エントリーがいくつあるかも表示されます。たとえば‘132t+3f+10u+2o’という文字列が表示されている場合、POモードには132個の翻訳済みのエントリー(翻訳済みのエントリーを参照してください)と、3個のfuzzyエントリー(fuzzyエントリーを参照してください)、それに10個の未翻訳のエントリー(未翻訳エントリーを参照してください)と、2個の廃止されたエントリー(陳腐化したエントリーを参照してください)が含まれていることを翻訳者に示しています。この際、エントリーが0個のものは表示されません。この例にならうと、fuzzyエントリーが解消され、未翻訳のエントリーが翻訳され、廃止されたエントリーが削除されれば、モードラインには‘145t’だけが表示されることになります。

主要なPOコマンドの中には、以下のセクションのカテゴリー分けに適合しないものもあります。それらのコマンドとは、POモードやPOモードが管理するウィンドウを、特別な方法で終了する方法などです。

_

POファイルにたいする最後の変更を取り消します(po-undo)。

Q

処理を終了してPOファイルを保存します(po-quit)。

q

問い合わせの後に処理を終了します(po-confirm-and-quit)。

0

一時的にPOファイルのウィンドウを離れます(po-other-window)。

?
h

POモードのヘルプを表示します(po-help)。

=

POファイルに関する統計情報を取得します(po-statistics)。

V

POファイル全体のフォーマットを検証します(po-validate)。

_コマンド(po-undo)は、Emacsのundo機能と連携します。Undoing Changes in The Emacs Editorを参照してください。_を入力する度に、翻訳者がPOファイルにたいして行った変更が少しずつ取り消されていきます。取り消し機能を実現するために、POモードのコマンドはアトミックになっています。これは特にRETコマンドにたいして当てはまります。このコマンドを使用して行った1度の変更は、編集がいくつかの操作により行われたものだったとしても、1度の取り消しで元に戻ります。しかし編集中のウィンドウでは、作業をより小さい単位で取り消すことができます。

Qコマンド(po-quit)と、qコマンド(po-confirm-and-quit)は、翻訳者がPOファイルにたいする作業を終了するときに使用します。後者のコマンドは前者のコマンドに比べると冗長なコマンドです。ファイルが変更されていた場合、まずディスクにファイルが保存されます。ファイルが変更されていない場合でも、コマンドはまずPOファイルに未翻訳のメッセージが残されていないかをチェックして、もしそのようなメッセージが残っていた場合、翻訳者は本当にこのPOファイルにたいする作業を終了したいのか尋ねられます。これはEmacsのPOファイルにたいするバッファーを離れるときに望ましい方法です。単にバッファーをkillする通常のC-x kコマンド(kill-buffer))は、好ましい方法ではありません。

0コマンド(po-other-window)は、POモードを一時的に離れるときに使用する、よりソフトな方法です。このコマンドはカーソルをEmacsの他のウィンドウに移動して、他のウィンドウを表示します。たとえば翻訳者が、メッセージのソース文脈中での箇所を探して、ソースのバグを修正するためだけにPOモードを開いている場合などに使用します。このコマンドにより翻訳者たる彼女は、プログラマーたるへと性転換を遂げ、修正したいプログラムを表示しているウィンドウにカーソルを移すことができます。後でPOファイルのウィンドウにカーソルを戻すか、このファイルをもう一度編集するかをEmacsに指定した時に、POモードが復元されます。

hコマンド(po-help)は、POモードで利用可能なすべてのコマンドの要約が表示されます。翻訳者が任意の文字を入力することにより、通常のPOモードの操作に戻ることができます。?コマンドでも、hコマンドと同じ結果を得ることができます。

=コマンド(po-statistics)は、POファイルのすべてのエントリーを集計し、現在のエントリーが先頭から数えて何番目かと、未翻訳のエントリー数、廃止されたエントリー数等のすべての数を表示します。

Vコマンド(po-validate)は、msgfmtのverbose modeにより、編集中のPOファイルをチェックします。このコマンドは最初に編集中のPOファイルをディスクに保存します。GNU gettextmsgfmtは、POファイルの出力としてMOファイルを生成するツールで、POモードがPOファイル全体の書式や個々のエントリーの書式をチェックするのに、このプログラムの機能が使用されています。

msgfmtプログラムはEmacsと非同期で実行されるので、POファイルの評価が終わっていなくても、制御はすぐに翻訳者に戻されます。標準エラー出力への出力はEmacsにより収集されて、他のウィンドウの‘*compilation*’バッファーに表示されます。Emacsの通常コマンドのC-x`(next-error)や、その他の同様のコンパイル時のコマンドにより、翻訳者は素早くPOファイル中の提示された位置に移動することができます。カーソルがエラーのある行に移動すると、翻訳者がエラーを修正するためのPOモードのコマンドを選択することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.3 エントリーの決定

POファイルのウィンドウの中のカーソルは、ほとんど常にエントリ一部となります。唯一の例外は、カーソルがファイルの最後のエントリーの後ろにあったり、POファイルが空だったりという、特別なケースのときだけです。カーソルのある位置のエントリーのことを、カレントエントリーと呼びます。POモードのコマンドの多くは、カレントエントリーにたいして操作を行うので、翻訳者にとってカーソルを動かすことはPOファイルを閲覧できるだけでなく、エントリーに作用するコマンドの対象エントリーを選択することでもあるのです。

POモードのコマンドには、特別な方法によりカーソルの位置を変更するものがあります。それらの特別な目的に対応する位置へカーソルを動かす方法については、ここで説明します。他の方法については、以降のセクションで説明します(C-h mで完全な一覧を得ることもできます)。

.

カレントエントリーを再表示します(po-current-entry)。

n

カレントエントリーの次のエントリーを選択します(po-next-entry)。

p

カレントエントリーの前のエントリーを選択します(po-previous-entry)。

<

POファイルの最初のエントリーを選択します(po-first-entry)。

>

POファイルの最後のエントリーを選択します(po-last-entry)。

m

後で利用できるように、現在のエントリーの場所を記録します(po-push-location)。

r

以前に記録したエントリーの場所に戻ります(po-pop-location)。

x

現在のエントリーの場所と、以前に記録したエントリーの場所を交換します(po-exchange-location)。

Emacsのカーソル位置を変更するための、文字、行、paragraph、画面単位での移動や検索などのコマンドは、POモードでカレントエントリを選択するのに使用できます。しかしPOモードには、通常のEmacsでカーソルを移動するコマンドには無いような、カレントエントリーを表示するための標準的な方法があります。.コマンド(po-current-entry)は、Emacsの画面が変更されたときなどPOモード以外の方法やでカレントエントリーが変更された時に、カレントエントリーを適切に再表示するという単一の目的のためのコマンドです。

翻訳者が作業をしているときに、POモードによりウィンドウ配置を厳格に強制されることが、彼女を助けるものなのか、それともイライラさせるものなのかは未だ不明です。私たちは当初、ウィンドウがどのように振る舞うべきかについて明確なアイデアを持っていました。しかしその一方で、Emacsを使うとき自分で完全にコントロールできるほうを好む人もいます。固定されたウィンドウ配置は、翻訳者が有効・無効を選択できるようにPOモードのオプションとして、実験的な機能として提供されるべきでしょう。もしこの機能を使う必要性や、記述する衝動をもつ人がだれもいないなら、私たちはこのアイデアを放棄するべきなのでしょう。これを行うには、プログラマーよりも翻訳者からの動機が必要です。私にとって、経験を積んだ翻訳者の意見は、他者がどうやって翻訳するか想像するしかないプログラマーの意見にくらべて、より価値があるからです。

nコマンド(po-next-entry)とpコマンド(po-previous-entry)は、カーソルをカレントエントリーの前または後のエントリーに移動します。POファイルの最後のエントリーにカーソルがあるときにnを押したり、最初のエントリーにカーソルがあるときにpを押しても、移動は行われません。

<コマンド(po-first-entry)と>コマンド(po-last-entry)は、POファイルの最初のエントリー、または最後のエントリーにカーソルを移動します。POモードのほとんどのコマンドは、POファイルの最後のエントリー以降にカーソルがあるときは、‘After last entry’のようなエラーを戻します。<コマンドと>コマンドは、カーソルがPOファイルのエントリーにない場合でも動作する特性があるので、このような状況をうまく解決するのに使う人もいます。しかしこれらのコマンドも、POファイルが空の場合は失敗します。ソースから対話的に空のPOファイルにエントリーを追加していくようにPOモードを開発するプランもあります。翻訳可能文字列のマークを参照してください。

翻訳者が特定のエントリーを翻訳する前には、そのエントリーに関連する用語や言い回しを探すために、POファイルの残りの部分を参照する必要があるかもしれません。もちろん彼女はEmacsの標準的な慣例にしたがって、カレントカーソルの位置をレジスターなどに保存して、後でその場所に戻るのにそのレジスターを使ったり、場所を記憶するためのリングバッファーを使うこともできます。

これらの方法にたいして、POモードは特別なスタックにカーソルの場所を保存するという、別の方法を提供します。mコマンド(po-push-location)は、スタック上に既に保存してあるカーソル位置の情報の上に、カレントエントリーをpushします。rコマンド(po-pop-location)は、スタックの最上部の要素をpopして、カーソルをその要素に関連付けられた位置へと移動します。これによりpopされた要素の位置情報は失われ、次のrコマンドでは、その要素の1つ前に保存された位置にカーソルが移動します。これはスタックに保存された位置の情報がなくなるまで同じように動作します。

翻訳者がスタックの最上位の要素に関連付けられているエントリーの位置を確認してから他の場所に移動して、後で元の場所に戻る等の理由で、エントリーの場所をスタックに保存したいとき、彼女はrの直後にmを使うべきです。

xコマンド(po-exchange-location)は、カーソルをスタックの最上位の要素に関連付けられた位置に再配置すると同時に、移動する前のカレントエントリーの位置を最上位の要素に保存します。つまり、xコマンドを繰り返し使うと、それら2つのエントリーを行き来することができます。これを行うにはまず、最初のエントリーにカーソルを移動してからmコマンドを使用し、その後2番目のエントリーでxコマンドを使えば、2つのエントリー間を行き来することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.4 エントリー内の文字列の正規化

特定の文字列をPOファイルのエントリーにエンコードする場合、複数行を分割したり括ったりする方法、さらには特殊な文字をバックスラッシュでエスケープする方法までもが異なっている等、とても多くの方法があります。POモードには、特定のエンコードの文字列をmsgidフィールドに挿入するために、既存のPOファイルをスキャンする機能があります。POモードにはこれらを簡単に認識するためのビルトイン機能が内部的に存在しますが、これを高速に行うのは技術的に困難です。この効率に関する問題の解決を容易にするために、わたしたちは文字列の正規表現を採択しました。

POファイル内の文字列の標準的な表現方法については現在も議論されていますが、POモードでは正規表現を実験的に採用しています。xgettextとPOモードで、同じ文字列を統一された方法で表示するのは、POモードで必要となる内部的な正規化が、GNU gettextからのxgettextの使用をも自動的に満たすので便利なのです。明示的なPOモードの正規化は、POファイルが他の場所からインポートされたときや、慣例そのものが変更されたときに必要です。

正規表現が必要なPOファイルの文字列を正規化するために、以下のPOモードのコマンドが利用可能です:

M-x po-normalize

エントリーをより標準化することにより、PO ファイル全体を整理します。

特別なコマンドであるM-x po-normalizeコマンド(キーは関連付けられていません)は、未翻訳のエントリーおよび翻訳済みのエントリー両方を、POファイル内部の標準的な引用符で括って、すべてのエントリーを修正します。このコマンドは最後のエントリーより後ろにあるゴミも削除します。このコマンドは、他の場所からインポートしたPOファイルを新たにインポートするときや、わたしたち自身がこの正規化された引用書式を改善していけるならば、有用となるでしょう。この正規化された書式はPOファイルを整理するだけでなく、ほかのPOモードのコマンドがmsgidから文字列を検索する処理のスピードを大幅に改善します。

M-x po-normalizeは、エントリーにたいして3パスの処理を行います。最初のパスで、複数行のmsgidmsgstrに、K&R CスタイルのC文字列書式を使用しているGNU gettext 0.6以前のPOファイルを発見して変換します。この発見的な処理は、廃止されたエントリーに関連付けられておらず、バックスラッシュで終端されたコメントでは失敗します。これは後続のパスで、廃止されたコメントに続くコメントを完成させる処理に依存します。この最初のパスは、すべての古いPOファイルの調整後は行われません。2番目と3番目のパスでは、すべてのmsgidmsgstrの文字列を、それぞれ正規化していきます。これらのパスではXViewのmsgfmtの継続行のためのバックスラッシュも除去します。

このように明示的に正規化を指定するコマンドは、他のソースからPOファイルをインポートするときだけではなく、現在使われている慣用句や美的観点による改善を容易にします。正規化コマンドで提案された調整を後で行うのは簡単で、最終的には他のGNU gettextツールも、この適合を自動化する必要があります。Emacsを持っていないが、それでもPOファイルを上手に手作りしたい人のために、以下では正規化された文字列の書式を説明します。

POモードの文字列は単一行か複数行になります。文字列内に埋め込まれた改行が存在するとき、すなわち‘[^\n]\n+[^\n]’というパターンにマッチする文字列は複数行になります。例えば以下のような文字列があったとします:

msgstr "\n\nHello, world!\n\n\n"

この文字列の空白を改行に置き換えると、以下のような文字列になります:

msgstr ""
"\n"
"\n"
"Hello,\n"
"world!\n"
"\n"
"\n"

ここでは問題点を明確にするために、カリカチュアーされた例を使用して議論していきます。通常、複数行の体裁は悪いものではありません。これを処理するための実装は多分、次のような提言にしたがったものになるでしょう。すべての改行、および空行を表す改行を空文字列の中にまとめます(n > 1からn-1番目の改行は文字列を区切る改行です)。これにより文字列は以下のようになります:

msgstr "\n\n"
"Hello,\n"
"world!\n"
"\n\n"

文字列の初期化に関しては、まだ未解決の点もあります。これらの問題については、解決されたものからこのドキュメントに記載されるでしょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.5 翻訳済みのエントリー

POファイル中のエントリーのmsgstrが翻訳されて、fuzzy(fuzzyエントリーを参照してください)もマークされていない場合、そのエントリーを翻訳済みのエントリーと呼びます。以後の処理では、翻訳済みのエントリーだけがGNU msgfmtでコンパイルされて、プログラムで利用できるようになります。他の種類のエントリーは除外され、それらにたいする翻訳は出力されません。

翻訳済みのエントリーを処理するためのコマンドがいくつかあります。

t

次の翻訳済みエントリーを検索します(po-next-translated-entry)。

T

前の翻訳済みのエントリーを検索します(po-previous-translated-entry)。

tコマンド(po-next-translated-entry)とTコマンド(po-previous-translated-entry)は、翻訳済みのエントリーを見つけて、前方または後方に移動するためのコマンドです。翻訳済みのエントリーが見つからなかった場合、POファイルのバッファーの先頭または終端に戻って検索します。

翻訳済みのエントリーは通常、翻訳者が翻訳を編集した結果です。翻訳の修正を参照してください。ただし変数po-auto-fuzzy-on-editnilでない場合、新しく翻訳されたエントリーは、公式な翻訳となる前に、最初はfuzzyエントリーになります。この場合、後でこのfuzzyエントリーのfuzzyを解消して、正式な翻訳済みのエントリーにする必要があります。fuzzyエントリーを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.6 fuzzyエントリー

POファイルのエントリーは、一連の属性を持っています。それらは名前から得られるような性質をもち、翻訳に関するシステムコメントを明示するために使用されます。その属性1つがfuzzyで、この属性をもつエントリーがfuzzy(あいまいな)な翻訳であることを示します。この属性がつけられたエントリーのことを、fuzzyエントリーと呼びます。

通常fuzzyエントリーは、おおよそ目的にあった翻訳であるような翻訳済みエントリーにたいして、翻訳者が見直しのために使用するものです。これらのfuzzyエントリーは、古い翻訳済みのPOファイルを新しいPOテンプレートファイルに対応して更新するために、msgmergeプログラムを適用することにより生成されることもあり、それはこのツールが、新しいmsgidが、古いものをわずかに修正したものであって、新しい修正されたエントリーに古い翻訳を選択できると推測したときです。元の文字列(msgid文字列)にたいするわずかな変更は、翻訳にも影響を与える場合があり、これは翻訳者による判断が必要です。あるエントリーにたいしてmsgmergeがfuzzyのマークを付与するのには、このような理由があるのです。

翻訳者が後で再検討する必要があるエントリーを覚えておくために、彼女自身の都合でエントリーをfuzzyとすることもあります。したがって特にfuzzyエントリーを処理するためのコマンドが、いくつかあります。

f

次のfuzzyエントリーを検索します(po-next-fuzzy-entry)。

F

前のfuzzyエントリーを検索します(po-previous-fuzzy-entry)。

TAB

カレントエントリーのfuzzy属性を取り除きます(po-unfuzzy)。

fコマンド(po-next-fuzzy-entry)とFコマンド(po-previous-fuzzy-entry)は、前方もしくは後方のfuzzyエントリーに移動します。fuzzyエントリーが見つからなかった場合、PO ファイルのバッファーの先頭または終端に戻って検索します。

TABコマンド(po-unfuzzy)は、エントリーに付与されているfuzzy属性を取り除いて、通常は翻訳済みのエントリーとします。さらに、変数po-auto-select-on-unfuzzynilでない場合には、TABコマンドにより自動的に他の対象となるエントリーに移動します。po-auto-select-on-unfuzzyの初期値はnil です。

po-auto-fuzzy-on-editの初期値はnilです。しかし変数po-auto-fuzzy-on-edittをセットすると、RETコマンドで編集したエントリーは、後から再チェックなどができるようにfuzzyとマークされます。この場合、通常の使用法では、翻訳者が変更したエントリーは、(すでにfuzzy だった場合をのぞき)fuzzyエントリーに変更されることになります。彼女が翻訳に満足した場合、TABを使えばfuzzy属性をクリアーするとともに、他のエントリーへと移動することができます。まだ翻訳が不十分だと思ったときは、SPCを使えばfuzzy属性を保持したまま他のエントリーに移動することができます。

翻訳者が作業中のエントリーを後で見直したいようなときに見つけやすいように、翻訳済みのエントリーをfuzzyとマークする場合は、DELコマンド(po-fade-out-entry)を使うこともできます。

翻訳者が作業を終えてPOファイルのバッファーをqコマンドで閉じるとき、まだfuzzyエントリーが残っている場合は、終了してもよいか確認を求められます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.7 未翻訳エントリー

xgettextで元となるPOファイルを作成する場合には、msgidは未翻訳の文字列で初期化され、msgstrには空文字列がセットされます。このように翻訳に空文字列がセットされているエントリーのことを、未翻訳(untranslated)のエントリーと呼びます。プログラマーがプログラム内の文字列に変更を加えた場合、変更された文字列にたいする新しい未翻訳のエントリーとしてPOファイル中に現れることになります。

未翻訳のエントリーにたいしても、有効なエントリー間の移動に通常使用するコマンドと同様のレベルで考えることができます。未翻訳のエントリーは、最後に‘msgstr ""があるので、容易に識別できます。

翻訳者の作業は(非常に簡単に表現するならば)、未翻訳のエントリーを探して編集・翻訳して、未翻訳のエントリーがなくなるまでそれを繰り返していくことではないでしょうか。特に未翻訳のエントリーを処理するためのコマンドが、いくつかあります。

u

次の未翻訳のエントリーを検索します(po-next-untranslated-entry)。

U

前の未翻訳のエントリーを検索します(po-previous-untransted-entry)。

k

カレントエントリーを未翻訳にします(po-kill-msgstr)。

uコマンド(po-next-untranslated-entry)とUコマンド(po-previous-untransted-entry)は、前方もしくは後方の未翻訳のエントリーに移動します。未翻訳のエントリーが見つからなかった場合、POファイルのバッファーの先頭または終端に戻って検索します。

kコマンド(po-kill-msgstr)は、単に翻訳された文字列を空文字列にすることによって、エントリーを未翻訳のエントリーにするコマンドです。翻訳の修正を参照してください。

翻訳者が作業を終えてPOファイルのバッファーをqコマンドで閉じるとき、まだ未翻訳のエントリーが残っている場合は、終了してもよいか確認を求められます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.8 陳腐化したエントリー

POファイルの陳腐化したエントリーとは、msgmergeによりローカライズされるパッケージ内で、その翻訳がもはや必要ないのでコメントアウトされているエントリーのことです。

陳腐化したエントリーにたいしても、有効なエントリー間の移動に通常使用するコマンドと同様のレベルで考えることができます。行にmsgidmsgstrが含まれているか否かに関係なく、行が#で開始されているという事実により、陳腐化したエントリーを識別できます。

再初期化するために翻訳を空文字列に置き換えて、元の未翻訳の空文字列にするコマンドがあります。これらのコマンドはEmacsのkillリングと互換性があるので、以前にkillリングに保存された文字列を翻訳として挿入することもできます。またユーザーは翻訳を対話的に編集することができます。これらすべてのコマンドは廃止されたエントリーの編集にも適用できますが、エントリーは廃止された状態のままになります。

陳腐化したエントリーに特化したコマンドがいくつかあります。

o

次の陳腐化エントリーを検索します(po-next-obsolete-entry)。

O

前の陳腐化したエントリーを検索します(po-previous-obsolete-entry)。

DEL

有効なエントリーにたいしては、それを陳腐化したエントリーにします。陳腐化したエントリーの場合は、エントリーを削除します(po-fade-out-entry)。

oコマンド(po-next-obsolete-entry)とOコマンド(po-previous-obsolete-entry)は、前方もしくは後方の陳腐化したエントリーに移動します。陳腐化したエントリーが見つからなかった場合、POファイルのバッファーの先頭または終端に戻って検索します。

PO モードには、陳腐化したエントリーにたいして、そのエントリーを非コメント化することにより有効なエントリーにする方法は用意されていません。用意されていない理由は、元となる未翻訳の文字列と、プログラム中の文字列の対応をとることができなくなるからで、これは msgid 駆動の哲学と反するからです。

とはいえ有効なエントリーをコメントアウトして、陳腐化したエントリーとすることは可能です。後でGNU gettextユーティリティーが処理するとき、翻訳が見つからなければ未翻訳の文字列が使用されます。DELコマンド(po-fade-out-entry)は、カレントエントリーを消滅の方向へと押しやるコマンドです。有効なエントリー(翻訳されたエントリー)の場合には、そのエントリーをfuzzyエントリーにします。すでにfuzzyエントリーの場合には、確認後にそのエントリーをコメントアウトします。すでに廃止されたエントリーの場合には、そのエントリーをPOファイルから削除します。削除した翻訳を、他のPOファイルの、(通常は)未翻訳のエントリに再使用するのは簡単です。翻訳の修正を参照してください。

今後POモードを開発していく上で、あなたを寝不足とさせるような、解決すべき興味深い問題が存在します。POモードをよりよくするこのアイデアとは、新しく出現した文字列にたいする翻訳として、すべての陳腐化したエントリーの中から最適な候補を推測することです。これはアルゴリズム的に解決するには困難な問題であり、文字列の相似をより効果的に計測するための開発を行う必要があると私は考えています。現在ではこれらの作業は翻訳者がすべて決定しなければなりませんが、いつの日か陳腐化したエントリーから翻訳を検索することができる便利なツールを提供できるように努力しています。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.9 翻訳の修正

POモードは、通常Emacsのバッファーを変更するような方法でPOファイルを直接編集することを防ぎます。そうすることで、直接編集してファイル全体のフォーマットや文字列の引用符を誤って編集してしまう等の、容易に発生し得るエラーを防ぎます。他の種類のエラーもありますが、それらのエラーは翻訳者がVコマンドを使っていつでも、バッチ検証プロセスにより発見・診断することができます。その他のエラーについては、翻訳者自身の判断と、彼女が翻訳したパッケージにたいする同じ母国語ユーザーによる、言語的な判定に頼る必要があります。

翻訳を作成し、機械的な診断およびユーザーによる報告を経た後、翻訳者は以下のコマンドを使って翻訳を変更します。

RET

翻訳を対話的に編集します(po-edit-msgstr)。

LFD
C-j

翻訳を元の未翻訳の文字列で再初期化します(po-msgid-to-msgstr)。

k

翻訳をkillリングに保存してから、削除します(po-kill-msgstr)。

w

翻訳をkillリングに保存するだけで、削除はしません(po-kill-ring-save-msgstr)。

y

翻訳をkillリングのもので置き換えます(po-yank-msgstr)。

RETコマンド(po-edit-msgstr)は、新しい翻訳を編集したり既存の翻訳を変更するための、新しいEmacsのウィンドウをオープンします。新しいウィンドウにはPOファイルのカレントエントリーの、翻訳のコピーが含まれています。翻訳のコピーは、すぐに編集できるように引用符を除かれていて、Emacsによる編集コマンドのすべてが使用できます。翻訳者が文字列の変更を終えたら、C-c C-cにより、自動的に引用符を付加した形式で結果を保存し、編集用のサブウィンドウを閉じることができます。変更を保存せずに取り消す場合には、C-c C-kを使用してください。詳細は、サブエディションの詳細を参照してください。

LFDコマンド(po-msgid-to-msgstr)は、翻訳を元の文字列で初期化します。このコマンドは通常、翻訳者が以前の作業を破棄して、元の文字列にたいして新しく翻訳をやり直したいときに使用します。

未翻訳のエントリーを編集するときに、常にLFDコマンドを自動的に実行させることもできます。po-auto-edit-with-msgidtをセットすれば、翻訳に何も文字列が設定されていない場合には、元の文字列により翻訳が初期化されます。デフォルトではpo-auto-edit-with-msgidnilです。

実際のところ、空の文字列から翻訳を開始するのか、それとも元の文字列のコピーから翻訳を開始するのかは好みの問題です。元の言語と、翻訳する言語があまりに異なっている場合には、単に空の文字列から開始するのがよいでしょう。その反対に元の言語と翻訳する言語が似ている場合には、元の文字列の数字や文字を再入力する手間を省きたいときもあるでしょう。未翻訳の余分な元文字列を取り除く手間がかかるとしても、彼女は元の文字列を見ながら未翻訳の文字列を翻訳で上書きしていく方法を好むかもしれません。

これにより、空文字列になる前の内容は、killリングと呼ばれる特別な場所に置かれます。wコマンド(po-kill-ring-save-msgstr)も、翻訳をkillリングにコピーする効果に違いはありませんが、エントリーをそのままにする点が異なります。この場合、エントリーから翻訳は削除されません。どちらのコマンドも、Emacs愛好家にはよく知られている共有バッファーである、Emacsのkillリングを使用します。

翻訳者は作業する過程で、kwを多く使うことでしょう。それにともないkillリングには翻訳が保存されていきます。killリングに保存された文字列は、後でEmacsの他のバッファーに挿入することができます。killリングは、単一のPOファイル内の異なるエントリー間だけではなく、翻訳者がPOファイルを複数開いている場合は、異なるPOファイル間で翻訳文字列を移動するのに使用されます。

POモードではないバッファーと文字列をやりとりするのを容易にするために、kコマンドでkillリングに置かれた翻訳文字列は、引用符が取り除かれて保存されます。すなわち、文字列を囲うための引用符は取り除かれ、複数行の文字列は結合され、バックスラッシュでエスケープされた文字は対応する実際の文字に変換されます。陳腐化したエントリーの場合、保存される前に翻訳は非コメント化されます。

yコマンド(po-yank-msgstr)は、カレントエントリーの翻訳をkillリングの文字列で完全に置き換えます。Emacsの用語にしたがうと、置き換えた文字列は、PO ファイルのバッファーへyank(yanked)されたといいます。Yanking in The Emacs Editorを参照してください。最初にyを使用したときは、killリングに最後に追加された値が翻訳として戻されます。他のキーを押さずに、もう一度yをタイプすると、killリングの最後から2番目に追加された文字列が、翻訳として挿入されます。yを何度も繰り返すことにより、望む文字列が見つかるまで、killリングに保存された文字列を巡回することができます。

文字列がPOファイルのエントリーにyankされるときには、自動的にPOファイルの書式にしたがった形式の引用符が付与されます。さらに陳腐化したエントリーの場合には、文字列は適切にコメント化されます。プログラムが使用できるように、翻訳された個々の文字列に引用符を付与するために、翻訳者が患わされることはありません。

kwだけが、文字列をkillリングに保存するコマンドではないことに注意してください。POモードの多くのコマンドは、翻訳された文字列(または翻訳者のコメント)を置き換えて、自動的にリングに保存します。この一般的なルールに当てはまらないコマンドは、yankコマンド自身です。

文字列のkillとyankについては、一般的な状況の実例で説明したほうがよいでしょう。プログラマーが文字列にちょっとした変更を加えたとしましょう。その後、彼が行った変更は、変更した文字列にたいする新しい未翻訳のエントリーとしてPOファイルに出現し、元の変更されていない文字列にたいする翻訳は、陳腐化したエントリーとなります。多くの場合、翻訳者は未翻訳エントリーのmsgstrに、陳腐化したエントリーの変更前の翻訳を流用することで作業を節約できるでしょう。その後、陳腐化したエントリーが必要ないなら、安全に削除することができます。

翻訳者が未翻訳のエントリーを見つけて、それが既存の翻訳と少ししか違わないのではないか、と思ったとしましょう。そのような場合は、すぐにカレントエントリーの場所をmでマークしてから、陳腐化したエントリーを検索して、変更される前の文字列にたいする翻訳を探すためにoを使用します。見つかったら、DELコマンドで廃止されたエントリーを削除します。なぜなら彼女はDELコマンドが翻訳をkillすることを知っており、それはつまり翻訳がkillリングに保存されることを知っているからです。その後rコマンドで最初の未翻訳エントリーに戻り、保存した翻訳をyコマンドでmsgstryankします。これで翻訳者は、RETを使って自由に翻訳内容を調整することができます。そしてその後は再びumで次の未翻訳の文字列を探していくのかもしれません。

翻訳者が同じキーシーケンスを何度も使用する必要があるときには、要求したときにそのキーシーケンスを再生させるEmacsの機能について学習するほうがよいかもしれません。Keyboard Macros in The Emacs Editorを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.10 コメントの修正

翻訳とは、言語的な難しさをともなう作業です。翻訳においてどのような決定をしたのか、その選択に関してドキュメントを残す必要があるでしょう。これらのドキュメントは、翻訳者のコメントとしてPOファイルに保存されます。これは、翻訳者が自由に作成・削除、または変更ができるコメントで、彼女が後でPOファイルを見直すときなどに便利です。

最初の‘#’の後に空白がないコメント、たとえば‘#.’や‘#:’ではじまるコメントは、翻訳者のコメントではありません。これらは、gettextツールにより作成されたコメントです。それらのシステムが追加したコメントは、翻訳者が変更するべきではないコメントなので、以下で説明するコマンドの対象外です。POファイルのフォーマットを参照してください。

以下のコマンドは翻訳を変更するコマンドと似ているので、一般的な原則は同様に適用できます。翻訳の修正を参照してください。

#

翻訳者のコメントを対話的に編集します(po-edit-comment)。

K

翻訳者のコメントをkillリングに保存してから、削除します(po-kill-comment)。

W

翻訳者のコメントをkillリングに保存するだけで、削除はしません(po-kill-ring-save-comment)。

Y

翻訳者のコメントを、killリングのもので置き換えます(po-yank-comment)。

これらの、翻訳文字列を変更するためのPOモードの類似コマンドは、翻訳文字列の代わりに翻訳者のコメントを処理する以外は、同じように動作します。詳細はすでに説明済みなので、以下ではこれらのコマンドを簡単に説明します。翻訳の修正を参照してください。

#コマンド(po-edit-comment)は、POファイルのカレントエントリーにたいする翻訳者コメントのコピーを含む、新しいEmacsウィンドウをオープンします。エントリーにそのようなコメントがない場合、POモードは翻訳者がエントリーにコメントを追加したいと解釈し、空のスクリーンが表示されます。編集前にコメントマーク(#)とそれに続くスペースは自動的に削除され、編集後に自動的に再付加されます。陳腐化したエントリーにたいする翻訳者コメントは、非コメント化とコメント化の操作が2度行われます。編集ウィンドウでC-c C-cキーを押すと、コメントの編集を終了します。詳細については、サブエディションの詳細を参照してください。

po-subedit-mode-hookに関数が登録されている場合には、編集バッファーに文字列が挿入されたときに実行されます。

Kコマンド(po-kill-comment)は、翻訳者コメントをkillリングに保存してから削除します。Wコマンド(po-kill-ring-save-comment)は、翻訳者コメントをkillリングにコピーするだけで、カレントエントリーのコメントは変更しません。Yコマンド(po-yank-comment)は、翻訳者コメントをkillリングの文字列で置き換えます。このコマンドを繰り返し入力すると、挿入されたコメントはkillリングに保存された他の文字列で順に置き換えられます。

killリングの文字列は、すべて同じ性質をもちます。翻訳された文字列翻訳者のコメントに違いはありません。たとえば翻訳者が翻訳を終了したとき、以前の翻訳の何が悪かったのかをドキュメント化して覚えておこうと、コメントを付与したい場合を考えます。彼女は翻訳者コメントで、以前の翻訳を引用したいと思うのではないでしょうか。それを行うには、まず翻訳者コメントを、killリングに残っている以前の翻訳で初期化するでしょう。すでにkillリングに保存されている以前の翻訳を使って編集するには、#の前にM-wとタイプすれば、以前の翻訳がkillリングに保存されるので、それに説明文などを追加すればよいでしょう。

すでに何らかの翻訳者コメントがあり、そのコメント全体を置き換えるのではなく翻訳者がコメントを追加したい場合を考えてみましょう。その場合には#でコメントを編集する必要があります。編集ウィンドウが開いたら、Emacsの標準コマンドのC-y(yank)とM-y(yank-pop)で、以前の翻訳を取得できます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.11 サブエディションの詳細

PO subeditマイナーモードは、ここで詳細な説明をする価値のある特殊なモードです。これによりEmacsの通常の編集コマンド以外に、以下で説明するコマンドがインストールされます。

C-c C-c

編集を完了します(po-subedit-exit)。

C-c C-k

編集を中止します(po-subedit-abort)。

C-c C-a

追加(auxiliary)のPOファイルを参照します(po-subedit-cycle-auxiliary)。

ウィンドウにはメッセージにたいする翻訳、もしくは翻訳者コメントが表示されます。翻訳者は自分の思うように、このウィンドウ内のコンテンツを変更します。作業が終わったら、C-c C-cコマンド(po-subedit-exit)を使えば、バッファーが切り替えられていたり、表示されていなくても、編集した翻訳で元の翻訳を置き換えてPOファイルに反映することができます。

kill翻訳者が自分の翻訳(または翻訳者コメント)に満足できなくて、RETコマンド(または#コマンド)を押す前の状態に戻したい場合には、C-c C-kコマンド(po-subedit-abort)を使えば、編集したものを破棄して、元の翻訳(または翻訳者コメント)に戻すことができます。他にも、普通にC-c C-cで編集を終了してから、U(訳注: UndoをするコマンドがUコマンドと記述してあるが、EmacsのUndoコマンドであるCtrl+_コマンドの間違いではないか)で元のバージョンに戻す方法があります。

C-c C-aコマンド(po-subedit-cycle-auxiliary)は、カレントエントリーの翻訳を編集しているとき、すでに他の言語へ翻訳されたメッセージに目を通したいときに使用します。このコマンドは翻訳者が複数の言語に通じているときなどに便利でしょう(もちろん利用可能な追加のPOファイルがある場合ですが(追加POファイルを調べるを参照してください)。

po-subedit-mode-hookに関数が登録されている場合には、編集バッファーに文字列が挿入されたときに実行されます。

編集中には、翻訳文字列の最後で意図せずRET(改行)キーを入力したり、必要な改行を誤って削除していまわないよう注意を払う必要があります。そのような文字が編集バッファーで非表示になっていると、容易に間違いを犯してしまいます。そのような間違いが起きないように、RETコマンドでは、編集している文字列の最後に自動的に<が付加されます。この<は実際のメッセージ文字列ではありません。C-c C-cで編集ウィンドウを閉じると、POモードは自動的にそのような<文字を削除して、適切な空白文字に置き換えます。翻訳者が末尾の<の後ろに文字を追加すると、<は区切り文字としての性質を失って、翻訳文字列の一部となります。<を削除した場合には、編集文字列はそのまま評価され、たとえ非表示であったとしても、末尾に改行があればそれもそのまま評価されます。翻訳した文字列が本物の<で終わる場合には、区切り文字の<も削除されずに表示されるので、編集ウィンドウの文字列の終端には2つの<が表示されます。

翻訳(またはコメント)を編集するとき、翻訳者はカーソルをPOファイルのバッファーに戻してから、エントリーを表示するために自由に他のエントリーに移動を行えます。編集を保留して、POファイルバッファーの他の箇所に移動したり、他のエントリーの編集をはじめることもできます。それぞれのエントリーは、それら自身のサブエディットバッファーで編集されます。1つのエントリーにたいする特定の翻訳やコメントを同時に編集したり、異なるPOファイルのエントリーを同時に編集することも可能です。すでに編集中のエントリーにたいしてRETをタイプすると、単にそのエントリーの編集を再開します。Emacsの複数のウィンドウの扱いに慣れれば、翻訳者はより快適になるでしょう。

保留したサブエディットの完了または中止は、編集を開始した順番に関わらず任意の順番で行うことができます。複数のサブエディットを保留している状態で、(qコマンドで)POファイルを閉じようとすると、サブエディットが1つずつ順番に再開されるので、翻訳者それら個々について決定していくことができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.12 Cソースのコンテキスト

POモードは、GNU gettextユーティリティーで作成されたPOファイルの場合、それらのユーティリティーが生成したPOファイルに特別なコメントを挿入するので、特に威力を発揮します。それらの特別なコメントの中には、POファイルのエントリーの未翻訳の文字列が、プログラムのソース中で出現する位置を示すものがあります。

翻訳者が未翻訳の文字列を翻訳するとき、その元文字列があまりに簡潔すぎたり、不可解あったり、曖昧である等、通常のように有効でない場合があります。そのような文字列をどのように翻訳するか決める前に、その文字列が本当は何を意味するのか、そしてそれにぴったりな翻訳は何なのかを理解する必要があります。このような問題を判断するために残された唯一の方法は、プログラムのソースからその文字列の場所を探し、その周辺に残されたプログラマーのコメントや、他に助けになりそうな何かを探すことに時間を割くことです。

翻訳者が有能なプログラマーである場合、プログラムのソースを見ることにより多くの助けを得ることができるでしょう。しかしプログラミングに精通していなくて、Cのコードを見ると不安な気持ちになったとしても、恥ずかしがらずにたまにはソースを見てみましょう。そうすれば彼女が必要とする何らかのヒントを得られるようになれるでしょう。プログラマーのコメント、そして(彼が適切な名前をつけていれば)変数名や関数名、プログラムコード自体の全体的な構成などに注意を払って学習することにより、すぐにプログラムのコードを見ても違和感を感じないようになるでしょう。

以下は、翻訳者がPOファイルのエントリーから、プログラムのソースコンテキストを参照するのに助けとなるコマンドです。

s

プログラムのソースコンテキストを表示、またはソースコンテキストのサイクル表示を再開します(po-cycle-source-reference)。

M-s

メニューで選択されたプログラムソースのコンテキストを表示します(po-select-source-reference)。

S

ソースファイルの検索パスにディレクトリを追加します(po-consider-source-path)。

M-S

ソースファイルの検索パスからディレクトリを削除します(po-ignore-source-path)。

sコマンド(po-cycle-source-reference)とM-sコマンド(po-select-source-reference)は、どちらも他のウィンドウを開いてプログラムのソースファイルの、翻訳しようとしている文字列が使用されている場所を表示します。このように、これらのコマンドは文字列にたいするソースプログラムのコンテキストを与えます。しかしエントリーがコンテキストへの参照を保有していなかったり、検索パスにあるプログラムソースでは参照が解決されない場合、コマンドはその旨をエラーとして表示します。

s(またはM-s)も新しいウィンドウをオープンしますが、カーソルはPOファイルのウィンドウに留まったままです。翻訳者がプログラムソースのウィンドウに移動したい場合には、明示的にOコマンドを使用する必要があります。

はじめてsを使用するときや、POファイルのエントリーのソースコンテキストが直前に取得したものと異なるときには、コマンドはこのエントリーにたいして利用可能な、最初のコンテキストを返します。すでにそのPOファイルのカレントエントリーにたいする、何かしらのコンテキストを表示していて、さらに他のものを探したいときには最後に表示したコンテキストのウィンドウでsを入力することにより、検索を再開できます。このコマンドにより、翻訳者がソースファイルのコンテキストからカーソルを移動していた場合には、カーソルがコンテキストの場所に戻されます。他のコマンドを入力しないでsコマンドを連続して入力すると、POモードはこのエントリーにたいして利用可能なコンテキストを順々に表示していき、最後のコンテキストを表示すると、また最初のコンテキストに戻って表示します。

M-sコマンドは異なる動作をします。このコマンドは参照を循環して表示せずに、いくつか存在する参照のうちから1つを翻訳者に選択させます。翻訳者がM-sで表示される質問にたいして、すぐにTABを押すと、翻訳者が適切なものを選べるように利用可能なすべての参照メニューが表示されます。このコマンドは翻訳する1つの文字列にたいして、多数の利用可能なコンテキストが存在するときに有用です。

プログラムのソースファイルは通常、POファイルの場所から相対的に見つけることができます。この検索が失敗したときには、特別なケースとしてPOファイルの1つ上のディレクトリーからの相対パスのファイルも検索対象になります。これらの2つのケースを考えておけば、大抵のPOファイルを処理することができます。しかしPOファイルが移動されていたり、通常あるべき場所とは異なる場所で編集されているときには検索が失敗します。このような場合には、翻訳者がPOモードにたいして、POファイルが本来どのディレクトリーにあるのかを、伝える必要があります。そのように指定したディレクトリーのことをまとめて、プログラムソースの検索パスと呼びます。Sコマンド(po-consider-source-path)は、検索パスに新しいディレクトリーを対話的に入力するために使用され、M-Sコマンド(po-ignore-source-path)は、検索パスから削除したいディレクトリーを選択して削除するのに使用されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3.13 追加POファイルを調べる

POモードには、複数の言語に通じている翻訳者が、彼女の知っている言語への既存の翻訳を利用するための機能があります。この機能は、他の言語への翻訳を追加のコンテキストとして、彼女の作業に提供することができます。また一度に複数の言語への翻訳を作成したいような場合にも、翻訳者にたいして作業を容易にするための機能をもっています。

追加(auxiliary)のPOファイルとは、翻訳者が作業するパッケージの、他の言語用の既存のPOファイルのことです。追加のPOファイルを定義・処理したり、作業中のエントリーのコンテキストを表示するためのコマンドが存在します。

以下は、POモードで利用可能な、追加のPOファイルのコマンドです。

a

追加のPOファイルから、同じエントリーにたいする他の翻訳を探します(po-cycle-auxiliary)。

C-c C-a

追加のPOファイルを指定して、それに切り替えます(po-select-auxiliary)。

A

表示しているPOファイルを、追加のPOファイルとして定義します(po-consider-as-auxiliary)。

M-A

表示しているPOファイルを、追加のPOファイルのリストから削除します(po-ignore-as-auxiliary)。

Aコマンド(po-consider-as-auxiliary)は、現在のPOファイルを、追加のPO ファイルのリストに追加し、M-Aコマンド(po-ignore-as-auxiliaryは、リストから削除します。

aコマンド(po-cycle-auxiliary)は、すべての追加POファイルを一つずつ走査して、カレントエントリーと同じmsgidにたいする、他の言語に翻訳されたエントリーを検索するコマンドです。POファイルが見つかったら、そのPOファイルが現在のウィンドウに表示されます(そのウィンドウがもっとも前面に表示されます)。追加のPOファイルに作業中のPOファイルが含まれていない場合は、これらの処理を行う前に追加しておくとよいでしょう。このようにしておけば、aコマンドで検索された他言語のPOファイルがウィンドウに表示されても、aコマンドを繰り返し入力して、元のPOファイルに戻ることができるからです。

C-c C-aコマンド(po-select-auxiliary)は、翻訳者にたいして追加のPOファイルを補完付き入力で選択させて、そのPOファイルに切り替えるコマンドです。選択したPOファイルにカレントエントリーと同じmsgidがあった場合は、そのエントリーをカレントエントリーとします。同じエントリー存在しない場合には、カーソルは元の位置から変更されません。

この機能が完全に動作するためには、msgidが、同じ方法で正確に、正規化されて記述されている必要があります。たとえ文字列を記述する方法は異なっていてもmsgidに同じ文字列が設定されていれば問題はありませんが、違う文字列が記述されていると、POモードの追加POファイル関連のコマンドの動作が損なわれてしまいます。しかしほとんどのPOファイルのmsgidは、同じGNU gettextツールで書き込まれたものなので、実際には問題になることはないでしょう。

しかしソースファイルの文字列をマークしながら、POモードで一から作成したPOファイルは、異なる形式で正規化されています。そのために‘M-x normalize’コマンドをPOファイルに適用するのです。POモードと他のGNU gettextツール間の矛盾を解決するまでは、翻訳者は正規化の問題に留意してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4 翻訳compendiaの使用

compendium(要約)とは、多くのパッケージで繰り返し使用される翻訳を含んだ特別なPOファイルのことです。翻訳者はgettextツールを使って、新しいcompendiumを構築して、compendiumに含まれた翻訳から、エントリーをcompendium に追加したり、未翻訳エントリーの初期化、既存の翻訳済みエントリーの更新できます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4.1 compendiaの作成

基本的に、すべてのPOファイルに含まれる翻訳済みエントリーだけを、有効なcompendiumとして定義できます。翻訳者が特別なcompendiaを所有したい場合があります。連結POファイル(concatenating PO files)POファイルからメッセージを抽出したサブセット(extracting a message subset from a PO file)という、2つのケースを考えてみましょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4.1.1 POファイルの連結

複数の有効なPOファイルを、1つのcompendiumファイルに連結するためには、‘msgcomm’か、‘msgcat’(推奨)を使用することができます:

msgcat -o compendium.po file1.po file2.po

デフォルトでは‘msgcat’は、同じ文字列にたいして異なる翻訳がある場合には、それらの翻訳を蓄積します。これらの複数の翻訳にはfuzzyマークが付与されるとともに、目立つように装飾されます。たとえば以下のような2つのファイルがあるとします。file1.poは以下のような内容です:

#: src/hello.c:200
#, c-format
msgid "Report bugs to <%s>.\n"
msgstr "Comunicar `bugs' a <%s>.\n"

そしてfile2.poです:

#: src/bye.c:100
#, c-format
msgid "Report bugs to <%s>.\n"
msgstr "Comunicar \"bugs\" a <%s>.\n"

これらにたいしてmsgcatを呼び出すと、以下のような結果になります:

#: src/hello.c:200 src/bye.c:100
#, fuzzy, c-format
msgid "Report bugs to <%s>.\n"
msgstr ""
"#-#-#-#-#  file1.po  #-#-#-#-#\n"
"Comunicar `bugs' a <%s>.\n"
"#-#-#-#-#  file2.po  #-#-#-#-#\n"
"Comunicar \"bugs\" a <%s>.\n"

“競合”は翻訳者が手動で解決する必要があります。彼女は最初のバージョンが適しているのか、それとも2番目のバージョンなのか(それとも新しい翻訳を提供する必要があるのか)を決定して、“マーカー行”を削除し、fuzzyマークをはずす必要があります。

最初に検索される翻訳済みのメッセージが常に最善の翻訳であることを翻訳者が知っている場合は、‘--use-first’スイッチを使用できます:

msgcat --use-first -o compendium.po file1.po file2.po

よいcompendium ファイルを作るには、fuzzyや未翻訳エントリーを含めてはいけません。入力ファイルがそのようなエントリーで“汚染”されている場合は、‘msgattrib --translated --no-fuzzy’を使って入力ファイルを前処理するか、結果ファイルを後処理しなければなりません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4.1.2 POファイルからのメッセージサブセットの抽出

同じメッセージを何度も翻訳したいと思う人はいないでしょう。たとえば、あなたがgetopt.cのメッセージを含んだcompendiumファイルが欲しいと思うかもしれません。

既存のPOファイルから1つのcompendiumにメッセージのサブセット(例: getopt.cのすべてのメッセージ)を抽出する場合は、‘msggrep’を使用できます。

msggrep --location src/getopt.c -o compendium.po file.po

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4.2 compendiaの使用

compendiumファイルを使用して、スクラッチから翻訳を初期化したり、既存の翻訳を更新できます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4.2.1 新しい翻訳ファイルの初期化

まだ翻訳されたPOファイルが存在しないときは、“古い”翻訳済みファイルとして/dev/nullを使用できます。

msgmerge --compendium compendium.po -o file.po /dev/null file.pot

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4.2.2 既存の翻訳ファイルの更新

compendiumファイルと既存のPOファイルを結合した後、それをマージしてPOTファイルを作成し、陳腐化したエントリーを削除します(これは任意です。ここでは‘msgattrib’が使用されています)。

msgcat --use-first -o update.po compendium1.po compendium2.po file.po
msgmerge update.po file.pot | msgattrib --no-obsolete > file.po

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9 POファイルの操作

POファイルを手で扱うよりは、自動的な方法で取り扱うほうがよいときがあります。GNU gettextには、この目的のための完全なツールが含まれています。

2つのパッケージを1つのパッケージにマージするときには、元の2つのパッケージのPOTファイルが結合されたものが、マージされたパッケージのPOTファイルになります。したがってメンテナーは、翻訳された各言語ごとに、既存の2つの翻訳済みパッケージを1つの翻訳カタログにマージしなければなりません。これを行うには‘msgcat’を使うのが最善です。マージにより発生し得る競合を解決するのは、翻訳者の役目となります。

ある翻訳者が他の翻訳者から作業を引き継ぐときに、彼女がそのlocaleの異なるエンコーディングを使っている場合には、カタログの文字のエンコーディングを変換することになるでしょう。これを行うには‘msgconv’プログラムを使うのが最善です。

メンテナーが他のパッケージからタグ付けされたメッセージを取得するとき、彼はこのソースファイルの既存の翻訳も取り込む必要があります(翻訳者が同じ作業をしなくても済むように)。これを行うには‘msggrep’を使う方法と、そのソースファイルからPOTファイルを作成して‘msgmerge’を使う方法があります。

翻訳者がある翻訳カタログを特定の方言や正書法に適応させたいとき – たとえばSwitzerlandで記述されたGermanを、Germanyで記述されたGerman に適応させる場合など – 彼女はカタログの中のすべてのメッセージに適用できるテキストプロセッサーが必要にるでしょう。これを行うためのツールが、‘msgfilter’です。

msgfilterの他の使い方としては、POファイルが作成される元となったPOTファイルに近いものを生成することです。これは、‘msgfilter sed -e d | sed -e '/^# /d'’のようなフィルターコマンドにより行うことができます。オリジナルのPOTファイルには異なるコメントがあったり、plural messageの数も異なります。この理由により、利用可能ならオリジナルのPOTファイルを使うほうがよいことに注意してください。

翻訳者が翻訳をチェックしたいとき、たとえば正書法のルールや非対話型のスペルチェッカーにしたがってチェックをしたいときは、‘msgexec’を使うことができます。

サードパーティー製のツールによりPO、またはPOTファイルを作成するとき、重複が無視されるときがあります。しかしGNU gettextツールは、同じファイル中に同じドメインで重複したmsgidがある場合にはエラーとなります。重複をマージするためには、‘msguniq’を使うことができます。

複数のファイル間での重複を維持(または破棄)するための、より一般的なツールとしては‘msgcomm’があります。

翻訳カタログが完全に翻訳されているかをチェックするには、‘msgcmp’を使うことができます。

翻訳カタログからfuzzyや未翻訳のメッセージだけを選択・抽出するためには、‘msgattrib’を使うことができます。

Englishの翻訳カタログを準備するための最初のステップとしては、‘msgen’が便利です。これは、各メッセージのmsgidをmsgstrにコピーします。

そして最後に、これらの様々なアプリケーションでも十分でない場合には、POファイルを取り扱う特殊なプログラムを記述するために使用できる、‘libgettextpo’ライブラリーが提供されています。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1 msgcatプログラムの呼び出し

msgcat [option] [inputfile]...

msgcatプログラムは、指定されたPOファイルを結合・マージするプログラムです。プログラムは、指定された複数のPOファイルの中から、2つ以上のファイルで使用されている共通のメッセージを見つけます。--more-thanオプションを使うと、指定したファイル数より多くのファイルで共通のメッセージを出力するか指定できます。反対に--less-thanオプションでは、指定したファイル数より少ないファイルで共通のメッセージを出力するか指定できます(例 ‘--less-than=2’ と指定すると一意なメッセージだけが出力されます)。翻訳やコメントは累積されますが、--use-firstを指定した場合は、指定されたPOファイルのうちで最初のものを採用します。すべてのPOファイルの位置情報も累積されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1.1 入力ファイルの位置

inputfile

入力ファイルです。

-f file
--files-from=file

入力ファイルの名前を、コマンドラインからではなく、fileから読み込みます。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileに‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1.2 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1.3 メッセージ選択

-< number
--less-than=number

numberに指定した数より少ないメッセージを出力します。指定しなかった場合のデフォルトは無限大です。

-> number
--more-than=number

numberに指定した数より大きいメッセージを出力します。指定しなかった場合のデフォルトは0です。

-u
--unique

--less-than=2’の省略指定です。一意なメッセージだけを出力します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1.4 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1.5 出力の詳細

-t
--to-code=name

出力のエンコーディングを指定します。

--use-first

各メッセージで利用可能な最初のメッセージを使用します。複数の翻訳を1つにマージしません。

--lang=catalogname

ヘッダーのエントリーで使用される、‘Language’フィールドを指定します。このフィールドの意味については、ヘッダーエントリーを入力するを参照してください。‘Language-Team’と‘Plural-Forms’のフィールドは変更されないことに注意してください。

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

-i
--indent

インデントされた形式で.poファイルを書き込みます。

--no-location

#: filename:line’という行を書き込みません。

-n
--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、陳腐化したメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

-F
--sort-by-file

ファイルの場所により出力をソートします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1.6 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2 msgconvプログラムの呼び出し

msgconv [option] [inputfile]

msgconvは、ある翻訳カタログを別の文字エンコーディングに変換するプログラムです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.1 入力ファイルの位置

inputfile

入力となるPOファイルです。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileが指定されていないか、‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.2 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.3 変換する対象

-t
--to-code=name

出力のエンコーディングを指定します。

デフォルトのエンコーディングは、現在のロケールのエンコーディングです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.4 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.5 出力の詳細

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

-i
--indent

インデントされた形式で.poファイルを書き込みます。

--no-location

#: filename:line’という行を書き込みません。

--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、陳腐化したメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

-F
--sort-by-file

ファイルの場所により出力をソートします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.6 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3 msggrepプログラムの呼び出し

msggrep [option] [inputfile]

msggrepは翻訳カタログから、指定したパターン、指定したソースファイルに属するすべてのメッセージを抽出するプログラムです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3.1 入力ファイルの位置

inputfile

入力となるPOファイルです。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileが指定されていないか、‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3.2 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3.3 メッセージ選択

  [-N sourcefile]... [-M domainname]...
  [-J msgctxt-pattern] [-K msgid-pattern] [-T msgstr-pattern]
  [-C comment-pattern]

以下のような場合、メッセージが選択されます

1つ以上の条件を指定した場合には、それぞれの条件に適合するメッセージのがすべて選択されます。

msgctxt-patternmsgid-patternmsgstr-patternの書式です:

  [-E | -F] [-e pattern | -f file]...

patternにはデフォルトでは標準の正規表現(POSIX Basic Regular Expressions: grep -eと同等)を指定します。拡張された正規表現(POSIX Extended Regular Expressions: egrep, grep -Eと同等)の場合は-Eを、固定文字列の場合(Fixed String search: fgrep, grep -Fと同等)には-Fを指定してください。

-N sourcefile
--location=sourcefile

sourcefileから抽出されたメッセージを選択します。sourcefileにはファイル名の文字列、またはワイルドカード文字列を指定できます。

-M domainname
--domain=domainname

ドメインdomainnameに属するメッセージを選択します。

-J
--msgctxt

msgctxtを選択するためのパターンの開始を宣言します。

-K
--msgid

msgidを選択するためのパターンの開始を宣言します。

-T
--msgstr

msgstrを選択するためのパターンの開始を宣言します。

-C
--comment

翻訳者コメントを選択するためのパターンの開始を宣言します。

-X
--extracted-comment

抽出コメントを選択するためのパターンの開始を宣言します。

-E
--extended-regexp

patternが、拡張された正規表現であることを指定します。

-F
--fixed-strings

patternが、改行で区切られた一連の文字列であることを指定します。

-e pattern
--regexp=pattern

patternを、正規表現として使用します。

-f file
--file=file

patternを、fileから取得します。

-i
--ignore-case

大文字と小文字を区別しません。

-v
--invert-match

条件に一致するメッセージではなく、一致しないメッセージだけを出力します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3.4 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3.5 出力の詳細

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

--indent

インデントされた形式で.poファイルを書き込みます。

--no-location

#: filename:line’という行を書き込みません。

--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、陳腐化したメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

--sort-by-file

ファイルの場所により出力をソートします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3.6 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3.7 例

gnulib-lib/error.cgnulib-lib/getopt.cというソースファイルからメッセージを抽出する場合:

msggrep -N gnulib-lib/error.c -N gnulib-lib/getopt.c input.po

“Please specify”という文字列が含まれるメッセージを抽出する場合:

msggrep --msgid -F -e 'Please specify' input.po

“Menu>File”、“Menu>Edit”またはそれらのサブメニューであることを指定するコンテキストをもつメッセージを抽出する場合:

msggrep --msgctxt -E -e '^Menu>(File|Edit)' input.po

翻訳文字列にwordlist.txtというファイル中の文字列を含むメッセージを抽出する場合:

msggrep --msgstr -F -f wordlist.txt input.po

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4 msgfilterプログラムの呼び出し

msgfilter [option] filter [filter-option]

msgfilterは、翻訳カタログ内の翻訳にフィルターを適用するためのプログラムです。

それぞれのfilter呼び出しにおいて、環境変数のMSGFILTER_MSGIDMSGFILTER_LOCATIONに、メッセージのmsgidとメッセージを含むPOファイルの場所がバインドされます。メッセージがコンテキストを保有する場合は、環境変数MSGFILTER_MSGCTXTがメッセージのコンテキストにバインドされます(コンテキストを保有していない場合にはバインドされません)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4.1 入力ファイルの位置

-i inputfile
--input=inputfile

入力となるPOファイルです。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileが指定されていないか、‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4.2 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4.3 フィルター

filterは、標準入力から翻訳を読み込み、それに変更を加えて標準出力に書き込むプログラムです。フィルターとして頻繁に使用されるプログラムとしては‘sed’があります。その他にも認識できるビルトインフィルターがいくつか存在します。

注意: ビルトインではないフィルターの場合には、エンコーディングに注意する必要があります。filterが、入力となる翻訳カタログのエンコードに対処できるようにするのは、あなたの責任となります。filterが入力として特定のエンコーディングを期待する場合には、‘msgfilter’を呼び出す前に、最初のステップとして‘msgconv’で翻訳カタログをそのエンコーディングに変換できます。filterが入力としてlocaleのエンコーディングを期待しているけれど、あなたはlocaleのエンコーディングを無視したいときには、最初に‘msgconv’で翻訳カタログをUTF-8に変換してから、環境変数LC_ALLにUTF-8 localeを指定して、‘msgfilter’を使うことができます。

注意: 翻訳カタログ内のほとんどの翻訳は改行で終端されていません。そのため、入力の最終行が改行で終端されていなくても、filterがそれを認識すること、そして最終行に余分な改行を付加しないことが重要になります。いくつかのプラットフォームにおいて‘sed’が、改行で終端されていない最終行を無視することが知られています。代用として、このような制限を持たないGNU ‘sed’を使うことができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4.4 filterが‘sed’のときの便利なfilter-option

-e script
--expression=script

実行するコマンドにscriptを追加します。

-f scriptfile
--file=scriptfile

実行するコマンドに、scriptfileの内容を追加します。

-n
--quiet
--silent

パターンの空白の出力を自動的に抑制します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4.5 ビルトインのfilter

recode-sr-latin’はビルトインのフィルターとして認識されます。‘recode-sr-latin’は、Cyrillic文字で記述されたSerbianのテキストを、Latin文字に変換するコマンドです。‘msgfilter recode-sr-latin’コマンドにより、POファイルの翻訳にたいしてこの変換を適用できます。これを使えばsr.poファイルを、sr@latin.poファイルに変換できます。

ビルトインのフィルターは、現在のロケールのエンコーディングとは無関係です。またビルトインのフィルターを使う場合、‘msgfilter’はメッセージカタログのエンコーディングを自動的にUTF-8に変換することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4.6 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4.7 出力の詳細

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

--indent

インデントされた形式で.poファイルを書き込みます。

--keep-header

ヘッダーのエントリーを保持します(例: ‘msgid ""’にフィルターを適用しないで未変更にします)。デフォルトでは、ヘッダーのエントリーにたいしても、他のメッセージと同様にフィルタリングの対象になります。

--no-location

#: filename:line’という行を書き込みません。

--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、陳腐化したメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

-F
--sort-by-file

ファイルの場所により出力をソートします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4.8 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4.9 例

Germanの翻訳を、Swissの正書法に変換する場合(UTF-8 locale):

msgconv -t UTF-8 de.po | msgfilter sed -e 's/ß/ss/g'

Cyrillic文字の Serbianの翻訳を、Latin文字に変換する場合:

msgfilter recode-sr-latin < sr.po

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5 msguniqプログラムの呼び出し

msguniq [option] [inputfile]

msguniqは、翻訳カタログ内の重複した翻訳を統一するためのプログラムです。このプログラムは、同じメッセージIDにたいする、重複した翻訳を探します。このような重複したメッセージは、msgfmtmsgmergemsgcatの入力としては無効です。デフォルトでは重複はマージされます。‘--repeated’オプションを指定すると、重複したメッセージだけが出力され、他のすべてのメッセージは破棄されます。コメント、および抽出されたコメントは累積されます。ただし‘--use-first’が指定された場合には、最初の翻訳のものが使用されます。‘--unique’オプションを使用すると、重複は破棄されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.1 入力ファイルの位置

inputfile

入力となるPOファイルです。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileが指定されていないか、‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.2 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.3 メッセージ選択

-d
--repeated

重複したメッセージだけを出力します。

-u
--unique

一意なメッセージだけを出力します(重複したメッセージは破棄されます)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.4 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.5 出力の詳細

-t
--to-code=name

出力のエンコーディングを指定します。

--use-first

各メッセージで利用可能な最初のメッセージを使用します。複数の翻訳を1つにマージしません。

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

-i
--indent

インデントされた形式で.poファイルを書き込みます。

--no-location

#: filename:line’という行を書き込みません。

-n
--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、知能化したメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

-F
--sort-by-file

ファイルの場所により出力をソートします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.6 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6 msgcommプログラムの呼び出し

msgcomm [option] [inputfile]...

msgcommは、指定された2つ以上のファイルから、共通のメッセージを探すプログラムです。--more-thanオプションを使用すると、指定された数より多くのファイルで共通のメッセージを出力します。反対に--less-thanオプションを使用すると、指定された数より少ないファイルで共通のメッセージを出力します(例: ‘--less-than=2’は一意なメッセージだけを出力します)。翻訳、コメント、および抽出されたコメントは蓄積されます(最初のPOファイルのものを使用するように指定した場合を除く)。POファイルのファイル位置の情報も蓄積されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.1 入力ファイルの位置

inputfile

入力ファイルです。

-f file
--files-from=file

入力ファイルの名前を、コマンドラインからではなく、fileから読み込みます。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileに‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.2 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.3 メッセージ選択

-< number
--less-than=number

numberに指定した数より少ないメッセージを出力します。指定しなかった場合のデフォルトは無限大です。

-> number
--more-than=number

numberに指定した数より大きいメッセージを出力します。指定しなかった場合のデフォルトは1です。

-u
--unique

--less-than=2’の省略指定です。一意なメッセージだけを出力します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.4 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.5 出力の詳細

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

-i
--indent

インデントされた形式で.poファイルを書き込みます。

--no-location

#: filename:line’という行を書き込みません。

-n
--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、陳腐化したメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

-F
--sort-by-file

ファイルの場所により出力をソートします。

--omit-header

Don’t write header with ‘msgid ""’ entry.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.6 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.7 msgcmpプログラムの呼び出し

msgcmp [option] def.po ref.pot

msgcmpプログラムは、Uniforum形式の2つの.poファイルを比較して、同じmsgid文字列を含んでいるかチェックするプログラムです。def.poファイルは、翻訳を含んだ既存のPOファイルです。ref.potは、最後に作成したPOファイル、またはPO Templateファイル(通常xgettextにより作成される)です。このプログラムは、プログラム内のメッセージが翻訳されているかチェックするときに便利です。完全に一致するエントリーが見つからない場合は、より良い診断メッセージを生成するためにfuzzyマッチングが行われます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.7.1 入力ファイルの位置

def.po

翻訳です。

ref.pot

ソースへの参照です。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.7.2 オペレーションの修飾

-m
--multi-domain

def.po 内の各ドメインにたいしてref.potを適用します。

-N
--no-fuzzy-matching

完全に一致するものが見つからない場合、fuzzyマッチングを行いません。これにより処理のスピードが大幅に改善されます。

--use-fuzzy

def.po内のfuzzyメッセージを、翻訳されたメッセージとみなします。fuzzyメッセージは翻訳者により検証されていないので、普通はこのオプションを使うのは正しくないことに注意してください。

--use-untranslated

def.po内の未翻訳のメッセージを、翻訳されたメッセージとみなします。普通はこのオプションを使うのは正しくないことに注意してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.7.3 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.7.4 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.8 msgattribプログラムの呼び出し

msgattrib [option] [inputfile]

msgattribプログラムは、翻訳カタログのメッセージの属性にしたがってフィルターを適用したり、属性を操作するためのプログラムです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.8.1 入力ファイルの位置

inputfile

入力となるPOファイルです。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileが指定されていないか、‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.8.2 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.8.3 メッセージ選択

--translated

翻訳されたメッセージを残して、未翻訳のメッセージは削除します。

--untranslated

未翻訳のメッセージを残して、翻訳済みのメッセージは削除します。

--no-fuzzy

削除: ‘fuzzy’ とマークされたメッセージを削除します。

--only-fuzzy

保持: ‘fuzzy’ とマークされたメッセージを残して、他のすべてのメッセージは削除します。

--no-obsolete

#~のついた廃止されたメッセージを削除します。

--only-obsolete

#~のついた廃止されたメッセージを残して、他のすべてのメッセージは削除します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.8.4 属性の操作

メッセージの選択・削除が実行された後に、属性は変更されます。‘--only-file’か‘--ignore-file’オプションを指定すると、only-fileに記載されたメッセージ、もしくはignore-fileに記載されていないメッセージにだけ、変更が適用されます。

--set-fuzzy

すべてのメッセージに、 ‘fuzzy’をセットします。

--clear-fuzzy

すべてのメッセージに、 非‘fuzzy’をセットします。

--set-obsolete

すべてのメッセージを、陳腐化したメッセージにします。

--clear-obsolete

陳腐化したメッセージを、陳腐化していないメッセージにセットします。

--previous

もし ‘fuzzy’ とマークされているとき、翻訳されたメッセージの“以前のmsgid”を残します。

--clear-previous

すべてのメッセージから、“以前のmsgid”であることを示すコメントマーク(‘#|’)がついたものを削除します。

--only-file=file

fileに記載されたエントリーの属性だけを変更します。fileにはPO、またはPOTファイルを指定します。

--ignore-file=file

fileに記載されていないエントリーの属性だけを変更します。fileにはPO、またはPOTファイルを指定します。

--fuzzy

--only-fuzzy --clear-fuzzy’の省略指定です。fuzzyメッセージだけを残すとともに、それらのメッセージの ‘fuzzy’ マークを外します。

--obsolete

--only-obsolete --clear-obsolete’の省略指定です。廃止されたメッセージだけを残すとともに、それらのメッセージが陳腐化していることを示すマークを外します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.8.5 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.8.6 出力の詳細

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

-i
--indent

インデントされた形式で.poファイルを書き込みます。

--no-location

#: filename:line’という行を書き込みません。

-n
--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、陳腐化したメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

-F
--sort-by-file

ファイルの場所により出力をソートします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.8.7 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.9 msgenプログラムの呼び出し

msgen [option] inputfile

msgenは、Englishの翻訳カタログを作成するプログラムです。最後に作成されたEnglishのPOファイル、またはPO Template(xgettext により生成されます)を入力とし、未翻訳エントリーの翻訳に、msgidと同じ文字列を割り当てます。

注意: ‘msginit --no-translator --locale=en’でも、同じような処理を行うことができます。異なるのは、msginitはヘッダーエントリーにたいして特別な配慮を払いますが、msgenは異なるという点です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.9.1 入力ファイルの位置

inputfile

入力となるPOまたはPOTファイルです。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileに‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.9.2 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.9.3 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.9.4 出力の詳細

--lang=catalogname

ヘッダーエントリーで使用される、‘Language’フィールドを指定します。このフィールドの意味については、ヘッダーエントリーを入力するを参照してください。注意: このオプションでは、‘Language-Team’と‘Plural-Forms’はセットされません。

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

-i
--indent

インデントされた形式で.poファイルを書き込みます。

--no-location

#: filename:line’という行を書き込みません。

--add-location

#: filename:line’という行を生成します(デフォルト)。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、陳腐化したメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。

-F
--sort-by-file

ファイルの場所により出力をソートします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.9.5 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.10 msgexecプログラムの呼び出し

msgexec [option] command [command-option]

msgexecは、翻訳カタログ内のすべての翻訳に、コマンドを適用するためのプログラムです。commandには、標準入力から翻訳を読み込む任意のプログラムを指定できます。呼び出しは、それぞれの翻訳について1回行われます。コマンドの出力は、msgexecの出力となります。msgexec自体の戻り値は、すべての呼び出しにおける最大の戻り値となります。

0’という、特別なビルトインコマンドを呼び出すと、NULL終端された翻訳が出力されます。‘msgexec 0’の出力は、‘xargs -0’の入力として適しています。

それぞれのcommand呼び出しにおいて、環境変数のMSGEXEC_MSGIDMSGEXEC_LOCATIONに、メッセージのmsgidとメッセージを含むPOファイルの場所がバインドされます。メッセージがコンテキストを保有する場合は、環境変数MSGEXEC_MSGCTXTがメッセージのコンテキストにバインドされます(コンテキストを保有していない場合にはバインドされません)。

注意: commandが翻訳カタログ内の翻訳のエンコーディングに対処できるようにするのは、あなたの責任です。commandが特定のエンコーディングを期待する場合、‘msgexec’を呼び出す前に、‘msgconv’プログラムで、翻訳カタログをそのエンコーディングに変換するのが最初のステップとなります。commandがlocaleのエンコーディングを期待しているが、あなたはlocaleのエンコーディングを無視したいときには、最初に‘msgconv’で翻訳カタログをUTF-8に変換してから、環境変数LC_ALLを指定して、‘msgexec’がUTF-8を処理するようにできます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.10.1 入力ファイルの位置

-i inputfile
--input=inputfile

入力となるPOファイルです。

-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし.poファイルが出力されるのは、カレントディレクトリーです。

inputfileが指定されていないか、‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.10.2 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.10.3 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.11 POファイルの一部をハイライトする

翻訳者は通常、POファイル中の未翻訳、およびfuzzyメッセージを見ることだけに関心を持っています。また、msgidが変更されたことによりメッセージにfuzzyがセットされたときに、以前のメッセージと現在のメッセージの差分を見たいと望みます(長いmsgidの中の数語が変更されたときは特に)。そして最後に、POファイル内のセクションのメッセージ(コメント、msgid、msgstrなど)の違いを強調するのは、いつでも歓迎します。

このような強調表示は、msgcatの‘--color’と‘--style’オプションで可能になります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.11.1 --colorオプション

--color=when’オプションは、どのような状況で着色された出力を生成するか指定します。whenには、以下のうち1つを指定できます:

always
yes

着色された出力が生成されます。

never
no

出力は着色されません。

auto
tty

出力デバイスがttyのとき(例 テキスト画面やterminal emulatorウィンドウに直接出力する場合)は、出力に着色します。

html

着色されたHTML出力が生成されます。

--color’と‘--color=yes’は同じです。デフォルトは‘--color=auto’です。

そのため、コマンドウィンドウで‘msgcat vi.po’のようなコマンドを実行すると、着色された出力が生成されます。‘msgcat vi.po | less -R’のように、パイプにたいして出力するときは、出力への着色は行われません。このような状況でも常に着色された出力を得るには、‘msgcat --color vi.po | less -R’のように指定します。

--color=html’オプションでは、ブラウザーで閲覧可能な出力が生成されます。このオプションは、例えばIndic言語を表示したいときに有用です。なぜなら、通常はIndic文字の表示にはterminal emulatorよりもブラウザーのほうが適しているからです。

--colorオプションにより生成される出力は、有効なPOファイルではないことに注意してください。出力にはterminal特有のエスケープシーケンスやHTMLタグが含まれます。このようなPOファイルをプログラムが読み込むと、文法エラーとなります。‘--color=html’オプションでHTMLファイルを生成する場合をのぞき、通常は--colorオプションで生成した結果をファイルに保存する必要はありません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.11.2 環境変数TERM

環境変数TERMには、テキストウィンドウの能力に関する識別情報が含まれています。これらの能力について詳細なリストを得るには、‘infocmp’コマンドを使用します(リファレンスは‘man 5 terminfo’コマンドで参照することができます)。

埋め込みの色指定をもつテキストを生成するとき、msgcatはTERM変数を参照します。現在のテキストウィンドウは、普通は少なくとも8色の表示をサポートします。しかしテキストウィンドウが16色、またはそれ以上の色数をサポートするのに、TERM変数には8色しかサポートしないように記述されている場合もあります。そのようなときは、TERMに異なる値を設定する価値があります。

xterm

多くのケースでは、xtermは16色をサポートするように構築されています。88色、または256色をサポートするように構築することもできます(両方はできませんが)。このような場合は、TERMxterm-16colorxterm-88color、またはxterm-256colorをセットすることを試みてもよいでしょう。

rxvt

rxvtが、16色をサポートするよう構築されている場合があります。このような場合は、TERMrxvt-16colorをセットすることができます。

konsole

konsoleも、16色をサポートするよう構築されている場合があります。このような場合には、TERMkonsole-16color、またはxterm-16colorをセットすることができます。

TERMを設定した後は、‘msgcat --color=test’により設定を検証するとともに、適切なカラーマップに見えるか出力を視認できます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.11.3 --styleオプション

--style=style_file’オプションで、着色時に使用するスタイルファイルを指定できます。この指定は--colorが有効なときだけ効果があります。

--styleオプションが指定されていないときは、環境変数PO_STYLEが使用されます。この環境変数にはユーザーが好むPOファイル用のスタイルファイルを指定します。

デフォルトのスタイルファイルは、$prefix/share/gettext/styles/po-default.cssです。$prefixはインストールした場所です。

いくつかのスタイルファイルが事前に定義されています:

po-vim.css

このスタイルはvim 7の表示を模倣します。

po-emacs-x.css

このスタイルは、X11ウィンドウでのGNU Emacs 21、22の表示を模倣します。

po-emacs-xterm.css
po-emacs-xterm16.css
po-emacs-xterm256.css

このスタイルは、‘xterm’(8色)、‘xterm-16color’(16色)、‘xterm-256color’(256色)の端末でGNU Emacs 22を実行したときの表示を模倣します。

これらのスタイルについてはディレクトリーを指定しなくても使うことができます。これらのスタイルファイルは$prefix/share/gettext/styles/にあります。$prefixはインストールした場所です。

あなた自身でスタイルをデザインできます。これは次のセクションで説明します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.11.4 POファイルのスタイルルール

端末出力とHTML出力で、同じPOファイル用スタイルを使用できます。POファイル用のスタイルはCSS(Cascading Style Sheet)の書式で記述します。CSSの正式な定義については、http://www.w3.org/TR/css2/cover.htmlを参照してください。CSSについての説明を含んだ、HTML記述のチュートリアルも数多く存在します。

HTML出力の場合、スタイルファイルはHTML出力中に埋め込まれます。テキスト出力の場合、スタイルファイルはmsgcatプログラムにより逐次解釈されます。これは@importに関連するファイル名が指定されていて、そのファイル名が以下のような場合、特に意味をもちます:

CSSルールはselectorとdeclarationにより構築されます。declarationにはグラフィカルなプロパティーを指定し、selectorにはそれをいつ適用するかを指定します。

POファイル用に、以下の簡単なselectorがサポートされています("CSS classes"を基本とします。詳細はCSS2 specのsection 5.8.3を参照してください)。

これらのselectorは、以下の例のように階層的なselectorとして組み合わせることができます。

.msgstr .invalid-format-directive { color: red; }

上記の例では、翻訳文字列中の無効な書式指定を強調表示しています。

テキストモードでは、pseudo-classes(CSS2 spec, section 5.11)とpseudo-elements(CSS2 spec, section 5.12)はサポートされません。

HTMLモードでの宣言には制限はありません。ブラウザーがサポートする任意のgraphical attributeがサポートされます。

テキストモードでの宣言は以下のプロパティーに制限され、他のプロパティーは暗黙に無視されます。

color (CSS2 spec, section 14.1)
background-color (CSS2 spec, section 14.2.1)

これらのプロパティーはサポートされます。色数はterminalの能力に適合されます。ほとんどのterminalのサポートは8色であることに注意してください。

font-weight (CSS2 spec, section 15.2.3)

このプロパティーはサポートされますが、ほとんどのterminalはnormalboldの2種類のweightしか描画できません。600以上の値を指定したときはboldとして描画されます。

font-style (CSS2 spec, section 15.2.3)

このプロパティーはサポートされます。italicobliqueは、同じ方法で描画されます。

text-decoration (CSS2 spec, section 16.3.1)

このプロパティーはサポートされます。値はnoneunderlineに制限されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.11.5 POファイルを閲覧するためにlessをカスタマイズする

less’は、テキストスクリーンやterminal emulatorでテキストファイルを閲覧するための一般的なプログラムです。このプログラムは、色表示や文字飾りのための埋め込みエスケープシーケンスもサポートします。

以下のようにして、POファイルの閲覧にlessを使用できます(UTF-8 環境の場合):

msgcat --to-code=UTF-8 --color xyz.po | less -R

これと同じことを、次ような簡単なコマンドで行うための方法を説明します:

less xyz.po

以下の3つの準備が必要です:

  1. 環境変数LESSに‘-R’と‘-f’のオプションを追加します:
    $ LESS="$LESS -R -f"
    $ export LESS
    
  2. あなたのシステムにlessopen.shlessclose.shスクリプトがない場合は、マニュアル(‘man less’)に記載されているように、それらのスクリプトを作成して、環境変数LESSOPENLESSCLOSEにセットします。
  3. 以下のような、ファイルの拡張子からPOファイルを認識することによりmsgcatを呼び出し、一時ファイルを生成する断片的なスクリプトをlessopen.shに追加します:
    case "$1" in
      *.po)
        tmpfile=`mktemp "${TMPDIR-/tmp}/less.XXXXXX"`
        msgcat --to-code=UTF-8 --color "$1" > "$tmpfile"
        echo "$tmpfile"
        exit 0
        ;;
    esac
    

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.12 POファイルを処理するプログラムを独自に記述する

msgattrib’や‘msgcat’などの組み合わせによる処理では十分でない場合のために、一連のC関数がライブラリにより提供されています。これを使うことにより、あなたのプログラムからPOファイルを処理できるようになります。ライブラリーを使う場合は、POファイルをパースするルーチンを自分で記述する必要はありません。かわりにPOファイル内の各メッセージに対応するメモリーへのポインターを取得することができます。現時点では、POファイルへ書き込むための関数は提供されていません。

関数はヘッダーファイル‘<gettext-po.h>’で宣言されており、‘libgettextpo’というライブラリーで定義されています。

Data Type: po_file_t

POファイルのコンテンツをメモリーに読み込んだ後に、それらを参照するためのポインター型です。

Data Type: po_message_iterator_t

一連のメッセージを生成するiteratorを参照するためのポインター型です。

Data Type: po_message_t

POファイルのメッセージ(翻訳を含む)を参照するためのポインター型です。

Function: po_file_t po_file_read (const char *filename)

関数po_file_readは、引数としてファイル名を受け取り、そのPOファイルをメモリー内に読み込みます。戻り値はPOファイル内のコンテンツへのハンドルで、そのハンドルはpo_file_freeが呼び出されるまで有効です。エラーが発生したときの戻り値はNULLで、errnoがセットされます。

Function: void po_file_free (po_file_t file)

関数po_file_freeは、メモリー内のPOファイルのコンテンツを解放します。iteratorを通じて暗黙にアクセス可能なすべてのメッセージも解放されます。

Function: const char * const * po_file_domains (po_file_t file)

関数po_file_domainsは、メッセージを所有するPOファイルのdomainを戻します。戻り値はNULLで終端された配列で、この配列はfileのハンドルが有効な間は有効です。‘domain’指定を持たないPOファイルの場合は、デフォルトのドメインである"messages"という名前のドメインだけが戻されます。

Function: po_message_iterator_t po_message_iterator (po_file_t file, const char *domain)

po_message_iteratorは、与えられたdomainに属するfileのメッセージを生成するiteratorを戻します。domainNULLのときは、かわりにデフォルトのdomainが使用されます。関数po_next_messageを繰り返し呼び出すと、メッセージをリストすることができます。

Function: void po_message_iterator_free (po_message_iterator_t iterator)

関数po_message_iterator_freeは、関数po_message_iteratorにより割り当てられたiteratorを開放します。

Function: po_message_t po_next_message (po_message_iterator_t iterator)

関数po_next_messageは、iteratorから次のメッセージを戻すとともにiteratorを1つ進めます。メッセージリストの終端に達すると、NULLが戻されます。

以下はpo_message_tのメンバーを戻す関数です。fileハンドルが有効な間は、呼び出しによる結果も有効です。

Function: const char * po_message_msgid (po_message_t message)

関数po_message_msgidは、メッセージのmsgid(未翻訳のEnglish文字列)を戻します。この結果は、非NULLであることが保証されています。

Function: const char * po_message_msgid_plural (po_message_t message)

関数po_message_msgid_pluralは、pluralをもつメッセージのmsgid_plural(未翻訳のEnglish plural文字列)を戻します。メッセージがpluralをもたない場合には、NULLが戻されます。

Function: const char * po_message_msgstr (po_message_t message)

関数po_message_msgstrは、メッセージのmsgstr(翻訳済み)を戻します。未翻訳のメッセージの場合は、空文字列が戻されます。

Function: const char * po_message_msgstr_plural (po_message_t message, int index)

関数po_message_msgstr_pluralは、pluralをもつメッセージのmsgstr[index]を戻します。indexが範囲外のとき、またはメッセージがpluralをもたない場合はNULLが戻されます。

以下は、これらの関数がどのように使用されるかを示す例です。

const char *filename = …;
po_file_t file = po_file_read (filename);

if (file == NULL)
  error (EXIT_FAILURE, errno, "couldn't open the PO file %s", filename);
{
  const char * const *domains = po_file_domains (file);
  const char * const *domainp;

  for (domainp = domains; *domainp; domainp++)
    {
      const char *domain = *domainp;
      po_message_iterator_t iterator = po_message_iterator (file, domain);

      for (;;)
        {
          po_message_t *message = po_next_message (iterator);

          if (message == NULL)
            break;
          {
            const char *msgid = po_message_msgid (message);
            const char *msgstr = po_message_msgstr (message);

            …
          }
        }
      po_message_iterator_free (iterator);
    }
}
po_file_free (file);

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10 バイナリーのMOファイルの生成


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1 msgfmtプログラムの呼び出し

msgfmt [option] filename.po …

msgfmtは、翻訳済みのテキストのメッセージから、バイナリーのメッセージカタログを生成するプログラムです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.1 入力ファイルの位置

filename.po …
-D directory
--directory=directory

ディレクトリーのリストにdirectoryを追加します。このディレクトリーのリストよりソースファイルを検索します。しかし、結果となるバイナリーファイルが出力されるのは、カレントディレクトリーです。

入力ファイルに‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.2 オペレーションモード

-j
--java

Javaモード: JavaのResourceBundleクラスを生成します。

--java2

–javaと同様ですがJava2(JDK 1.2以上)とみなします。

--csharp

C#モード: GettextResourceSetのサブクラスを含んだ、.NETの.dllファイルを生成します。

--csharp-resources

C# resourcesモード: .NETの.resourcesファイルを生成します。

--tcl

Tclモード: tcl/msgcatの.msgファイルを生成します。

--qt

Qtモード: Qtの.qmファイルを生成します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.3 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

--strict

プログラムがUniforum/Sun実装にしたがうように指定します。これは現時点では、出力ファイルの名前に影響を与えるだけです。オプションにファイル名を指定しなかった場合、出力ファイルは同じdomain 名になります。厳密なUniforumモードが有効でファイル名が与えられなかった場合には、ファイル名に.moが付加されます。

わたしたちはこのSun実装は意味がないと考え、デフォルトではこのモードは選択されません

出力となるfileに‘-’が指定されたときは、出力は標準出力に書き込まれます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.4 Javaモードでの出力ファイルの位置

-r resource
--resource=resource

リソース名を指定します。

-l locale
--locale=locale

locale名を指定します。ll形式による言語指定と、国と言語指定を組み合わせたll_CCのどちらでも指定できます。

-d directory

classのディレクトリー階層のベースとなるディレクトリーを指定します。

クラス名はリソース名の後ろに区切り文字のアンダースコアーとlocale名を付加して決定されます。‘-d’オプションは必須です。クラスは指定されたディレクトリーに出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.5 C#モードでの出力ファイルの位置

-r resource
--resource=resource

リソース名を指定します。

-l locale
--locale=locale

locale名を指定します。ll形式による言語指定と、国と言語指定を組み合わせたll_CCのどちらでも指定できます。

-d directory

localeに依存する.dllファイルを出力するベースディレクトリーを指定します。

\‘-l’と‘-d’が必須オプションです。.dllファイルは、localeに依存した名前の指定ディレクトリーのサブディレクトリーに出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.6 Tclモードでの出力ファイルの位置

-l locale
--locale=locale

locale名を指定します。ll形式による言語指定と、国と言語指定を組み合わせたll_CCのどちらでも指定できます。

-d directory

メッセージカタログ.msgのベースディレクトリーを指定します。

-l’と‘-d’は必須オプションです。.msgは指定されたディレクトリーに出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.7 入力ファイルの構文

-P
--properties-input

入力ファイルがPOファイルの構文ではなく、Javaの.propertiesの構文にのっとったJava ResourceBundleファイルだとみなします。

--stringtable-input

入力ファイルがPOファイルの構文ではなく、NeXTstep/GNUstepのlocalized resourceの.stringsの構文にのっとったファイルだとみなします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.8 入力ファイルの解釈

-c
--check

--check-format--check-header--check-domainがすべて指定されたとみなしてチェックを行います。

--check-format

languageに依存した書式文字列をチェックします。

文字列がprintfのような関数で使用される書式文字列の場合、書式指定子‘%’と、それらに対応する型の変数の個数は一致するはずです。エントリーにたいして#,コメントでc-formatpossible-c-formatフラグが指定されている場合は、チェックが行われます。たとえば、‘%s’が期待される箇所に‘%.*s’や‘%d’が使われていたり、‘%x’が期待される箇所に‘%d’が使われている場合、チェックは診断メッセージを出力します。このチェックは位置パラメーターを処理することさえできるのです。

xgettextプログラムは通常、ある文字列が書式文字列かどうかを、自動的に判定します。しかしこのアルゴリズムも完全ではありません。そのため、printfのような関数で使用されていない文字列を書式文字列とみなしてしまい、エラーが存在しないにもかかわらずmsgfmtがエラーを報告する場合があります。

プログラマーがxgettextに判定結果を指示することにより、この問題を解決することができます(Cフォーマット文字列を参照してください)。翻訳者は#,行からフラグを削除しようと考える必要はありません。なぜならこの"fix"は、次にmsgmergeを呼び出したときに元に戻されてしまうからです。

--check-header

ヘッダーエントリーの存在および内容をチェックします。ヘッダーエントリーのさまざまなフィールドの説明は、ヘッダーエントリーを入力するを参照してください。

--check-domain

domain指定と--output-fileオプションの競合をチェックします。

-C
--check-compatibility

GNU msgfmtがX/Open msgfmtのように振る舞うかをチェックします。GNU拡張を使用しているとエラーになります。

--check-accelerators[=char]

メニューアイテムにたいしてキーボードアクセラレーターの存在をチェックします。このチェックは、いくつかのGUIにおいてメニューアイテム文字列内のキーボードアクセラレーターが、‘&’のすぐ後ろに続く文字としてデザインされていることにもとづきます。キーボードアクセラレーターが"keyboard mnemonic"と呼ばれることもあります。このチェックは、未翻訳文字列に‘&’が1つあるとき、翻訳文字列にも1つの‘&’があるかをチェックします。このオプションの引数にcharが与えらる場合、charには非英数文字を指定します。指定した文字は‘&’のかわりに、キーボードアクセラレーターのマークとして使用されます。

-f
--use-fuzzy

出力にfuzzyエントリーを使用します。これらのfuzzyメッセージは人間の翻訳者により検証されたものではないため、このオプションの使用は通常は正しくないことに注意してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.9 出力の詳細

-a number
--alignment=number

文字列をnumberバイトに揃えます(デフォルトは1)。

--endianness=byteorder

32ビットの数字を与えられたバイト順で書き出します。biglittleを指定できます。デフォルトはプラットフォーム、正確に言うとCPUのインディアンに依存します。

任意のインディアンをもつMOファイルは、任意のプラットフォームで使用できます。MOファイルのインディアンがプラットフォームのものでない場合、32ビットの数値は実行時に交換されます。パフォーマンスに与える影響は無視できるものです。

このオプションは、プラットフォームに束縛されずMOを作成するために便利です。

--no-hash

バイナリーファイルにハッシュテーブルを含めないようにします。(ハッシュテーブルを参照するかわりに、バイナリーサーチが行われるため)実行時の検索が、より高価な処理となります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.10 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。

--statistics

翻訳の統計情報を表示します。--statisticsとともに--verboseオプションが指定された場合は、統計行の前に入力ファイルの名前が出力されます。

-v
--verbose

診断レベルを上げます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2 msgunfmtプログラムの呼び出し

msgunfmt [option] [file]...

msgunfmtは、バイナリーのメッセージカタログを、Uniforum形式の.poファイルに変換するプログラムです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.1 オペレーションモード

-j
--java

Javaモード: JavaのResourceBundle class が入力となります。

--csharp

C#モード: GettextResourceSetのサブクラスを含む.NETの.dllファイルが入力となります。

--csharp-resources

C# resourcesモード: .NETの.resourcesファイルが入力となります。

--tcl

Tclモード: tcl/msgcatの.msgファイルが入力となります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.2 入力ファイルの位置

file

入力となる.moファイルです。

fileが指定されていないか、‘-’が指定された場合は、標準入力から読み込みます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.3 Javaモードでの入力ファイルの位置

-r resource
--resource=resource

リソース名を指定します。

-l locale
--locale=locale

locale名を指定します。ll形式による言語指定と、国と言語指定を組み合わせたll_CCのどちらでも指定できます。

class名は、resource名の後ろにアンダースコアーをつけて、その後ろにlocale 名を付加することにより決定されます。classは、CLASSPATHによって配置されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.4 C#モードでの入力ファイルの位置

-r resource
--resource=resource

リソース名を指定します。

-l locale
--locale=locale

locale名を指定します。ll形式による言語指定と、国と言語指定を組み合わせたll_CCのどちらでも指定できます。

-d directory

localeに依存する.dllファイルを出力するベースディレクトリーを指定します。

-l’と‘-d’が必須オプションです。.msgファイルは、locale に依存した名前の指定ディレクトリーのサブディレクトリーに配置されています。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.5 Tclモードでの入力ファイルの位置

-l locale
--locale=locale

locale名を指定します。ll形式による言語指定と、国と言語指定を組み合わせたll_CCのどちらでも指定できます。

-d directory

メッセージカタログ.msgのベースディレクトリーを指定します。

-l’と‘-d’は必須オプションです。.msgは指定されたディレクトリーに配置されています。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.6 出力ファイルの位置

-o file
--output-file=file

指定されたファイルに出力を書き込みます。

出力ファイルが指定されていない、または‘-’が指定された場合、結果は標準出力に出力されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.7 出力の詳細

--color
--color=when

色や色以外のテキスト属性を使うか、いつ使うかを指定します。詳細は--colorオプションを参照してください。

--style=style_file

--colorにたいしてCSS style ruleファイルを使うかを指定します。詳細は--styleオプションを参照してください。

--force-po

メッセージが何も含まれていない場合でも、常に出力ファイルに書き込みます。

-i
--indent

インデントされた形式で.poファイルを書き込みます。

--strict

Uniforumに厳密に準拠したPOファイルを出力します。このUniforum形式はGNUの拡張をサポートしないため避けたほうがよいでしょう。

-p
--properties-output

Javaの.propertiesの書式で、Java ResourceBundleを出力します。このファイル形式はplural formをサポートせず、陳腐化したメッセージを暗黙で除去することに注意してください。

--stringtable-output

.stringsの書式で、NeXTstep/GNUstepのローカライズされたリソースファイルを出力します。このファイル形式はplural formをサポートしないことに注意してください。

-w number
--width=number

出力ページの幅をセットします。これにより出力ファイル中の長い文字列が指定した幅(例:スクリーンの列数)に収まるように、各行の長さがnumber以下のような複数の行に分割されます。

--no-wrap

長いメッセージ行を分割しません。出力ページの幅を超えるようなメッセージ行も、複数行に分割されません。出力ページの幅を超えるファイル参照行だけが分割されます。

-s
--sort-output

ソートされた出力を生成します。このオプションを使用することにより翻訳者が、メッセージがどのようなコンテキストで使用されるかを理解するのが、困難になることに注意してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.8 情報的な出力

-h
--help

このヘルプを表示して終了します。

-V
--version

バージョン情報を表示して終了します。

-v
--verbose

診断レベルを上げます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.3 GNU MOファイルのフォーマット

生成されたMOファイルの書式については、以下のような図を用いて説明するのがよいでしょう。

最初の2wordには、ファイルの識別が含まれます。magic numberは常にGNU MOファイルを意味するnumberになります。numberは生成されたマシンのバイトオーダーにしたがって格納されます。つまり実際のmagic numberは、0x950412de0xde120495のいずれかです。

2番目のwordは、ファイル書式の現在のrevisionを説明し、major revision number、およびminor revision numberから成り立ちます。revision numberにより、MOファイルの読み手は、古い書式と新しい書式を識別して、(可能なかぎり)内容を処理できます。いまのところmajor revisionは0か1で、minor revisionも0と1ですが、将来は追加されるかもしれません。想定外のmajor revision numberの場合、プログラムはMOファイル全体を読み込むのを中止する必要があります。想定外のminor revision numberは、ファイルは読み込めても、すべての内容は読み込めないことを意味します。プログラムが解析できるのは、より小さなminor revision numberのときだけです。

異なるmagic numberによって書式の違いを表すのではなく、magic numberとは別にversionが保持されます。これは/etc/magicが滅多に更新されないことが主な理由です。

MOファイルの冒頭部の情報が拡張されたときに、それらを読み込むプログラムをリコンパイルしなくても良いように、以降のテーブルのポインターを使ってください。そのようにしておけば、後で新しいフラグのビットを追加したり、使用されている文字コードの表示や、新しいテーブルなどを挿入されたときに便利です。

図中のoffset Oとoffset Tには、2つのstring descriptorを見出すことができます。この2つのテーブルでは、どちらもstring descriptorとして 32ビットの整数が使用されており、1つは文字列の長さを示し、もう1つは文字列がMOファイルの先頭から何バイト目かというoffsetを示します。最初のテーブルには元の文字列のdescriptorが含まれていて、これらの元文字列は辞書順にソートされて格納されています。2番目のテーブルには翻訳された文字列のdescriptorが含まれており、これらは1番目のテーブルに対応しています。つまり1番目のテーブルと同じ添字で2番目のテーブルにアクセスすれば、対応する翻訳を取得できます。

元の文字列をソートして格納することにより、MOファイルにハッシュテーブルを含まれていなかったり、含まれていたとしても実際に使うことができないときにも、単純な二分探索が可能になります。これには他にも利点があります。GNU gettextは、POファイルの空の文字列にたいする翻訳文字列として、MOファイルに付加するシステム情報を割り当てます。この空文字列と翻訳のペアが、元の文字列のテーブルと、翻訳文字列のテーブルの最初に配置されることにより、システム情報を簡単に見つけることができるのです。

ハッシュテーブルのサイズSが0のときもあります。これは、ハッシュテーブル自体がMOファイルに含まれていない場合です。事前に算出されたハッシュテーブルはディスク容量を消費し、速度も早くないという理由で、この方式を好む人もいます。ハッシュテーブルは、MOファイル中の文字列のソートされた配列の添字を含んでいます。競合はdouble hashingにより解決しています。使用されている正確なhashing algorithmは、GNU gettextのコード実装の説明になってしまうので、ここでは説明しません。

ハッシュテーブルを参照して取得する文字列自体はNUL終端されており、string descriptorの文字列長にそのNULの分は含まれません。msgfmtプログラムには、MOファイル中の文字列のインデントを選択するオプションがあります。このオプションを指定すると、個々の文字列の開始位置のオフセットは指定されたインデント値の倍数分ずれます。RISCマシンには、適したインデント指定によって速度が改善するものがあります。

contextについては、元の文字列の代わりに、context文字列と元の文字列をEOTで連結したものが、ソートされて格納されます。

plural formについては、元の文字列のsingularとpluralがNULで区切られて格納されます。string descriptorには、両方の長さが記述されます。しかし、ハッシュテーブルを参照するときは、元の文字列のsingularだけが使用されます。さまざまなpluralにたいする翻訳は、すべてNUL区切りで格納されます。この場合もstring descriptorには、それらすべての長さが格納されます。

MOファイル内の文字列にNULが埋め込まれることを防ぐ方法はありません。しかし現在のプログラムのインターフェースは、文字列がNULで終端されると仮定しているため、文字列の途中にNULが埋め込まれている場合、何らかの不都合が起こり得ます。MOファイルの書式は、後から他のインターフェースを適用できるほどには一般的です。一例としては、意図しないNULが出現するような箇所にwide characterを使用する方法などがあります(実際にはMOファイル中にwide characterを保持することはしません。wide characterを使用するとファイルの容量が不必要に大きくなります。また‘wchar_t’はプラットフォームに依存するため、MOファイルもプラットフォームに依存することになるからです)。

この技術的な問題は、GNU gettextのdevelopment forumで盛んに議論されており、MOファイルの書式が将来、進化・変更されることが予想されます。その可能性としては、同時に複数の書式にたいするサポートさえもが含まれます。しかし、わたしたちに何らかの出発点が必要なことは確かで、ここで説明しているMOファイルの書式はよい出発点でした。今の書式には厳密な制約もなく、後から書式を拡張するのは簡単なので、わたしたちは現在のアプローチに満足しています。

        byte
             +------------------------------------------+
          0  | magic number = 0x950412de                |
             |                                          |
          4  | file format revision = 0                 |
             |                                          |
          8  | number of strings                        |  == N
             |                                          |
         12  | offset of table with original strings    |  == O
             |                                          |
         16  | offset of table with translation strings |  == T
             |                                          |
         20  | size of hashing table                    |  == S
             |                                          |
         24  | offset of hashing table                  |  == H
             |                                          |
             .                                          .
             .    (possibly more entries later)         .
             .                                          .
             |                                          |
          O  | length & offset 0th string  ----------------.
      O + 8  | length & offset 1st string  ------------------.
              ...                                    ...   | |
O + ((N-1)*8)| length & offset (N-1)th string           |  | |
             |                                          |  | |
          T  | length & offset 0th translation  ---------------.
      T + 8  | length & offset 1st translation  -----------------.
              ...                                    ...   | | | |
T + ((N-1)*8)| length & offset (N-1)th translation      |  | | | |
             |                                          |  | | | |
          H  | start hash table                         |  | | | |
              ...                                    ...   | | | |
  H + S * 4  | end hash table                           |  | | | |
             |                                          |  | | | |
             | NUL terminated 0th string  <----------------' | | |
             |                                          |    | | |
             | NUL terminated 1st string  <------------------' | |
             |                                          |      | |
              ...                                    ...       | |
             |                                          |      | |
             | NUL terminated 0th translation  <---------------' |
             |                                          |        |
             | NUL terminated 1st translation  <-----------------'
             |                                          |
              ...                                    ...
             |                                          |
             +------------------------------------------+

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11 プログラマーの視点

GNU gettextにより提供される現在のメッセージカタログの実装は、インストーラーにより選択された場合にはシステムによるメッセージカタログ処理を使用することを目標にしています。そのため、まず最初に既知の解決策を概観しておく必要があるかもしれません。POSIXコミティーの人たちは、以下で説明する準公式な標準候補のうちから1つを採択して管理しませんでした。実際、彼らは何も採択せず、インターフェースの例を含めるだけに決めました。Unixのメジャーなベンダーによるのインターフェースの採用は、X/Openのcatgetsと、Uniforumのgettextに二分されました。以下ではそれらのインターフェースについて説明するとともに、このジレンマにたいするわたしたちの解決策を説明します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1 catgetsについて

catgetsの実装は、X/Open Portability Guide, Volume 3, XSI Supplementary Definitions, Chapter 5に定義されています。しかし、この標準を作成する過程は、いくつかのUnixベンダーからは遅すぎると見なされ、それゆえ彼らは標準を先取りしたバージョンを実装しました。プラットフォームに依存したプログラムを記述したことから、これは問題を引き起こしました(catgetsが一意なインターフェースを保証しないことさえありました)。

インターフェースの決定にコメントするのがコミティー仲間だけに制限されていて、彼らだけがインターフェースを作成できました。彼らは、このインターフェースを本当にプログラムに使わせようと考えてはいませんでした。メモリー保存の実装手法により処理は高速だったので、ユーザーはハッピーでしたが、プログラマーはそれを嫌っていました(少なくともわたしと、他の何人かも…)。

Unix(tm)への正しい移植にともなうすべてのトラブルの原因は、結局のところ彼らがこの仕様を発行した人たちと同じ、X/Openの人たちだったことです。これはわたしに、すべてのUnix(という名前を名乗ることを許された)実装にたいして、このインターフェースがUnix標準となる未来を予想させるのです(例: Spec1170)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1.1 インターフェース

catgetsの実装にたいするインターフェースには、ファイルのアクセスのための3つの関数: ファイルを開くcatopen、メッセージテーブルにアクセスするcatgets、そして処理が終わった後にファイルを閉じるためのcatcloseが含まれます。関数のプロトタイプと、必要となる定義は、<nl_types.h>というヘッダーファイルにあります。

catopenは、以下のように呼び出されます:

nl_catd catd = catopen ("catalog_name", 0);

関数の引数としてカタログ名を指定します。これは通常、プログラムかパッケージを参照する名前を指定します。2番目のパラメーターは、標準仕様では規定されていません。わたしには、それがさまざまなシステムで一貫した形で実装されているかすら、わからりません。あたりさわりのないアドバイスとしては、値として0を指定するのがよいでしょう。戻り値はメッセージカタログのハンドルで、このハンドルはopenで戻されるファイルのハンドルと同じです。

このハンドルは、以下のようにしてcatgets関数で使うことができます:

char *translation = catgets (catd, set_no, msg_id, "original string");

最初のパラメーターはcatalog descriptorです。2番目のパラメーターにはmsg_idに保持されるメッセージの、セット番号を指定します。つまりcatgetsは、以下のような3段階のアドレッシングを行います:

catalog name ⇒ set number ⇒ message ID ⇒ translation

4番目の引数は、翻訳された文字列のアドレスを指すためには使用しません。これはアドレッシングステージが失敗したとき、デフォルト値を与えるためのものです。ここで重要なのは、catgetsの戻り値の型がchar *だとしても、結果の文字列を変更してはならないということです。本来、この戻り値の型はconst char *のほうがよいのですが、この標準はANSI C標準が発行される1年前の、1988年に発行されたものなのです。

最後の関数は期待されたとおりに使用され、そのとおりに振る舞います:

catclose (catd);

この関数を呼び出すと、そのdescriptorをcatgetsの呼び出しには使用できません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1.2 catgetsインターフェースに関する問題点?!

これを説明するのはとても簡単に見えます — わたしたちが話してきたインターフェースのどこに問題があったのでしょうか? 実際のところ、分別のある使い方をするかぎり、そのインターフェースを使うことはできます。しかしメッセージカタログを構築するのは苦痛をともないます。その理由はcatgetsの3番目の引数となる、一意なmessage IDです。これには、すべてのメッセージのペアごとに、数字を割り当てなければなりません。ソースコードの変更、たとえばメッセージを追加したり削除するときに、このリストを保守する際に発生する問題を想像してみてください。もちろん、この混沌を組織化するためのツールもたくさん開発されました。しかし、あるツールで処理できるのに、他のツールでは読み込めないといった様相でした。より簡単に管理できて問題もない、他のやり方はあるのですが、述べないでおきましょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2 gettextについて

gettextのインターフェースの定義は、Uniforumの提案によるものです。これはSunから提出されたもので、Sunは1990頃に、SunOS4でgettextを実装済みでした。現在では、gettextのインターフェースは、OpenI18N標準により規定されています。

この解決策の主要な点は、通常のファイル処理の手順(open-use-close)を踏襲しないことと、プログラマーに負担(特に一意なキーの取扱いにたいして)をかけないことにあります。もちろん一意なキーは必要なので、(メッセージの長短に関わらず)メッセージ自身をキーとします。比較に関する2つの方法の詳細については、2つのインターフェースの比較を参照してください。

以下のセクションでは、より詳細にインターフェースを説明します。インターフェースについて詳細を掘り下げて説明するのは、それが GNU gettextライブラリーに密接に関係しているからです。ライブラリーの使い方に興味をもつプログラマーは、この説明にも興味をもつことでしょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.1 インターフェース

インターフェースは最小限、a)文字列が由来するドメインの選択(すべてのプログラムが1つのドメインを使用するのは、構築と保守が難しいので、たとえ可能であったとしても合理的ではありません)、b)選択されたドメインの文字列へのアクセス、の機能をもたなければなりません。

これは主にgettextのインターフェースについての説明です。このインターフェースは、使用するドメインを与えなかった場合に、無条件に参照されるグローバルドメインをもっています。もちろん、このドメインはユーザーが選択することができます。

char *textdomain (const char *domain_name);

これにより、LC_MESSAGEカテゴリーにおける現在のグローバルドメインの状態を問い合わせたり変更することができます。引数はヌル終端された文字列で、ファイル名として使用できる文字でなければなりません。引数domain_nameNULLの場合、この関数は現在の値を戻します。値がセットされていなければ、デフォルトのドメイン名messagesが戻されます。textdomainの戻り値型はchar *となっていますが、それを変更することはできないことに注意してください。それと、ドメイン名が利用可能かのチェックは行われないことを知ることも重要です。ドメイン名が利用可能でない場合、それは翻訳が提供されていないという事実をあらわします。

textdomainでセットしたドメインは、以下の関数で使用されます

char *gettext (const char *msgid);

この関数は想像されるとおりの簡単な方法で使用されます。これにより、現在のドメインが利用可能な場合には、msgidにたいする翻訳文字列が戻されます。ドメインが利用可能でない場合には、引数自身が戻されます。引数にNULLが指定された場合の戻り値は未定義です。

1つ念頭においてもらいたいのは、使用するドメインを明示的に与えられなかった場合のことです。この場合には現在のドメインが使用されます。プログラム中で同じgettextを呼び出したとしても、実行の間にドメインが変更された場合には、異なるメッセージカタログが参照されることになります。

もっとも簡単なのは、国際化されたパッケージで普通に使うケースで、この場合は実行開始時に呼び出されるtextdomainにより、一意なドメイン名(通常はパッケージ名)がセットされます。以降のコードでは、翻訳が必要な文字列はすべてgettext関数により処理されます。これだけでパッケージがあなたの言語で話し出すのです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.2 あいまいざの解決

ほとんどのアプリケーションでは、単一のドメイン名でうまく動作するかもしれませんが、複数のドメインから翻訳を取得する必要があるアプリケーションも存在します。textdomainを呼び出すことにより異なるドメインに切り替えることもできますが、これは不便だし低速です。起こり得る状況としては、この文書を記述しているときに提出された議論(一般的に使われる関数のすべてのエラーメッセージは、errorというドメインに分離するべきである)のケースがあります。これには翻訳が1度で済むという意味があります。他のケースとしてはライブラリーのメッセージの場合で、これらがアプリケーションの現在のドメインからは独立している必要があります。

これらの理由により、文字列を取得するために、さらに2つの関数が用意されています:

char *dgettext (const char *domain_name, const char *msgid);
char *dcgettext (const char *domain_name, const char *msgid,
                 int category);

これらの関数は、どちらも1番目に追加の引数があります。これにはtextdomainと同じ引数を与えます。dcgettextの3番目の引数により、LC_MESSAGES以外の、他のlocale categoryを使うことができます(実際のところ、わたしにはこれがどんなときに便利なのか、わかりませんが)。domain_nameNULLのとき、またはcategoryに未知のものが指定された場合、結果は未定義となります。Solarisの関数ファミリーの2番目の実装にはでは、1つは含まれているのに、この関数は含まれていないことも触れておくべきでしょう

多重定義が発生する2番目の理由は、複数のドメインが同じ名前を共有するかもしれないという事実に起因します。これは必要なメッセージカタログがどこにあるか指定することで解決します。

char *bindtextdomain (const char *domain_name,
                      const char *dir_name);

この関数を呼び出すことにより、指定されたドメインとディレクトリーのファイルがバインドされます(ファイルがどのように決定されるかは以下で説明します)。特に、システムの既定の位置にあるファイルのかわりに、指定された位置のファイルを使ってtextdomainを呼び出したいときに使用します。dir_nameパラメーターにNULLポインターを与えると、domain_nameにバインドされている値が戻されます。domain_name自身がNULLの場合は何も行われず、NULLポインターが戻されます。他の関数と同様に、戻された値を変更することはできません!

dir_nameに相対パスを指定することは、トラブルの原因になることを覚えておくことは重要です。プログラムがchdirコマンドを呼び出すことにより、カレントディレクトリーに関連づいた相対パスは、再計算されます。相対パスの使用により、常に非依存性と信頼性が無効にされます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.3 メッセージカタログファイルの配置

さまざまなパッケージごとに、多くの異なる言語を保存する必要があるという理由により、わたしたちにはこれらの情報をメッセージカタログファイルに記録するための、何らかの方法が必要です。Unix環境でよく使われるのは、ファイル名にエンコード名をもたせる方法で、ここでも同じ方法を用います。ディレクトリーは、bindtextdomainの2番目の引数に指定するディレクトリー(または既定のディレクトリー)の後ろに、locale名とlocale category、それとdomain名を連結したものになります:

dir_name/locale/LC_category/domain_name.mo

dir_nameの既定値はシステムにより定義されます。この習慣を順守するGNUのライブラリーやパッケージのために、以下のように定義されています:

/usr/local/share/locale

localeは、LC_categoryで指定されたlocale categoryの名前です。gettextdgettextの場合、LC_categoryは常にLC_MESSAGESになります3。locale category の名前は、setlocale (LC_category, NULL)を通じて決定されます4dcgettext関数では、3番目の引数にlocale categoryを指定できます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.4 gettextが使用する出力文字セットの指定方法

gettextは、メッセージカタログ内の翻訳を取得するだけでなく、オンザフライで翻訳出力の文字セットを変換することもできます。これは、翻訳者がメッセージカタログを作ったときとは異なる文字セットを使っているユーザーにとって便利です。これにより、文字セットだけが異なるメッセージカタログをいくつも作らなくてよくなるからです。

出力される文字セットのデフォルトはnl_langinfo (CODESET)です。これは現在のlocaleのLC_CTYPEの部分に依存します。文字列をlocaleとは関係のない文字セット(例: UTF-8)で保存するプログラムは、gettextや、それに関連するプログラムにたいして、そのエンコードで翻訳を戻すように要求することができます。これは、bind_textdomain_codeset関数により行います。

gettextの引数であるmsgidは、文字セットの変換の対象外であることに注意してください。gettextが、msgidに対応する翻訳を見つけられなかったときは、現在の出力の文字セットとは関係なく、元のmsgidが変更されずに出力されます。すべてのmsgidに US-ASCII 文字列が推奨されているのは、これが理由です。

Function: char * bind_textdomain_codeset (const char *domainname, const char *codeset)

関数bind_textdomain_codesetは、ドメインdomainname用のメッセージカタログの出力文字セットを指定するのに使用します。引数codesetには、関数iconv_openで使用できる有効なコードセット名、またはNULLポインターでなければなりません。

パラメーターcodesetがNULLポインターの場合、bind_textdomain_codesetは、ドメインdomainnameで現在選択されているコードセットを戻します。コードセットが選択されていないときは、NULLが戻されます。

bind_textdomain_codeset関数を複数回呼び出すこともあるでしょう。引数domainnameを変更せずに複数回呼び出したときは、それ以前に呼び出したときのセッティングによりオーバーライドされます。

bind_textdomain_codeset関数は、選択されたコードセットを結合した文字列へのポインターを戻します。その文字列は関数内部で割り当てられ、ユーザーは変更できません。bind_textdomain_codesetの実行中にシステムが割り当てに失敗すると、戻り値はNULLとなり、グローバル変数errnoに対応するエラーがセットされます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.5 あいまいさの解決のためにコンテキストを使用する

グラフィカルユーザーインターフェース(GUI)をもつプログラムで、gettext関数を普通に使うと、大きな問題がおきるかもしれない箇所があります。その問題とは、翻訳する必要がある文字列のほとんどが、短い文字列であるような場所で発生します。そらの文字列とは、プルダウンメニューの文字列のように、長さを制限する必要のある文字列です。それらの文字列は、センテンス全体を含んでいなかったり、センテンスの断片がプログラムの異なるシチュエーションで出現し、シチュエーションごとに異なる翻訳を割り当てる必要のあるものです。特にGUIプログラムで頻繁に使用される、1単語の文字列が問題になります。

gettextのアプローチには問題があるので、このような問題が存在しないcatgetsを使う必要があるという人もたくさんいます。しかし、この種の問題を処理するための簡単で強力な方法が、gettext関数には備わっているのです。

それは翻訳するべき文字列に、contextを追加する方法です。contextにもとづく翻訳参照とは、与えられた文字列にたいする翻訳を検索するときに与えられたcontextに検索範囲を限定することです。同じ文字列でも、異なるcontextに属する場合、異なる翻訳を割り当てることができます。ある文字列にたいするcontextごとの翻訳は、1つのMOファイルに一緒に保存でき、翻訳者も1つのPOファイルを編集するだけです。

gettext.hには、context付きの文字列を参照するためのマクロが含まれます。これらは<libintl.h>由来の軽量マクロ、またはインライン関数により実装されています。

const char *pgettext (const char *msgctxt, const char *msgid);

このマクロの呼び出しでは、msgctxtmsgidを文字列リテラルにしなければなりません。マクロは、msgctxtに与えられたcontextの、msgidに対応する翻訳を戻します。

msgctxtは、POファイル中で翻訳者が目にすることのできる文字列です。あなたは何らかの方法により標準的なものを定めることと、それを決して変更しないことが必要です。なぜならmsgctxtを変更する度に、翻訳者はmsgidにたいする翻訳をレビューする必要があるからです。

時間を経過しても変更されないような、標準的なmsgctxt文字列を見つけるのは困難です。しかしpgettextの呼び出しに、ファイル名やクラス名を使うべきではありません – なぜならファイルやクラスの名前を変更するのは開発タスクでは一般的なので、それが翻訳者の作業に影響を及ぼすべきでないからです。また、msgctxtに完全な英語センテンスのコメント形式を使うべきでもありません – なぜなら、そのようなセンテンスに適用される正書法や文法はしばしば変更されるので、繰り返しになりますが、その変更により翻訳者がレビューを強いられるべきではありません。

pgettext’の‘p’は、“particular(特定の)”から由来しています: pgettextは、特定のmsgidから翻訳を取得します。

const char *dpgettext (const char *domain_name,
                       const char *msgctxt, const char *msgid);
const char *dcpgettext (const char *domain_name,
                        const char *msgctxt, const char *msgid,
                        int category);

これらの関数はpgettextを、より一般化したものです。それぞれの関数は、dgettextdcgettextと同様に振る舞います。引数domain_nameには、翻訳のドメインを定義します。引数categoryを指定することにより、LC_MESSAGESとは異なるlocale categoryを指定できます。

次のような例で考えてみましょう。メニューバーをもつGUIプログラムがあり、メニューには以下のようなエントリーがあるとします:

+------------+------------+--------------------------------------+
| File       | Printer    |                                      |
+------------+------------+--------------------------------------+
| Open     | | Select   |
| New      | | Open     |
+----------+ | Connect  |
             +----------+

コード中のFilePrinterOpenNewSelectConnectの文字列は、gettextファミリーの関数によって翻訳される必要があります。しかしOpenという文字列は、2ヶ所で使われており、それにたいして異なる翻訳を割り当てなければならないかもしれず、それゆえ上述したようなジレンマが発生します。

メニュー中の同じ2つの文字列を区別するのは、メニューのルートからそれらのエントリーへのパスです:

Menu|File
Menu|Printer
Menu|File|Open
Menu|File|New
Menu|Printer|Select
Menu|Printer|Open
Menu|Printer|Connect

したがってcontextは、メニューのパスから最後の部分を除いたものになります。そうすると呼び出しは以下のようになるでしょう:

pgettext ("Menu|", "File")
pgettext ("Menu|", "Printer")
pgettext ("Menu|File|", "Open")
pgettext ("Menu|File|", "New")
pgettext ("Menu|Printer|", "Select")
pgettext ("Menu|Printer|", "Open")
pgettext ("Menu|Printer|", "Connect")

contextの最後に、区切り文字の‘|’をつけるかどうかは、スタイルの問題になります。

より複雑なケースとしては、msgctxtmsgidが文字列リテラルでない場合があります。そのようなケースにたいしては、より一般的なマクロが利用できます:

const char *pgettext_expr (const char *msgctxt, const char *msgid);
const char *dpgettext_expr (const char *domain_name,
                            const char *msgctxt, const char *msgid);
const char *dcpgettext_expr (const char *domain_name,
                             const char *msgctxt, const char *msgid,
                             int category);

これらのマクロは、msgctxtmsgidに、任意の文字列変数を指定できるので、より一般的です。どちらの引数も文字列リテラルのときは、‘_expr’が付加されていないマクロのほうが効率的です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.6 複数形(plural forms)にたいする追加の関数

いままで説明してきた既存のアプローチでは完全に無視してきましたが、gettextファミリーの関数(すべてのcatgets関数も同様)を実世界で使用する場合は、1つの問題があります。それはplural form(複数形書式)の取り扱いです。

インターナショナリゼーション以前のUnixのソースコード(そして悲しいことにインターナショナリゼーション以降のソースコードさえも)を見てみると、以下のようなコードを目にすることがあります:

   printf ("%d file%s deleted", n, n == 1 ? "" : "s");

最初にコードをインターナショナライズする人々から不具合が報告された後は、このような複数形についての場合分けを無視するか、"file(s)"という文字列を使うようになりました。これはどちらも不自然で解決法とはなりませんでした。最初の試みとして、以下のようにすることで解決が図られました:

   if (n == 1)
     printf ("%d file deleted", n);
   else
     printf ("%d files deleted", n);

しかし、これは問題の解決になっていません。この方法は、単純に名詞に ‘s’ を追加することによりplural formを表現するだけではない言語をも対象としていましたが、結局それだけのことでした。人々は自分が使っている言語のルールが、他の言語にも適用できる普遍的なものだと信じるという罠に陥っていたのです。実際には言語ファミリー間でplural formの取り扱いかたは大きく異なっていたのです。たとえば、Rafal Maszkowski <rzm@mat.uni.torun.pl>による以下のレポートを見てください:

わたしたちはPolishでplik(fileのこと)を以下ように表現します:

1 plik
2,3,4 pliki
5-21 pliko'w
22-24 pliki
25-31 pliko'w

以下同様にカウントしていきます(o’は8859-2 oacuteを意味しており、okreskaより、むしろaogonekと似ています。

言語間(そして言語ファミリー内部においてさえも)には、2つの異なる事象が存在しました:

これらの理由により、アプリケーションを記述する人は、これらの問題をコードで解決するべきではないという結論になります。これは言語環境にたいしてハードコードされた状態においてのみ有用なローカリゼーションでしょう。かわりに拡張されたgettextのインターフェースを使うべきです。

これらの追加の関数は、単一のキー文字列ではなく、2つの文字列と、数値の引数をとります。この考え方の背景には、数値の引数と最初の文字列をキー文字列として使用することにより、翻訳者が指定した正しいplural formを実装が選択できるようにするというアイデアがあります。それから、2つの文字列引数は、メッセージカタログが見つからなかったときの戻り値を提供するために使用されます(これは通常のgettextの振る舞いと同じです)。このケースではGermanic言語のルールが適用され、最初の文字列引数はsingular form、2番目の文字列引数はplural formとみなされます。

この結果、言語カタログをもたないプログラムは、それがGermanic言語のルールにしたがって記述された場合のみ正しい文字列を表示できるということになります。これは確かに制限なのですが、GNU C library(とGNU gettextパッケージ)がGNUパッケージの一部として記述されていること、そしてGNUプロジェクトのコーディング規約がEnglishによるプログラム記述を要請しているので、制限があるにもかかわらずこの解決策により要件を満足することができるのです。

Function: char * ngettext (const char *msgid1, const char *msgid2, unsigned long int n)

ngettext関数は、gettext関数と似ており、メッセージカタログを検索する方法は同じですが、2つの追加の引数をとります。パラメーターmsgid1には、変換する必要のある文字列のsingular formを指定します。このパラメーターはカタログを検索するキーとしても使用されます。パラメーターmsgid2にはplural formを指定します。パラメーターnは、plural formの適用を決定するのに使用されます。メッセージカタログが見つからなかったとき、n == 1ならmsgid1が戻され、それ以外のときはmsgid2が戻されます。

以下はこの関数の使用例です:

printf (ngettext ("%d file removed", "%d files removed", n), n);

nの数値は、printf関数にも引き渡されることに注意してください。ngettextだけに渡したい場合、この例は不適切です。

Englishのsingular caseの場合、常に1であるような数値は、"one"に置き換えることができます:

printf (ngettext ("One file removed", "%d files removed", n), n);

printf’関数は、format stringが与えられていない余分な引数を無視するので、この例は問題なく動作します。

ここで2つ以上の引数を要求するようなformat stringを関数で使う場合、以下の例のような使い方はできません:

printf (ngettext ("%d file removed from directory %s",
                  "%d files removed from directory %s",
                  n),
        n, dir);

Englishでsingular caseのときに‘%d’を“one”に置き換えたように、他の言語の翻訳者も特定の単語に置き換えたいと望むかもしれません。しかしCのformat stringでは、1番目の引数をスキップして2番目の引数を使用するようなことはできません。このような場合は引数の順番を変えて、‘n’が最後にくるようにする必要があります:

printf (ngettext ("%$2d file removed from directory %$1s",
                  "%$2d files removed from directory %$1s",
                  n),
        dir, n);

このように引数の配置を指定する文法についての詳細は、Cフォーマット文字列を参照してください。

nの値がとる範囲がわかっている場合には、xgettextツールのためのコメントを指定することができます。以下の例のような情報は、翻訳者が適切な翻訳を行う助けとなるでしょう:

if (days > 7 && days < 14)
  /* xgettext: range: 1..6 */
  printf (ngettext ("one week and one day", "one week and %d days",
                    days - 7),
          days - 7);

以下の例のように、文字列に数値が含まれないようなときに、この関数を使うこともできます:

puts (ngettext ("Delete the selected file?",
                "Delete the selected files?",
                n));

この例で、nはplural formであるかを判定するためだけに使用されています。

Function: char * dngettext (const char *domain, const char *msgid1, const char *msgid2, unsigned long int n)

dngettextは、選択されたメッセージカタログにたいして、dgettextと同様な方法で使用します。異なるのは、正しいplural formのために、2つの余分なパラメーターを指定できる点です。この2つのパラメーターは、ngettextのときと同様に処理されます。

Function: char * dcngettext (const char *domain, const char *msgid1, const char *msgid2, unsigned long int n, int category)

dcngettextは、選択されたメッセージカタログにたいして、dcgettextと同様な方法で使用します。異なるのは、正しいplural formのために、2つの余分なパラメーターを指定できる点です。この2つのパラメーターは、ngettextのときと同様に処理されます。

では、これらの関数はどのようにしてplural formsの問題を解決しているのでしょうか? 言語学の情報(そして、それは利用可能ではありません)がないかぎり、少しの差異しかないplural formのうちからどれを使用すればよいのか、そして新たにサポートされる言語ごとに数を増やせるかを決定することはできません。

したがって、plural formを選択するルールを翻訳者が指定するという解決策が実装されました。各言語ごとに方式が異なる以上、これはコード内に情報をハードコーディングする以外の、唯一可能な解決策なのです(それでもまだ新しい言語の使用を妨げない拡張可能性を満たすという要件は残されています)。

plural form選択のための情報は、以下のようにPOファイルのヘッダーエントリー(msgidが空文字列のエントリーのうちの1つ)に保存されています:

Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;

npluralsには、その言語では何種類のplural formがあるのかを数字で指定します。pluralに続く文字列には、C言語で使用できる評価式です。負の数値は使用できません。数値には正の整数を指定します。また、変数として使用できるのはnだけです。式で空白を使うことはできますが、バックスラッシュは使用できません。以下の例のうち、バックスラッシュと改行が使用されている例がありますが、これは表示を見やすくする目的のためだけに使用しています。この式はngettextdngettextdcngettextが呼び出されたときに評価されます。これらの関数に数値が渡されると、式中の変数nの値として、その数値が評価されます。結果は0以上、かつnpluralsに指定した値より小さくなければなりません。

複数形の使い分けについては、以下のルールが知られています。言語と言語のファミリーが記載されていますが、この情報を言語ファミリー全体に適用する必要があるという訳ではありません(見やすくするために併記しています)。5

1つの形式だけを使うもの:

1つの形式しか必要としない言語があります。これらの言語ではsingular formとplural formの区別はありません。この場合の適切なヘッダーエントリーは以下のようになるでしょう:

Plural-Forms: nplurals=1; plural=0;

このような特性をもつのは以下の言語です:

Asian family

Japanese, Vietnamese, Korean

2つの形式がありsingularは1にしか適用しないもの

この形式はEnglishで使われているもので、既存のプログラムでも一番多く使用されています。この場合のヘッダーエントリーは以下のようになるでしょう:

Plural-Forms: nplurals=2; plural=n != 1;

(注意: これはCの真偽値が0か1の2値をとる機能を使用しています。)

このような特性をもつのは以下の言語です:

Germanic family

English, German, Dutch, Swedish, Danish, Norwegian, Faroese

Romanic family

Spanish, Portuguese, Italian, Bulgarian

Latin/Greek family

Greek

Finno-Ugric family

Finnish, Estonian

Semitic family

Hebrew

Artificial

Esperanto

同じヘッダーエントリーを使う他の言語:

Finno-Ugric family

Hungarian

Turkic/Altaic family

Turkish

Hungarianは、数字を含んだセンテンスでは複数形を使いません。たとえば“1 apple”は “1 alma” で、“123 apples”も“123 alma”です。しかし数が明確でない場合には“the apple”は“az alma”、“the apples”は“az almák”のようにsingularとpluralを区別します。このようなセンテンスをngettextがサポートするようになってから、Hungarianも2つの形式をもつクラスに分類されるようになりました。

Turkish も同様です: “1 apple”は“1 elma”で、“123 apples”も“123 elma”です。しかし数字が省略された場合には、“the apple”は“elma”、“the apples”は“elmalar”のようにsingularとpluralを区別します。

2つの形式がありsingularを0と1に適用するもの

言語ファミリーの例外的なケースです。ヘッダーエントリーは以下のようになります:

Plural-Forms: nplurals=2; plural=n>1;

このような特性をもつのは以下の言語です:

Romanic family

Brazilian Portuguese, French

3つの形式があり、0を特別なケースとして扱うもの

ヘッダーエントリーは以下のようになります:

Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;

このような特性をもつのは以下の言語です:

Baltic family

Latvian

3つの形式があり、1と2を特別なケースとして扱うもの

ヘッダーエントリーは以下のようになります:

Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;

このような特性をもつのは以下の言語です:

Celtic

Gaeilge (Irish)

3つの形式があり、00または[2-9][0-9]で終わる数字を特別なケースとして扱うもの

ヘッダーエントリーは以下のようになります:

Plural-Forms: nplurals=3; \
    plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;

このような特性をもつのは以下の言語です:

Romanic family

Romanian

3つの形式があり、1[2-9]で終わる数字を特別なケースとして扱うもの

ヘッダーエントリーは以下のようになります:

Plural-Forms: nplurals=3; \
    plural=n%10==1 && n%100!=11 ? 0 : \
           n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2;

このような特性をもつのは以下の言語です:

Baltic family

Lithuanian

3つの形式があり、1、または2、3、4で終わる数字を特別なケースとして扱うもの、ただし1[1-4]で終わる数字を除く

ヘッダーエントリーは以下のようになります:

Plural-Forms: nplurals=3; \
    plural=n%10==1 && n%100!=11 ? 0 : \
           n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;

このような特性をもつのは以下の言語です:

Slavic family

Russian, Ukrainian, Belarusian, Serbian, Croatian

3つの形式があり、1と、2、3、4を特別なケースとして扱うもの

ヘッダーエントリーは以下のようになります:

Plural-Forms: nplurals=3; \
    plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;

このような特性をもつのは以下の言語です:

Slavic family

Czech, Slovak

3つの形式があり1と、2、3、4で終わる数字を特別なケースとして扱うもの

ヘッダーエントリーは以下のようになります:

Plural-Forms: nplurals=3; \
    plural=n==1 ? 0 : \
           n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;

このような特性をもつのは以下の言語です:

Slavic family

Polish

4つの形式があり1と、02、03、04で終わるすべての数字を特別なケースとして扱うもの

ヘッダーエントリーは以下のようになります:

Plural-Forms: nplurals=4; \
    plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;

このような特性をもつのは以下の言語です:

Slavic family

Slovenian

ここまで読んで、あなたは思うかもしれません。ngettextが扱うnの型は‘unsigned long’だ。では、もっと大きな整数型の場合はどうだろうか? 負の数値については? 浮動小数値の場合は?

uintmax_t’や‘unsigned long long’のようなより大きな数値のための整数型の場合、これらの数値は‘unsigned long’の範囲に適合するように値を小さくして処理できます。この場合、単に値を‘unsigned long’にキャストするのは正しくありません(キャストではULONG_MAX + 1は0、ULONG_MAX + 2は1、...のようにキャストされます)。あなたは、いままで紹介してきたすべてのplural formで、100(または1000や1000000)で除する方法によって数式を間接的に評価できるという事実を見てきたでしょう。もし大きな数値を、下6桁を保持して[1000000, 1999999]という範囲の他の数値に置き換えられれば、同じplural formの選択方法で取り扱えます。この場合のコードは以下のようになるでしょう:

#include <inttypes.h>
uintmax_t nbytes = ...;
printf (ngettext ("The file has %"PRIuMAX" byte.",
                  "The file has %"PRIuMAX" bytes.",
                  (nbytes > ULONG_MAX
                   ? (nbytes % 1000000) + 1000000
                   : nbytes)),
        nbytes);

負の数や小数については、通常はsingularかpluralが明解でない物質量に適用されます。このようなケースでは、ngettextを使う必要はなく、単にすべての値に適切な形式を指定してgettextを呼び出します:

printf (gettext ("Time elapsed: %.3f seconds"),
        num_milliseconds * 0.001);

num_millisecondsが1000の倍数のようなときでも、出力は以下のようになります

Time elapsed: 1.000 seconds

これは、Englishや他の言語でも許容できる出力です。

plural formにたいする翻訳者の考え方については、複数形の翻訳で説明しています。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.7 *gettext関数の最適化

この点を議論するには、GNU gettextの実装の優位性について話す必要があります。インターナショナライズされたプログラムは、翻訳する必要のある文字列がループ内にあるような場合に性能が劣化すると思う読者がいるかもしれません。たしかにループを実行するごとに文字列が評価されることによる劣化は無視できません。ループの実行中に文字列が変化しない場合に毎回文字列を翻訳する場合は、時間の無駄になります。以下の例で考えてみましょう:

{
  while (…)
    {
      puts (gettext ("Hello world"));
    }
}

選択したlocaleが実行中に変更されないような場合、翻訳結果の文字列は常に同じです。以下のようなやり方も1つの方法です:

{
  str = gettext ("Hello world");
  while (…)
    {
      puts (str);
    }
}

しかしこの解決策は、すべての状況で使える訳ではありません(例: 実行中にlocaleが変更される場合)。また、コードも読みにくくなってしまいます。

この理由により、GNU gettextは以前の結果をキャッシュしています。同じ翻訳が2度要求された場合、要求の間に新たなメッセージカタログがロードされていなければ、2度目の呼び出しではgettextは結果をキャッシュから取得します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3 2つのインターフェースの比較

以下の議論は幾分誇張されたものかもしれません。これまで述べてきたように、わたしたちはUniforumの勧告にしたがう理由があって、GNU gettextを実装しました。しかし、どのようにしてこの決定に至ったかをお見せするべきでしょう。

最初に開発プロセスを概観してみましょう。わたしたちがgettextにより提供されるNLSを使ってアプリケーションを記述するときは、いつものとおり処理のことです。ユーザーの目に触れるので文字列を翻訳する必要があるときだけ、わたしたちは"…"のかわりにgettext("…")を使って翻訳を行います。各ソースファイル(または中核となるヘッダーファイル)で、以下を定義します

#define gettext(String) (String)

この定義により、システムのCライブラリー自体でgettextがサポートされていても、それを無効化できます。このコードをコンパイルすると、NLSコードを使わない場合と同じ結果が得られます。GNU gettextのコードを見ると、gettext("…")のかわりに_("…")を使っているのがわかるでしょう。これにより翻訳可能な文字列のために余分にタイプしなければならない文字数を3文字まで減らせます。

これを出荷するバージョンのプログラムにする場合は、単に以下の定義

#define _(String) (String)

を、以下の定義に置き換えるだけで済みます。

#include <libintl.h>
#define _(String) gettext (String)

そして、翻訳可能な文字列を含むすべてのソースファイルにたいしてxgettextプログラムを実行します。わたしたちは翻訳が利用できないものにたいしても、利用可能になったら使えるように、プログラムを実行します。

同様のことはgettext_noop呼び出しでも行うことができます(翻訳可能文字列の特別なケースを参照してください)。gettext_noopは通常、no-op(訳注: no-operation = 何もしない) マクロとして定義します。プロジェクトでは以下のようなコードを考慮する必要があります:

#define gettext_noop(String) String
#define N_(String) gettext_noop (String)

N_は、_と同様、省略形です。GNU gettextpo/ディレクトリーにあるMakefileは、これらの省略形を認識するので、必要に応じて使うことができます。

今度はcatgetsを見てみましょう。主な問題点はプログラマー向けの機能にあります。彼は、翻訳可能な文字列ごとに、毎回異なる数字(または記号定数)を割り当てる必要があります。彼は重複したエントリー、重複したメッセージID、etc...にも注意を払わなければなりません。もしGNU gettextプログラムが提供するのと同じ品質をメッセージカタログにもたせたい場合、文字列にたいする説明コメントやソースコード中での場所をメッセージカタログに記述しなければなりません。これはほとんどMission: Impossibleでしょう。

しかしcatgetsの優位性を語る人たちが触れる点もいくつかあります。文字列内にある単語があり、その文字列が異なるコンテキストや他の言語で使われている場合に、その単語は異なる翻訳をもつことができます。以下に例を示しましょう:

printf ("%s: %d", gettext ("number"), number_of_errors)

printf ("you should see %d %s", number_count,
        number_count == 1 ? gettext ("number") : gettext ("numbers"))

この例では、"number"という文字列を2回翻訳する必要があります。たとえあなたがEnglishに類する言語を話さなくても、この単語が2つの文で異なる意味をもつかもしれないことに気づくでしょう。Germanでは、1番目にたいして"Anzahl"、2番目には"Zahl"と翻訳する必要があります。

これであなたはこのが難解な例だということに同意するでしょう。そしてあなたは間違っていません! では問題を正確に把握して、その問題がそれほど深刻ではないことにも気づくはずです。この問題は以下のようにして簡単に解決することができます:

printf ("%s %d", gettext ("number:"), number_of_errors)

printf (number_count == 1 ? gettext ("you should see %d number")
                          : gettext ("you should see %d numbers"),
        number_count)

わたしたちは、この方法で文字列の競合はすべて解決できると信じます。もし競合する文字列の一方を変更するのが困難なら、もう一方の文字列を少しだけ変更することも考慮できます。これを克服するのは不可能ではありません。

catgetsは、同じ元文字列にたいして異なる翻訳をもたせることができます。gettextでは同じ元文字列にたいして異なる翻訳をもたせることはできませんが、この種のあいまいさによる問題を解決する、よりスケーラブルな解決策があります。あいまいざの解決を参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.4 独自のプログラム内でlibintl.aを使用する

ライブラリーのバージョン0.9.4から始める場合、libintl.hは自己充足的になっています(例: 追加の関数なしでプログラムで使用できます)。ヘッダーとライブラリーはMakefileにより、$(prefix)で選択されたディレクトリーに配置されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.5 gettextを根底から理解する

注意: このセクションの文書は時代遅れになっているので、改訂する必要があります。

ソースコードを読むことは、GNU gettextの機能を完全に活用するための助けになるでしょう。しかし、(時として込み入った内容の)コードを読むために時間 費やすことを望まない人々のために、幾つかのコメントを挙げておきます:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.6 プログラマの章についての一時的なメモ

注意: このセクションの文書は時代遅れになっているので、改訂する必要があります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.6.1 一時的な情報 - 二つの実装

言語に依存せずにメッセージを扱う二つの手法があります。一つはX/Openの catgetsによるものであり、もう一つはUniforumのgettextによるものです。catgetsによる方法では、整数によってメッセージを指定します。gettextによる方法では、英語のメッセージによって指定します。catgetsによる方法は長く使われ、多くのベンダでサポートされています。gettextによる方法ははSunでサポートされていて、COSEマルチベンダイニシアティブ(COSE multivendor initiative)がサポートするようです。どちらもPOSIX標準とはなりませんでした。POSIX.1 委員会では、この件に関して様々な見解の相違がありました。

二つの手法のいずれもPOSIX標準ではありません。gettextcatgets(XPG)ルーチンのいずれを標準として採用するかについて、POSIX.1 委員会ではは様々な議論がなされました。委員会の終盤に至っても何らの合意は得られず、結局メッセージングシステムは標準規格には含まれませんでした。私はXPG3メッセージングインターフェースに関する追記を標準に付与するのは有益であると信じていますし、“...メッセージングシステムの実例は既に実装されているのです...”

委員会は、ある一つのインターフェースの実装を使うのが良いということをどの場所でも言わないように非常に注意していました。この話題に関するこれ以上の情報 については、国際化プログラミングFAQ(Programming for Internationalization FAQ)を参照して下さい。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.6.2 一時的な情報 - catgetsについて

catgetsを基盤として使用することに関する討議の末期には、幾つかの議論がありました。その議論の両側を提示することは大切だと思いますし、これから、私はちょっとしたことに対して「悪魔の弁護士」となってみることにします。

catgetsはもっと良くデザイン出来たでだろうということは否定しません。その実装には既に指摘したような制限が少なからずあります。

しかしながら、その一貫性と標準化の度合いについては申し分ありません。UNIXソフトウェアを書くときに繰り返し発生する問題とは、UNIXプラットフォーム間での移植性に関する問題です。それは全ての UNIXベンダがオペレーティングシステム上を調べて改良する部分を見つけたようなものです。疑いもなく、これらの修正は革新的なものであり、現実の問題を解決するものです。しかしながら、ソフトウェアベンダがこれらの変更を多くのプラットフォームで行いつづけるには、多くの労力が必要です。

そしてこれは各UNIXベンダが自社のシステムを標準化することを促進します。Spec1170に準拠するためにです。各主要UNIXベンダはこの標準化のために委員会を設けました。そして全てのUNIXソフトウェア開発者はこの標準に従ってソフトウェアを作成し、異なるプラットフォームへソフトウェアを導入する際には (autoconfを使うことなく)リコンパイルするだけで済むようになる日を心待ちにし ているのです。

私の理解しているところでは、Spec1170はX/Open Portability Guidelinesのバージョン4(XPG4)に基づいたものです。catgetsとその眷属がXPG4で定義されているので、私はcatgetsがSpec1170の一部であり、それがすべてのUNIXシステムの標準的なコンポーネントになることを信じています。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.6.3 一時的な情報 - なぜ一つの実装なのか

メッセージカタログにアクセスするために二つの異なるシステムをインストールすることは不経済なことのように思えます。我々がcatgetsの不足しているものを改善したいと思ったのなら、なぜ新しいシステムを実装するのではなく、catgetsを(互換性を保ちながら)拡張しようとしないのでしょうか? いずれにせよ我々は、メッセージカタログにアクセスするためのシステムをオペレーティ ングシステムに対して二つインストールすることになるでしょう。一つはGNUソフ トウェアのためルーチン群であり、もう一つはその他全てのソフトウェアのためのルーチン群(catgets)です。傲慢でしょうか?

カタログにアクセスする別のシステムが実装されたと仮定してみましょう。我々がお奨めするのはどちらでしょうか? 少なくともLinuxシステムに対しては、我々は可能な限り多くのソフトウェア開発者を呼び込む必要があります。そのため、我々はソフトウェア開発者が彼らのソフトウェアを移植しやすいようにする必要があります。そしてそれはcatgetsをサポートすることを意味します。我々は libintlコードをlibc中に実装するでしょうが、libcには別のメッセージカタログに対するアクセス方法を同じように取り込まなければいけないということなのでしょうか? そして、libintlと非catgetsルーチンを組み合わせて使おうとする人達に関してはどうでしょうか?ソフトウェア開発者が彼らのソフトウェアを他のプラットフォームに移植する際、彼らはそのソフトウェアに単にlibintlを含めるだけでなく、フロントエンド(libintl)コードと、バックエンド(非catgetsアクセスルーチン)コードを付け加えようとするでしょう。

しかしメッセージカタログのサポートは氷山の一角に過ぎません。他のロカールカテゴリのデータはどうでしょうか。それらもまた、多くの相違点を持っています。我々はそれに対処することを諦めて、重複したルーチン群を別々に開発せねばならないのでしょうか(libintlをメッセージカタログサポート以上のものにすべきなのでしょうか)?

UNIX上の改良可能な多くの部分と同じように、我々は将来に向けて改良を加えつつも、過去のものに対する互換性を落とさないようにしていました。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.6.4 一時的な情報 - ノート

多くの実装が最終形式からかけ離れたものであったため、X/Openが標準形式を承認するのは非常に遅くなりました。私の使っている両方のシステム(古いLinux catgetsとUltrix-4)には奇妙なバリエーションがあります。

最後の変更を加えた後、私はGNU/Linux libcgettext関数群を作成するために時間を割かねばなりませんでした。従って、将来的にはSolarisがgettextを備えた唯一のシステムであるということはなくなります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12 翻訳者の視点


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.1 イントロダクション0

注意: このセクションの文書は時代遅れになっているので、改訂する必要があります。

GNUは国際化しつつあります! 翻訳プロジェクトは保守担当者、翻訳者、そしてユーザーを全てまとめるもので、そのためGNUソフトウェアは徐々に多くの言語を喋ることが出来るようになります。

GNU gettextツールセットには、保守担当者がパッケージのメッセージを国際化するために必要となる全てがあります。また、パッケージが国際化された後で、翻訳者がメッセージの地域化を行う際の助けになるような便利なツールもあります。

翻訳プロジェクトを完遂するために、我々は自分の国の言葉を愛し、良く書くことが出来、そして他の翻訳者が話しているのと同じ言語で助けることの出来る(synergize)能力を持った人間を数多く必要としています。もしあなたが翻訳チームでボランティアとして働くことを望むなら、該当する翻訳チームにメー ルを出して下さい。

各チームはLinux Internationalの好意による自身のメーリングリストを持っています。ll@li.orgというアドレスのllをあなたの注目する言語のISO 639の二文字コードに置き換えることによって、その言語の翻訳チームに連絡できます。言語コードはISO 3166に定められている国コードと同じではありません。現時点では以下の翻訳チームが存在します。

Chinese zh、Czech cs、Danish da、Dutch nl、Esperanto eo、Finnish fi、French fr、Irish ga、German de、Greek el、Italian it、Japanese ja、Indonesian in、Norwegian no、Polish pl、Portuguese pt、Russian ru、Spanish es、Swedish sv、Turkish tr

仮に中国語翻訳チームにメールを出すとすれば、zh@li.orgとなります。翻訳チームのメンバーになるには、その言語チームのメーリングリストに登録する必要があります。例えば、スウェーデン人は本文に以下の内容を記述してsv-request@li.orgにメールを出します。

subscribe

チームのメンバーは翻訳作業に興味を持つべきだということを心に留めて置いて下さい。そうでなければ翻訳を果たすことは難しいのです。もしが希望する言語のチームがまだ存在せず、その言語のチームを作りたいという場合にはcoordinator@translationproject.orgまで連絡して下さい。それによって全ての翻訳チームの調整者に連絡が取れます。

一握りのGNUパッケージには幾つかの言語に対するメッセージの翻訳が適用・提供 されています。翻訳チームは組織化され始めており、これらのパッケージを起点として使っています。しかしまだまだ多くのパッケージがあり、多くの言語についてはボランティアの翻訳者がいません。もし翻訳チームでボランティアとして作業したいと思うのでしたら、coordinator@translationproject.orgに作業することの出来る言語を明記してメールを送って下さい。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.2 イントロダクション1

注意: このセクションの文書は時代遅れになっているので、改訂する必要があります。

現在公式に、GNUは国際化しつつあります! 以下は1995年1月のGNU Bulletinで述べられた声明です。

一握りのGNUパッケージには幾つかの言語に対するメッセージの翻訳が適用・提供されています。翻訳チームは組織化され始めており、これらのパッケージを起点として使っています。しかしまだまだ多くのパッケージがあり、多くの言語についてはボランティアの翻訳者がいません。もし翻訳チームでボランティアとして作業したいと思うのでしたら、‘coordinator@translationproject.org’に作業することの出来る言語を明記してメールを送って下さい。

本ドキュメントはその過程に興味を持ったり、貢献したいと考えている人々が持つ多くの疑問に答えます。願わくばざっと目を通し、GNUの国際化に対するこの集合的努力から産み出される大量のメールの幾ばくかでもを担当して下さい。

広く共用される多くのフリーソフトウェアのプログラミングは英語で行われています。そして現在のところ、英語はGNUプロジェクトに協力する国家的コミュニ ティ間での主要なコミュニケーション言語として使われています。このドキュメントでさえも英語で書かれています。これは当面変わらないでしょう。

しかしながら、多くのソフトウェアで自国語や自国の習慣を用いたいという、国家的コミュニティからの強い欲求があります。また、GNUソフトウェアをそのようにするための努力が現在も行われています。この試みは今までのところプリテスタからの熱心な反応の向上によって動かされており、我々はGNUの国際化は成功すると信じています。

このドキュメントに対する内容の明確化、追加、訂正に関する提案については、coordinator@translationproject.orgまでメールを送って下さい。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.3 議論

注意: このセクションの文書は時代遅れになっているので、改訂する必要があります。

この国際化の効果を目の当たりにして、幾人かのユーザが彼らの考えを表明しています。紹介され議論されたこれらの疑問の幾つかをここに挙げてみましょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.4 組織

注意: このセクションの文書は時代遅れになっているので、改訂する必要があります。

大きな尺度で見れば、真の解決方法は有志が参加できるようなある種の正しく厳密な集合を組織化することでしょう。私は、最近このアイディアについて幾つかの考察を行い、幾つかの微妙なポイントがあるであろうことを認識しています。私は、そのようなプロジェクトを開始するために、Richard Stallmanに連絡することを考えましたが、まず最初に我々の間でアイディアを揺り落とすことが良いだろうと感じました。おそらく、Linux Internationalは既にこの分野における幾らかの経験、または、有志の作業のオーケストラのようなものを持っています。あらゆる場合に、思考のための食物を!

我々は早々に何らかの方法で何かをセットアップせねばならないと考えます。同じ言語に対する作業のインターロックと重複を避けるという点で、それは多くの言語のコントリビュータを助けるでしょう。そして、更にそれらの言語(大部分の言語では技術的な英語の翻訳について独特な多くの問題点があります)についての独特な問題を共に解決するように連絡が取れるようにします。スウェーデンのコントリビュータはこれらの問題点を認め、そして私はフランス語においてのそれらの問題点に相当に気が付いています。

確かにこれは技術的問題ではありません、しかし我々は、コントリビュータ、及び管理者間の国家チーム層のインターフェースに関わらず、ロカールコントリビュータの努力が最大限に有益になるように管理するべきです。

翻訳プロジェクトは言語コーディネータを統合するためにある準備を必要とします。一度この作業が始められたなら、発展中のプログラムのローカライズは、確かにフリーソフトウェアコミュニティにおいて永久の、そして、連続的な動きになるでしょう。GNU gettextが公式の現実になる前に、最小限の準備が完了し、そしてテストされているべきです。電子メールアドレスcoordinator@translationproject.orgは、これらの話題に基づくボランティア、及び、一般的な電子メールから申し出を受けるための準備でした。このアドレスは、翻訳プロジェクトのコーディネータに届きます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.4.1 中央による調整

そのことについて考えるよりも更に早く、GNUは誰かがそれらのグループを組織化し調整する方法を準備する必要があると私もまた考えます。ある種のグループのグループです。GNUは直ちに共同で働いているボランティアの小さなグループにこのタスクを委託することが良いだろうと、私は考えています。 おそらく、この国家委員会的なグループのリストはgnu.announceにおいて公表され得ます。

コーディネータとしての私の役割は単に、Ulrichをフリーソフトウェアの地域化に興味を持っているドイツ語を話すボランティアに紹介すること、そして国家的グループの準備が出来るまでの国家的登録機関のメンテナンス中に、国家的グループの最初の組織化を助けることです。実際、コーディネータは、ボランティアが国家チーム(言語または国(局地的言語)について1人のコーディネータを選択するべきです)を作成するために相互と連絡を取りやすくせねばなりません。これが正しく行われたならば、コーディネーションは不可抗力的作業を除いて便利なものとなり、代理人に時間を任せることが出来るようになります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.4.2 国家チーム

私は、我々が個々の言語のための有志のコーディネータ/エディタを捜すことを提案します。これらの人々は彼ら自身の言語のために、様々なプログラムの翻訳ファイルを探し出し、そして、語法に対する高度で一定の標準を保証することになるで しょう。

今までの他の人々との間の私の現在の経験によれば、地域化を実現する人々はこのプロセスに対して非常に熱心であり、彼らは自分自身が地域化するプログラムよりも地域化のプロセスにほうに興味を持ち、それだけでなく多くのプログラムを地域化したいと思うものです。この事実は、各言語のためのコーディネータ/エディタを持つことは良いアイディアであることを確信させます。

我々は、問題となる言語において明瞭かつ簡潔な文章を書く際、適任となる人物を選択する必要があります。これは難しい作業です — 我々は、自分自身でそれをチェックすることができません。従って、我々は数人の人間対してに互いの記述を判断するように要請し、そして最適任者を選択する必要があります。

私は私のプレリリースを20人から30人の人々に発表ましたが、そのプレリリースが既に生み出した全ての議論をあなたは信じないでしょう。私は、真に、公式に、世界中でこの作業が開始されるときに起こるであろうことを想像すると身震いがします。例えば、相互に反論しあう二人のチェコスロヴァキアのユーザーの間を仲裁するのは私なのでしょうか?

私がこれらの公式化について判断することが出来ないように、あなたのドイツ語が私のフランス語よりはるかに良いとは限らないと推測します。私が提案するものは、各言語に対してPOファイルをメンテナンスしその変更を判定する人々のグループを置くということです。そのような人々のグループがどのように行動するかについて、グループ間には文化的な相違点があると考えます。幾つかのグループはは緩い方法を採用し、簡単にコンセンサスの一致に達し、グループ中の誰もが保守者に関わることができます。一方は死ぬまで戦い、重い管理を国家の標準にまで組織化し、厳密なチャネルを使用するでしょう。

ドイツのチームは良い例を出しています。直ちに、彼らはおそらくお互いの翻訳を訂正する半数の人々と言語上の論点について議論する半ダースの人々です。私は全ての名前を知っているわけではありません。Ulrich Drepperはドイツのチームのコーディネートを担当しています。彼は私のプレテストのリストの購読を申し込みました。従って、私は彼に対して、連絡されるリリースの詳細について警告する必要は特にありません。

各言語を担当する翻訳チームを得るためには、それはよいアイディアだと思います。 翻訳を更に良く首尾一貫した状態にするでしょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.4.2.1 サブカルチャー

フランス語を例に取ってみましょう。コンピュータの世界では、意味が異なる語彙を持つ幾つかのサブカルチャーがあります。組織化された方法でこの問題を提起することなしにあちこちでボランティアを選んでいると、プロジェクトにはすぐに国際化されたプログラムのごちゃ混ぜ状態が発生します。そしてことによると、実際にこの問題を気にする人々の間で終りなき口論が始まるでしょう。

国際化されたプログラムをフランス語へ地域化する過程において、ある種の統一を保つことは難しい(そしてデリケートな)仕事です。フランス人のラテンな人柄 (:-) を知っていても、もし我々がこのことを間違った方法で捉えれば、我々はどことも知れぬ場所で終わってしまうか、多くのエネルギーを無駄にしてしまうことでしょう。おそらく我々は、GNU gettextが公式に発表される前に真剣にこの問題に取り組まなければならないでしょう。そして、それはすぐではないかと私は推測します!


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.4.2.2 組織化へのアイディア

私は、公式リリース後に次の大きな変更があると考えています。どうか、私が短いGPLメッセージのドイツ語翻訳を用いることに注目してください。我々は、フリーソフトウェアコミュニティにおける真の地域化が消え去ってしまう前に2、3の良い例を示す必要があります、ここでは、議論が必要ないくつかのポイントを示します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.4.3 メーリングリスト

GNU gettextに関するあらゆる問合せについては、以下に送ってください。

coordinator@translationproject.org

*-pretestリストは、私にとって本当に有益です、アイディアはおそらく、多くのGNU、及び、非GNUパッケージへと一般化されるでしょう。しかし、保守者以外の、彼/彼女の方法!

François、我々は、チーム、チームをサポートするメーリングリストそしてログメンバを追跡するために、gnu.ai.mit.eduに適当なメカニズムを持って います。我々は、あなたが使うわずかな優先権を持っています。これがあなたにとって問題ないならば、私はあなたに情報を与えることができます。

事物は変化しています! 2、3年前、Daniel Feketeと私がGNU地域化のメーリングリスト(FSFの中にあった)に尋ねたとき、我々は作業をどこででも組織化するように礼儀正しく勧められ、そして我々はそれを実行しました。私のプリテスタと連絡を取るために、私はmajordomoで管理される少数のメーリングリストをiro.umontreal.caに作成しました。これらのリストは今までのところ非常に信頼できました...

私は、ドイツ語のチームがドイツにあるメーリングリストを組織化し、他の国にも組織化をさせると思います。しかし組織化が行われる前に、FSFにおいて各国のチームのためのメーリングリストを提供することは確かに有益でしょう。そうです、私にどのようにメーリングリストを作成し扱えばよいかを説明して下さい。

我々は一時的なメーリングリストを、人々を組織化しやすいように国ごとに一つずつ作らねばなりません。なぜ一時的か、なぜなら一度再構成されたなら、各国のボ ランティアは彼らのリストへと戻ってきて、そして自分達が望むように管理するだろうからです。このことについては、個々のチームは自分達の国の中から 自分達のリストを動かすだろうと思います。全てのチームが購読することの出来る、 中央のメーリングリストも作る必要があるでしょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.5 情報の流れ

注意: このセクションの文書は時代遅れになっているので、改訂する必要があります。

パッケージが最終的にリリースされた後、このメッセージについての幾つかの議論があることでしょう。今、人々が更に良い幾つかのメッセージを提案したとしたら、あなたはどうしますか? Jim、私が提供する1ダース近い地域化されたプログラムと同様、どうか直ちにそれらのメッセージに注目して下さい。私は翻訳とそれらに関する調整の両方を受け取るのです。

私が事前にテストするものを一つ置いたならば、Ulrichはその告知を受け取り、そしてそれを最後に修正するドイツ語のチームに渡します。そして彼は保守者として私に翻訳ファイルを引き渡します。私が保守していないフリーのパッケー ジについては何も聞きません。私が思うに、全ての翻訳プロジェクトにおいてこのスキームが作られるでしょう。セキュリティに関わる理由のために、おそらく Ulrich(実際の国家的コーディネータ)は時折翻訳プロジェクト(Jim、私、又はLenの新人)によって保持される中央のレジストリをアップデートすべきです。

私は小さなGNUパッケージは一週間に一つずつ、より大きなパッケージは数週間か数ヵ月をかけるという責務を私自身に課し、12月か1月には私はにGNUの全パッケー ジを国際化する準備を積極的に整えていました。しかし、それはそのようには動きません。私は最初に、私が責任を持つ全てのことを行いました。私は他の保守者の幾らかの伝道作業に対して何も持っていませんでした。しかし私もまた多くのエネルギーを失いました — 同じ議論を繰り返します。

そして、最初に地域化されたパッケージがリリースされるとき、我々は、醜悪な翻訳 :-) についての多くの反応を得るでことしょう。確かに、そして我々は事前に、パッケージ保守者と国家チームの間の情報の流れを制御することに関する良いアイディアを持つ必要があります。

どうかどこかに各POファイルの迅速なヒストリを保存し始めて下さい。コメントを認めることによってファイルフォーマットがいずれ変更されるであろうことを私は知っています。各ファイルがログのようなもの、そしてコメントや不平の申し立て、又はその他の貢献をしたいと思う人々へのリファレンスを持つほうがよいでしょう。私は高速でフレキシブルなフォーマットに関する申し立てをしましたが、しかしそれはまだGNUの意思決定者によって受け入れられていません。私がこれについてより多くの情報を得たなら、このことについてお話しすることになるでしょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.6 複数形の翻訳

あなたがPOファイルを翻訳しようとしていて、それには以下のようなエントリーが含まれているとしましょう:

#, c-format
msgid "One file removed"
msgid_plural "%d files removed"
msgstr[0] ""
msgstr[1] ""

これはどういう意味なのでしょうか? どうやって記入すればよいのでしょうか?

このようなエントリーは、メッセージにplural formがあることを示しています。plural formとは、メッセージ中の数字の値が複数形として出力しなければならない値の時に出力すべき文字列です。msgid_plural行に記述されているのは、Englishにおけるそのようなメッセージの一般的な形式です。msgid行には、Englishにおけるsingular formで、数字の値が1のときに出力するテキストが記述されています。plural formについての詳細は、複数形(plural forms)にたいする追加の関数で説明しています。

最初に見る必要があるのは、POファイルのヘッダーエントリーのPlural-Formsという行です。この行にはplural formを判定するための数字と式が記述されています。まだPOファイルにそのような行がない場合は、追加する必要があります。これは、あなたが翻訳しようとしている言語に依存します。この情報はmsginitコマンド(新しいPOファイルの作成を参照してください) – これには既知のplural formulaのデータベースが含まれています – を使うか、翻訳チームの他のメンバーに尋ねてみてください。

以下のような行について考えてみましょう:

"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"

これは論理的には1行になります。POファイルの書式では、各行を80文字までにおさまるように長い行を分割できることを思い出してください。

npluralsの値は、3つのplural formがあることを示しています。最初に行わなければならないのは、各形式ごとにmsgstrを含むエントリーを作ることです:

#, c-format
msgid "One file removed"
msgid_plural "%d files removed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""

それからmsgid_pluralを翻訳して、各msgstr行にそれを記述します:

#, c-format
msgid "One file removed"
msgid_plural "%d files removed"
msgstr[0] "%d slika uklonjenih"
msgstr[1] "%d slika uklonjenih"
msgstr[2] "%d slika uklonjenih"

ではplural formに適合するように翻訳を改善しましょう。上述の式にしたがって、msgstr[0]には1で終わるが11では終わらない数字のときの翻訳を、msgstr[1]には2、3、4で終わるが12、13、14では終わらない数字のときの翻訳、そしてmsgstr[2]にはそれ以外のときに使用する翻訳を記述します。これにしたがって改善したものが以下の翻訳です:

#, c-format
msgid "One file removed"
msgid_plural "%d files removed"
msgstr[0] "%d slika je uklonjena"
msgstr[1] "%d datoteke uklonjenih"
msgstr[2] "%d slika uklonjenih"

Englishのsingular form(msgid)では、数字用の書式指定が省かれて、数字の1をあらわす“one”という単語に置き換えられていることに気づくでしょう。あなたが翻訳するときも同じようできるでしょうか?

msgstr[0] "jednom datotekom je uklonjen"

これはmsgstr[0]を1のときだけ使うのか、他の数字のときも使うかによります。plural formulaに当てはめて考えると、msgstr[0]n == 1のときだけ、数字用の書式指定子を使わない特定の翻訳文を使うことができます。しかしこの例の場合、msgstr[0]は21、31、41...などのときにも使用するので、書式指定子を省くことはできません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

12.7 メッセージの優先度: 最初に翻訳すべきメッセージを決める方法

翻訳者が週のうちパッケージに避ける時間が限られているにもかかわらず、パッケージにはとても多くのメッセージ(1000超)があるとしましょう。そのようなときは彼女は一番ユーザーの目に触れるメッセージ、または一番頻繁に発生するメッセージを訳したいと望むでしょう。このセクションでは、このような"もっとも緊急"なメッセージをどのように決定するか説明します。これは、すでに部分的に翻訳されたメッセージカタログの中から、"次に緊急"なメッセージを決定するのにも適用できます。

最初のステップとして、彼女は、ユーザーがプログラムを使うのと同様にしてプログラムを使ってみます。彼女がこれを行っているとき、プログラムがまだ翻訳されていないメッセージの翻訳にたいする要求があると、GNU gettextライブラリーはそれをログファイルに記録します。

次のステップで、彼女はPOモードを使って、それらのメッセージを翻訳するのです。

より詳細に見てみましょう。GNU libintl(GNU libcの対応する関数とは異なる)は、環境変数GETTEXT_LOG_UNTRANSLATEDをサポートします。GNU libintlライブラリーはgettext()、および関連する関数が翻訳を見つけられなかったとき、そのメッセージをログに記録します。ログファイルがない場合には、必要に応じて作成します。GNU libcによるシステムでは、ELFの‘LD_PRELOAD’メカニズムで使用できる、共有ライブラリー‘preloadable_libintl.so’が提供されます。

GNU libcのシステムでは、翻訳者は最初のステップとして以下のコマンドを実行します:

$ LD_PRELOAD=/usr/local/lib/preloadable_libintl.so
$ export LD_PRELOAD
$ GETTEXT_LOG_UNTRANSLATED=$HOME/gettextlogused
$ export GETTEXT_LOG_UNTRANSLATED

他のシステムでは以下のコマンドを使います:

$ GETTEXT_LOG_UNTRANSLATED=$HOME/gettextlogused
$ export GETTEXT_LOG_UNTRANSLATED

それから彼女はプログラムを使ってみます(あなたが翻訳を提供するプログラムを使うのはよいことですし、お勧めの練習方法です。これは必要なコンテキストを与えてくれます)。これが終わったら、彼女は環境変数を削除します:

$ unset LD_PRELOAD
$ unset GETTEXT_LOG_UNTRANSLATED

次のステップは、重複を取り除くことです:

$ msguniq $HOME/gettextlogused > missing.po

この結果はPOファイルですが、POファイルエディターで処理するためには、少し前処理が必要です。最初に、このファイルは多くの翻訳ドメインのメッセージを含んだマルチドメインのPOファイルです。次に、翻訳者のコメントとソースファイルへの参照が含まれていません。以下は、影響を受ける翻訳ドメインの一覧を得る方法です:

$ sed -n -e 's,^domain "\(.*\)"$,\1,p' < missing.po | sort | uniq

それから翻訳者はドメインを1つずつ処理していきます。単純にするために、language、domain、source package を環境変数に設定しましょう。

$ lang=nl             # your language
$ domain=coreutils    # the name of the domain to be handled
$ package=/usr/src/gnu/coreutils-4.5.4   # the package where it comes from

彼女は、$lang.poの最新コピーを、翻訳プロジェクト、またはそのパッケージ(大抵は$package/po/$lang.po)から入手します。もし彼女が、そのパッケージの最初の翻訳者の場合は、新規作成することになります(新しいPOファイルの作成を参照してください)。それから彼女は、以下のコマンドを使って、緊急ではないメッセージにたいして "obsolete" のマークを付与します(それらの翻訳済み、および未翻訳のメッセージが本当に "obsolete" としてしまう訳ではありません。これは以下の編集で、POファイルエディターに、それらのメッセージを無視させるためです)。

$ msggrep --domain=$domain missing.po | grep -v '^domain' \
  > $domain-missing.po
$ msgattrib --set-obsolete --ignore-file $domain-missing.po $domain.$lang.po \
  > $domain.$lang-urgent.po

それから彼女はPOファイルエディターを使って$domain.$lang-urgent.poを翻訳します(POファイルの編集を参照してください)。(FIXME: KBabelとgtranslatorが期待通りobsolete messageを保持してくれるかどうかについては、わたしにはわかりません) そして彼女は最後に、以下のコマンドで緊急ではないメッセージ(およびすでに翻訳済みのメッセージの初期の"翻訳")を復元します:

$ msgmerge --no-fuzzy-matching $domain.$lang-urgent.po $package/po/$domain.pot \
  > $domain.$lang.po

$domain.$lang.poを投稿したら、彼女は次のドメインを処理できます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13 メンテナーの視点

パッケージのメンテナーには多くの責任があります。そのうちの1つは、たくさんのプラットフォームでパッケージを簡単にインストールできるようにすることで、わたしたちが前に説明したマジック(ユーザーの視点を参照してください)を、インストーラーとエンドユーザーにたいして働くようにすることです。

GNU gettextをディストリビューションに統合できるようにする方法はたくさんありますが、このチャプターではそれらを総括的にカバーすることはしません。かわりにGNU標準、さらにはGnits標準にしたがった、多くのフリーソフトウェアディストリビューションで利用可能なアプローチの詳細について議論します。なぜならGNU gettextは、GNUプロジェクト全体のインターナショナリゼーションを助けるのを目的としているので、多くの有用でフリーなパッケージが対象となるからです。そのためこのチャプターでは、すでにconfigure.acがあり、GNU Autoconfを使うパッケージを対象とします。

それにもかかわらずGNU gettextは、GNU標準やその類にしたがっていないフリーパッケージにたいしても有用です。そのようなパッケージのメンテナーは自分の想像力と独創力によりディストリビューションを組織化する必要がありますが、gettextはすべての状況で動作するでしょう(そしてそのようなパッケージはたくさん存在します)。

gettextのメソッドは現在安定しているとはいえ、gettextの各バージョン間でちょっとした調整は必要になるでしょう。そのため、このチャプターの内容は、新たなリリースによる変更にしたがって読み替える必要があります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1 非フラットなディレクトリー階層

フリーなソフトウェアパッケージの中には、tarにより配布され、解凍すると単層のディレクトリーに展開されるものがあります。このようなパッケージをflatなディストリビューションと呼びます。それとは別に、Texinfoマニュアルやman pageのためのサブディレクトリーdoc/、Cライブラリーを置き換えたり保管する関数を保持するlib/、パッケージのソースの入ったsrc/などの階層をもつ、フリーなソフトウェアパッケージも存在します。このようなディストリビューションのことを、non-flatであると呼びます。

flatなディストリビューションにたいして、わたしたちはあまり多くを語ることはできません。GNU gettextを新しいバージョンにすることにより、flatなディレクトリー構造は難しさが増大するという欠点があります。たくさんのPOファイルがある場合、この単層のディレクトリーの内容は汚くなってしまうでしょう。またCソースに含まれる GNU gettextのlibintlのソース、シェルやsedのスクリプト、そして複雑なMakefileのルールは、flatな構造には適しません。これらの理由により、non-flatを使う方法を推奨します。

GNU gettext自身もnon-flatな構造をもち、わたしたちはこの方法に精通していることも、わたしたちがこのチャプターでそれを説明しようとしている理由なのかもしれません。これを機会に、パッケージの構造をnon-flatにするメンテナーもいるかもしれません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.2 前提となる作業

パッケージにたいしてGNU gettextを使用するためには、準備が少し必要です。これらの作業は、要点の説明だけだと肝心な部分がわからなくなってしまうある種の一般性をもっているので、このチャプターを読んで後から見返せるように、ここで大まかに説明しておきましょう。

POファイルが投稿されたとき、メンテナーとしてどのように振る舞うのが理想的なのか、少し説明をしておきましょう。メンテナーとしてのあなたの役割は、その投稿が翻訳プロジェクト内の対応する翻訳チーム(わからないときはcoordinator@translationproject.orgに転送してください)によるものであることを証明し、POファイルのフォーマットが壊れていてインストールできないくなっていないか確認し、それらのPOファイルを配布物のpo/ディレクトリーに配置することです。

メンテナーとしては、翻訳が十分なのか、または完璧なのかをチェックする責任を負う必要はないので、語学に関する事柄については無視するべきです。翻訳チームは、チーム自身の運営と翻訳プロジェクトでの言語学的な選択について完全な責任を負います。翻訳チームがメンテナーにより運営されるのではないことを覚えておいてください。ユーザーからの言語上の指摘や報告などを、適切な翻訳チームに転送したり、ユーザーが翻訳チームに参加する方法を説明するような手助けをすることはできます。もっとも簡単なのはABOUT-NLSファイルを送ることでしょう。

メンテナーが翻訳チームを介さずに、自分でPOファイルに関するバグ報告を受けるのは決して行うべきではないことです。ある問題について翻訳者が彼女のチームと一致した見解をもつのが困難なとき、彼女が直接メンテナーと交渉するようなオプションが存在するべきではありません。どんな問題にせよ、彼らは問題をチーム自身で解決するべきです。メンテナーとしては、もしチームに本当に問題があると思えるときでも、あなた自身がチームの問題を解決しようとはしないでください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.3 gettextizeプログラムの呼び出し

gettextizeプログラムは、GNU gettextによりインターナショナライズされたパッケージのメンテナーを助けるための対話的なツールで、2つの目的のために使用されます:

このプログラムは以下のタスクを処理します:

呼び出し方は以下のようになります:

gettextize [ option… ] [ directory ]

以下のオプションを指定できます:

-f
--force

すでに存在するファイルを強制的に置き換えます。

--intl

libintlのソースを、intl/というサブディレクトリーにインストールします。このlibintlは、GNU libintlがインストールされていないシステムでインターナショナリゼーションを提供するのに使用されます。このオプションが省略された場合は、configure.acAM_GNU_GETTEXT呼び出しが読み込まれます。しかし‘AM_GNU_GETTEXT([external])’とインターナショナリゼーションは、GNU gettextのないシステムでは利用できないでしょう。

--po-dir=dir

POファイルを含むディレクトリを指定します。このようなディレクトリーには、特定のPOTファイルをさまざまな言語に翻訳したファイルが含まれています。このオプションは、翻訳ドメインどとに複数回指定することができます。指定されなかったときは、po/というディレクトリーが更新されます。

--no-changelog

ChangeLogの作成・更新をしません。デフォルトではgettextizeは、影響を受けるディレクトリーごとの‘ChangeLog’というファイルに、すべての変更(ファイルの追加・変更・削除)を記録します。

--symlink

必要なファイルをコピーするかわりに、シンボリックリンクを作成します。これはディスク容量を数キロバイト節約するのには便利ですが、自分自身を含む形式のtarballの作成には特別な配慮が必要になり、メンテナーがソースに適用できるいくつかの機能が使えなくなり、システムに新しいバージョンのgettextがインストールされたときにバグ(のような状態)を招きます。

-n
--dry-run

変更を出力しますが、処理は行いません。普通にgettextizeを実行したときのアクションはすべて抑止され、かわりにリストが標準出力に出力されるだけになります。

--help

このヘルプを表示して終了します。

--version

バージョン情報を表示して終了します。

directoryを指定した場合、そのディレクトリーはGNU gettextを使う準備をしたいパッケージの、トップレベルのディレクトリーになります。

プログラムgettextizeは、以下のファイルを提供します。しかし--force (-f)オプションを指定しなければ、既存のファイルは置き換えられません。

  1. ABOUT-NLSファイルは、パッケージのメインディレクトリー(トップレベル)にコピーされます。このファイルは、プログラムでNative Language Support機能をインストールして使う方法を示す主要なファイルです。もし手軽に入手できるなら、gettextizeにより提供されるABOUT-NLSよりも、新しいコピーを使いたいと思うかもしれません。より新しいABOUT-NLSファイルのコピーを、翻訳プロジェクト、またはGNU archive siteから入手することもできます。
  2. 作成されたpo/ディレクトリーには、最終的にはすべての翻訳用ファイルが保持されますが、初期状態ではGNU gettextによるpo/Makefile.in.in(ファイル名に‘.in’が2つあることに注意してください)と、いくつかの予備ファイルしか含まれていません。すでにpo/というディレクトリーがあるときは、そのディレクトリーのファイルは保持され、Makefile.in.inと予備ファイルだけが上書きされます。

    --po-dir’が指定されたときは、po/のかわりに‘--po-dir’で指定されたそれぞれのディレクトリーに配置されます。

  3. --intl’だけが指定されたときは、intl/ディレクトリーが作成され、GNU gettextintl/ディレクトリーから、ほとんどのファイルがコピーされます。--force (-f)も指定されたときは、まず最初にintl/が空にされます。
  4. ファイルconfig.rpathは、設定サポートファイルを含むディレクトリーにコピーされます。このファイルは、autoconfマクロAM_GNU_GETTEXTで必要です。
  5. プロジェクトがGNU automakeしか使っていないときは、autoconfの一連のマクロファイルが、パッケージのautoconfマクロのレポジトリー(通常はm4/というディレクトリー)にコピーされます。

シンボリックリンクがサポートされている場合、gettextizeはパッケージのディレクトリーへは実際にコピーはされず、かわりにシンボリックリンクが作成されます。これによりすべてのパッケージで必要なファイルによる重複を避けることができます。単に‘-h’オプションを指定すると、配布物のtarアーカイブを作成するときには、それらのリンクが解決されて実際のファイルが配布物のアーカイブにコピーされます。そのため、メインのMakefile.inのゴールdistにたいするtarのオプションには、‘-h’を使う必要があることを強調しておきましょう

それだけではなく、gettextizeは、影響を受ける各ディレクトリーのMakefile.amをすべて更新し、同様にトップレベルのconfigure.ac(またはconfigure.in)も更新します。

パッケージのサブディレクトリーintl/po/m4/にコピーされる、GNU gettextをサポートするための最新のファイルを理解するのも、興味深いでしょう。intl/と他の2つのディレクトリーの違いは、intl/はGNU gettextを使うすべてのパッケージで同じですが、他の2つのディレクトリーのものの大部分はパッケージに依存したものだという点です。

gettextizeプログラムは、置換または変更するファイルのバックアップを作成して、それらの変更をChangeLogに書き込みます。この方法により、注意深いメンテナーはgettextizeを実行した後に、それによる変更が許容できるか確認して、可能なら調整することができます。このルールの例外はintl/ディレクトリーで、このディレクトリーは完全に追加・置換、または削除されます。

gettextizeが、GNU gettextを使うパッケージのための調整すべてを処理できる訳ではないことを理解するのことも重要です。残っている作業の量は、パッケージがGNU automakeを使うか否かによります。それでも大抵の場合、メンテナーはgettextizeを呼び出した後、作成または変更しなければならないファイルを読む必要があるでしょう。

特に‘gettexize’を使った後は、‘AC_COMPILE_IFELSE was called before AC_GNU_SOURCE’、または‘AC_RUN_IFELSE was called before AC_GNU_SOURCE’というエラーが発生するかもしれません。このエラーはトップレベルのconfigure.acで説明している方法でconfigure.acを変更することにより修正できます。

gettextizeは、GNU build systemの一部ではないので、自動的には呼び出されず、パッケージメンテナーとしての責任を持たない人も呼び出さないことを理解しておくのも重要です。後者の目的のためには個別にツールが準備されています。詳細はautopointプログラムの呼び出しを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4 作成または変更しなければならないファイル

gettextizeにより自動的に追加されたファイルをのぞいて、GNU gettextと正常に対話するために修正が必要なファイルがたくさんあります。あなたがMakefileの設計とauto-configuration自動設定のためのGNU標準に忠実にしたがっているなら、調整は容易でしょう。ここではそれぞれについて必要な変更を順に説明します。

以下では変更が必要なファイルと、必要な変更を説明していきます。多くの例はGNU gettext 0.18.3 のディストリビューション自体か、GNU helloディストリビューション(http://www.franken.de/users/gnu/ke/helloまたはhttp://www.gnu.franken.de/ke/hello/)から引用しました。GNU gettextのソースコードとGNU helloを参照してみれば、これらのパッケージがGNU gettextの機能を使うよい例だということが納得できるでしょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.1 po/内のPOTFILES.in

ディレクトリーpo/には、POTFILES.inというファイルが必要です。このファイルは、すべてのプログラムソースの中で、翻訳が必要だとマークされた文字列をもつファイルがどれかを告げるもので、以下のような内容です:

# List of source files containing translatable strings.
# Copyright (C) 1995 Free Software Foundation, Inc.

# Common library files
lib/error.c
lib/getopt.c
lib/xmalloc.c

# Package source files
src/gettext.c
src/msgfmt.c
src/xgettext.c

#マークのコメントと空行は無視されます。それ以外の行は翻訳用にマークされた文字列を含むソースファイルをリストした行(ソース内でマークはどのように見えるかを参照してください)で、相対パスはPOTFILES.inのあるディレクトリーではなく、ディストリビューション全体のトップレベルからの相対パスです。

flexbisonのような、それ自身では翻訳可能な文字列を提供しないようなツールによりCファイルが自動生成されるときは、po/POTFILES.inには自動生成されたCファイルではなく、本当のソースファイル(flexのときは.lで終わるファイル、bisonのときは.yというファイル)を記述することをお勧めします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.2 po/内のLINGUAS

ディレクトリーpo/には、LINGUASというファイルも必要です。このファイルは利用可能な翻訳がリストされています。これは空白区切りのリストで、#マークのコメントと空行は無視されます。以下は例です:

# Set of available languages.
de fr

この例はGermanとFrenchのPOファイルが利用可能で、パッケージでは現在それらの言語がサポートされていることを意味しています。インストール時に、インストールされる言語にさらに制限をかけたいときは、ファイルLINGUASを変更するのではなく、環境変数LINGUASを使用します(インストーラーと配布者の視点を参照してください)。

LINGUASファイルには、‘en@quot’と‘en@boldquot’という"言語"を追加することをお勧めします。en@quotはEnglishのメッセージカタログ(en)の亜種で、非対称な体裁の‘`’と‘'’によるASCIIの置き換えではなく、本当のクォーテーションマークを使います。en@boldquoten@quotの亜種で、クォーテーション文字を太字のフォントで出力します。これはVT100のエスケープシーケンスをサポートする端末エミュレーター(xtermやLinuxのconsole。EmacsのM-x shellモードは該当しません)で使用されます。

これらの追加のメッセージカタログ‘en@quot’および‘en@boldquot’は、翻訳者が作成したのではなく、自動的に作成されたものです。これらのファイルをサポートするためにはpo/ディレクトリーに、Rules-quotquot.sedboldquot.seden@quot.headeren@boldquot.headerinsert-header.sinというファイルが必要です。これらのファイルは、gettextizeを実行することによりインストールされます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.3 po/内のMakevars

ディレクトリーpo/には、Makevarsというファイルもあります。このファイルには、プロジェクトで固有の変数が含まれています。po/Makevarsが作成されるときに、po/Makefileが挿入されます。そのため、変数はPOTファイルが作成・更新されたときや、メッセージカタログがインストールされたときに効果を及ぼします。

あなたのパッケージが単一のメッセージドメイン(1つのpo/ディレクトリーしかない)のときは、最初の3つの変数は変更する必要はありません。別々の場所に複数のpo/ディレクトリーをもつパッケージの場合だけ、Makevarsの最初に定義された3つの変数を調整する必要があります。

XGETTEXT_OPTIONS変数のかわりに、autoconfマクロのAM_XGETTEXT_OPTIONにより、xgettextのオプションを指定することもできます。詳細はpo.m4内のAM_XGETTEXT_OPTIONを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.4 po/内のMakefileの拡張

po/ディレクトリーの、Rules-*と呼ばれるファイルは、po/Makefileが作成されたときに追加されたファイルです。これらのファイルは、po/Makefile.in.inに干渉することなく、特定のPOファイルのMakefileにルールを追加する機会を与えてくれます。

GNU gettextには、カタログen@quot.poおよびen@boldquot.poをビルドするルールを含む、Rules-quotファイルが含まれます。en@quot.poの効果は、環境変数LANGUAGEに‘en@quot’をセットすると、クォーテーションを示す代替のASCII grave accentとASCII apostropheのかわりに、対称性をもつUnicodeの正しいクォーテーションマークが表示されることです。このカタログを有効にするには、単にen@quotpo/LINGUASに追加します。en@boldquot.poの効果は、LANGUAGEに‘en@boldquot’をセットすると、正しいクォーテーションマークが得られるだけでなく、ターミナルやコンソールで表示されるクォーテーションマークの文字に、太字フォントが使用されることです。これはGUIプログラムではなく、コマンドラインのプログラムにとってだけ便利なカタログです。po/LINGUASファイルにen@boldquotを追加するだけで、このカタログを利用できます。

同様にして、sr locale – Cyrillic文字で記述されたSerbian – から、sr@latin locale – Latinアルファベットで記述されたSerbian – のためのメッセージカタログを構築するルールを作成することができます。msgfilterプログラムの呼び出しを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.5 トップレベルのconfigure.ac

configure.acまたはconfigure.in – これはautoconfconfigureスクリプトを生成するときのソースになるファイルです。

  1. パッケージとバージョンを宣言します。

    これは以下のように宣言します:

    PACKAGE=gettext
    VERSION=0.18.3
    AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
    AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
    AC_SUBST(PACKAGE)
    AC_SUBST(VERSION)
    

    GNU automakeを使っている場合は、以下のようになるでしょう:

    AM_INIT_AUTOMAKE(gettext, 0.18.3)
    

    もちろん、パッケージ名の‘gettext’と、バージョン番号の‘0.18.3’は、あなたのパッケージの名前とバージョン番号で置き換えます。これらは配布物のパッケージされたtarのファイル名(この例ではgettext-0.18.3.tar.gz)にそのまま使用されます。

  2. インターナショナリゼーションにたいするサポートのチェック。

    以下のマクロは、インターナショナリゼーションにたいするサポートを発動するためにメインとなる、m4のマクロです。この行をconfigure.acに追加します:

    AM_GNU_GETTEXT
    

    マクロはconfigure時に多くのチェックと処理を行いますが、呼び出しは故意に単純にしています。

    gettextizeを呼び出すとき、‘--intl’オプションを指定せず、intl/を作成しない場合は、以下の呼び出しが読み込まれます:

    AM_GNU_GETTEXT([external])
    
  3. 出力ファイルの作成。

    AC_OUTPUT命令はconfigure.acファイルの最後にあり、以下の2つの方法で変更する必要があります:

    AC_OUTPUT([existing configuration files intl/Makefile po/Makefile.in],
    [existing additional actions])
    

    AC_OUTPUTの最初の引数の変更は、intl/およびpo/ディレクトリーを置き換えるための変更です。接尾辞‘.in’は、po/だけに使用されることに注意してください。これにより配布される本当のファイルはpo/Makefile.in.inであることがわかります。

    gettextizeを呼び出すとき、‘--intl’オプションを指定せず、intl/を作成しない場合は、AC_OUTPUTの行にintl/Makefileを追加する必要はありません。

必要な変更をした後は、‘aclocal -I m4’や‘autoconf’(または‘autoreconf’)などのコマンドは、以下のようなトレース情報を出力して失敗するようになります:

configure.ac:44: warning: AC_COMPILE_IFELSE was called before AC_GNU_SOURCE
../../lib/autoconf/specific.m4:335: AC_GNU_SOURCE is expanded from...
m4/lock.m4:224: gl_LOCK is expanded from...
m4/gettext.m4:571: gt_INTL_SUBDIR_CORE is expanded from...
m4/gettext.m4:472: AM_INTL_SUBDIR is expanded from...
m4/gettext.m4:347: AM_GNU_GETTEXT is expanded from...
configure.ac:44: the top level
configure.ac:44: warning: AC_RUN_IFELSE was called before AC_GNU_SOURCE

configure.acファイルの‘AC_PROG_CC’より後、かつ‘AM_GNU_GETTEXT’より前の箇所(おそらく‘AC_PROG_CC’呼び出しのすぐ近く)に、‘AC_GNU_SOURCE’の明示的な呼び出しを追加する必要があります。この順番は、GNU autoconfによる制限により必要です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.6 トップレベルのconfig.guessconfig.sub

サブディレクトリーintl/の作成を省略しない場合、配布物にconfig.guessおよびconfig.subという、GNUのファイルを追加する必要があります。これらのファイルが必要なのは、intl/ディレクトリーがlocaleの文字エンコーディングを決定するという、プラットフォームに依存したサポートを行うため、プラットフォームを識別しなければならないからです。

最新バージョンのconfig.guessおよびconfig.subを、http://savannah.gnu.org/の‘config’プロジェクトから入手できます。以下は入手するためのコマンドです

$ wget -O config.guess 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
$ wget -O config.sub 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'

バージョンは最新ではありませんが、GNU automakeとGNU libtoolパッケージにも含まれています。

config.guessおよびconfig.subは通常、配布物のトップレベルに配置されます。しかし、他の設定ファイル(install-shltconfigltmain.shmissingなど)と同様に、サブディレクトリーに配置することもできます。ファイルを移動すること以外に必要なのは、configure.acに以下の行を追加することです。

AC_CONFIG_AUX_DIR([subdir])

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.7 トップレベルのmkinstalldirs

初期のバージョンのGNU gettextでは、配布物にGNU mkinstalldirsスクリプトを追加する必要がありました。これは今では必要ありません。使用しているautomakeが、automake 1.9以降であれば削除することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.8 トップレベルのaclocal.m4

配布物にaclocal.m4ファイルがない場合、1番単純なのは、GNU gettextのサブディレクトリーm4/codeset.m4fcntl-o.m4gettext.m4glibc2.m4glibc21.m4iconv.m4intdiv0.m4intl.m4intldir.m4intlmacosx.m4intmax.m4inttypes_h.m4inttypes-pri.m4lcmessage.m4lib-ld.m4lib-link.m4lib-prefix.m4lock.m4longlong.m4nls.m4po.m4printf-posix.m4progtest.m4size_max.m4stdint_h.m4threadlib.m4uintmax_t.m4visibility.m4wchar_t.m4wint_t.m4xsize.m4を1つのファイルに結合する方法です。intl/ディレクトリーを作成しなかった場合、結合する必要があるのはgettext.m4iconv.m4lib-ld.m4lib-link.m4lib-prefix.m4nls.m4po.m4progtest.m4だけです。

GNU automake 1.8以降を使っていない場合は、もっと新しいautomakeの配布物から、上記のファイルにmkdirp.m4ファイルを追加する必要があります。

すでにaclocal.m4ファイルがある場合は、前述のマクロファイルを既存のaclocal.m4にマージする必要があります。以前にリリースされたGNU gettextからアップグレードしたようなときは、ほとんどの場合マクロ(AM_GNU_GETTEXT、... )を置き換える必要があることに注意してください。なぜならそれらのマクロは、GNU gettextがリリースされるときは通常、少し変更されるからです。これらの内容は、わたしたちが "奇妙" なシステムに出会う度に増えていくかもしれません。

GNU automake 1.5以降を使用している場合には、マクロファイルをm4/というサブディレクトリーに配置して、以下の行を追加すれば充分です。

ACLOCAL_AMFLAGS = -I m4

上記のような行を、トップレベルのMakefile.amに追加してください。

GNU automake 1.10以降を使用している場合は、さらに簡単になります。以下の行を追加してください

ACLOCAL_AMFLAGS = --install -I m4

上記のような行を、トップレベルのMakefile.amに追加して、‘aclocal --install -I m4’を実行します。これはaclocal.m4を更新する前に、必要なファイルを自動的にm4/サブディレクトリーに追加します。

これらのマクロはインターナショナリゼーションのサポート機能と関連情報をチェックします。1度うまく安定させられれば、多分これらのマクロを、標準のAutoconfに統合できるでしょう。なぜなら、これらの断片的なm4コードは、GNU gettextを使うプロジェクトでは同一だからです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.9 トップレベルのacconfig.h

初期のバージョンのGNU gettextでは、acconfig.hファイル内でENABLE_NLSHAVE_GETTEXT and HAVE_LC_MESSAGESHAVE_STPCPYPACKAGE and VERSIONを定義することが要求されました。これは今では必要ないので、パッケージがintl/ディレクトリーから独自に使用していなければ、削除することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.10 トップレベルのconfig.h.in

configureにより定義されるCマクロを保持するインクルードファイルのテンプレートを、通常はconfig.h.inと呼び、手動または自動で保守されるかもしれません。

gettextizeintl/ディレクトリーを作成している場合、ファイル名はconfig.h.inで、トップレベルになければなりません。gettextizeの‘--intl’オプションを指定しないで、intl/ディレクトリーを作成しなかったときは、ファイル名と場所は自由に選ぶことができます。

プログラム‘autoheader’を使って自動的に保守されている場合、なにも行う必要はありません。これは特にGNU automakeを使っているケースです。

手動で保守していてgettextizeintl/ディレクトリーを作成している場合は、‘autoheader’を使うように変更するべきです。intl/ディレクトリーのために追加するCマクロのリストは、手動で保守するには長すぎます。そして、このリストはGNU gettextのバージョンが異なることにより変化するのです。

手動で保守している場合で、gettextizeを‘--intl’オプションなしで呼び出したために、intl/ディレクトリーが作成されていないなら、config.h.inに以下の行を追加して"逃げる"ことができます:

/* Define to 1 if translation of program messages to the user's
   native language is requested. */
#undef ENABLE_NLS

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.11 トップレベルのMakefile.in

以下は、トップレベルにあるメインのMakefile.inファイルにたいして必要な変更です。

  1. ゴール‘dist:’が正常に動作(以降で説明します)するように、Makefile.inの最初の部分に、以下の行を追加します:
    PACKAGE = @PACKAGE@
    VERSION = @VERSION@
    
  2. 定義DISTFILESに、ファイルABOUT-NLSを追加して、このファイルが配布されるように変更します。
  3. どのサブディレクトリーのMakefile.inを処理する場合でも、サブディレクトリー‘intl’および‘po’も処理するようにしてください。Makefiles内の特別なルールは、インターナショナリゼーションが必要ない場合を処理するためのものです。

    Makefilesを使用している場合、それがautomakeにより作成されたものか、手入力されたものかにかかわらず、GNUのコーディング規約にしたがうように注意してください。新しいサブディレクトリーを処理しなければならないために影響を受けるゴールには、‘installdirs’、‘install’、‘uninstall’、‘clean’、‘distclean’が含まれます。

    以下は標準的な処理順の例です。この例ではゴール‘dist:’のために使用されるSUBDIRSを、Makefile.inの中で定義しています。

    SUBDIRS = doc intl lib src po
    

    make’の調整では、ヘッダーファイルlibintl.hを使うコードが含まれるディレクトリーより、intlディレクトリーが前にくるように注意してください。intl の前に libsrcの前にintlがあるのは、これが理由です。

  4. デリケートなポイントは、intl/Makefilepo/Makefileの両方のゴール‘dist:’が、メインのMakefileによって、後から正しいディレクトリーにセットアップされる点です。以下はゴール‘dist:’がどのようなものかという例です:
    distdir = $(PACKAGE)-$(VERSION)
    dist: Makefile
    	rm -fr $(distdir)
    	mkdir $(distdir)
    	chmod 777 $(distdir)
    	for file in $(DISTFILES); do \
    	  ln $$file $(distdir) 2>/dev/null || cp -p $$file $(distdir); \
    	done
    	for subdir in $(SUBDIRS); do \
    	  mkdir $(distdir)/$$subdir || exit 1; \
    	  chmod 777 $(distdir)/$$subdir; \
    	  (cd $$subdir && $(MAKE) $@) || exit 1; \
    	done
    	tar chozf $(distdir).tar.gz $(distdir)
    	rm -fr $(distdir)
    

GNU automakeを使っているときは、Makefile.amからMakefile.inが自動的に生成されますが、Makefile.amに必要な修正は、‘gettextize’の実行よって修正済みであることに注意してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.12 src/内のMakefile.in

メインのMakefile.inで行ったいくつかの修正は、あなたのパッケージソースのMakefile.in(ここではsrc/サブディレクトリーにあると仮定します)でも必要です。以下は、src/Makefile.in内で必要な修正のすべてです:

  1. ゴール‘dist:’を考慮して、src/Makefile.inの先頭の部分に以下の行が必要になります:
    PACKAGE = @PACKAGE@
    VERSION = @VERSION@
    
  2. まだ定義されていなければ、top_srcdirを定義する必要があります。これはcppのインクルードファイルのための定義で、以下の行を追加するだけです:
    top_srcdir = @top_srcdir@
    
  3. 後ですべてのMakefile.inで、一様なのゴール‘dist:’とするために、subdirを‘src’と定義したいと思うかもしれません。以下は、このゴール‘dist:’のために必要な定義です:
    subdir = src
    
  4. 以下のようにプログラムのmain関数は通常、bindtextdomain(gettext処理のトリガーを参照してください)を呼び出します:
    bindtextdomain (PACKAGE, LOCALEDIR);
    textdomain (PACKAGE);
    

    プログラムにLOCALEDIRを知らせるために、以下の行をMakefile.inに追加します(Autoconfのバージョン2.60以降の場合):

    datadir = @datadir@
    datarootdir= @datarootdir@
    localedir = @localedir@
    DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
    

    Autoconfのバージョンが2.60より古い場合は、以下の行を追加します:

    datadir = @datadir@
    localedir = $(datadir)/locale
    DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
    

    @datadir@のデフォルトは‘$(prefix)/share’なので、$(localedir)のデフォルトは、‘$(prefix)/share/locale’になることに注意してください。

  5. あなたは最後のリンクで、ライブラリーとして@LIBINTL@または@LTLIBINTL@が使われることを保証する必要があります。@LIBINTL@libtoolなしで使用され、@LTLIBINTL@libtoolとともに使用されます。これを達成するには、以下のようにこれらをLIBSで管理します:
    LIBS = @LIBINTL@ @LIBS@
    

    GNU gettextでインターナショナライズされたパッケージには、ヘルパー関数を含むライブラリーを、ディレクトリーlib/にビルドするものがたくさんあります(少なくともGNU gettextライブラリー自身が必要とするいくつかの関数が必要です)。しかしlib/の中の関数のいくつかは、ユーザーに翻訳が必要なメッセージをあたえる関数です。これに注意してサポートのためのライブラリー (libsupport.aとしましょう)を、上記の例の@LIBINTL@@LIBS@の前に配置します:

    LIBS = ../lib/libsupport.a @LIBINTL@ @LIBS@
    
  6. あなたは、あらゆる状況において、ディレクトリーintl/が、Cプリプロセッサーに検索されることも保証する必要があります。そのためには、‘-I../intl’と‘-I$(top_srcdir)/intl’の両方がCコンパイラーに与えられるように管理する必要があります。
  7. ゴール‘dist:’は、他のものと一致している必要があります。以下はそのための合理的な定義です:
    distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
    dist: Makefile $(DISTFILES)
    	for file in $(DISTFILES); do \
    	  ln $$file $(distdir) 2>/dev/null || cp -p $$file $(distdir) || exit 1; \
    	done
    

GNU automakeを使用している場合、Makefile.inMakefile.amから自動的に生成されるので、最初の3つと最後の変更は必要ないことに注意してください。Makefile.amに必要な変更は以下になります:

  1. プログラムにLOCALEDIRを知らせるために、特定のモジュールにたいしては以下の行を:
    <module>_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
    

    またはコンパイル単位については以下のようにMakefile.amに記述します。

    AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
    

    これはすべてのモジュール、またはコンパイル単位のためのものです。さらにAutoconfのバージョンが2.60より古いものを使用している場合、以下の行を追加して‘localedir’を定義します:

    localedir = $(datadir)/locale
    
  2. 最後のリンクが@LIBINTL@または@LTLIBINTL@を使うことを保証するために、以下をMakefile.amに追加します:
    <program>_LDADD = @LIBINTL@
    

    特定のプログラムごとには上記のように記述します。

    LDADD = @LIBINTL@
    

    これはすべてのプログラムの場合です。プログラムのリンクにlibtoolを使うときは、プログラム用に@LIBINTL@ではなく、@LTLIBINTL@を使う必要があることを忘れないでください。

  3. intl/ディレクトリーがあり、その内容がgettextizeにより作成されたものである場合は、以下のような行をMakefile.amに追加して、すべての状況において、Cプリプロセッサーがインクルード ファイルをそこから検索することを保証するようにしてください:
    AM_CPPFLAGS = -I../intl -I$(top_srcdir)/intl
    

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.4.13 lib/内のgettext.h

GNU gettextにより提供される、パッケージのインターナショナリゼーションはオプションであり、2つの状況でオフに切り替えることが考えられます:

Cプリプロセッサーのマクロは、これら2つのケースを検知するのに使用できます。通常、libintl.hが見つかって、明示的に利用不可されていなければ、autoconfが設定ファイルを生成するときに、ENABLE_NLSマクロが1に定義されます。しかし上記以外の状況では、このマクロは定義されず、それゆえCでは0に評価されます。

gettext.hは、ENABLE_NLSマクロにもとづいて<libintl.h>を使用する、便利なヘッダーファイルです。ENABLE_NLSがセットされていると、<libintl.h>がインクルードされ、セットされていない場合はlibintl.h関数のために代用のno-op(訳注: no-op = no operation = 何もしない)が定義されます。わたしたちは直接<libintl.h>を使うのではなく、"gettext.h"を使うことを推奨します。そうすれば古いシステムへの可搬性が保証され、もし望むならインストーラーでインターナショナリゼーションをオフにできます。

#include "gettext.h"

Cのソースコードは下記の行を、上記のように書き換えます(訳注: 下が修正前で、上が修正後です。通常とは逆の順序で説明しているので間違えないでください)。

#include <libintl.h>

gettext.hの場所は通常、補助のインクルードファイルを含んだディレクトリーです。多くのGNUパッケージには、ヘルパー関数を含むlib/ディレクトリーがあるので、gettext.hはそこに配置すればよいでしょう。他のパッケージでは、srcディレクトリーに配置することができます。

gettext.hをパブリックな場所にインストールしないでください。このファイルを必要とするすべてのパッケージは、パッケージ自身にそのファイルのコピーが含まれているからです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.5 configure.ac内でのautoconfマクロの使用

GNU gettextは、パッケージのconfigure.ac(またはconfigure.in)で使用されるマクロをインストールします。詳細については、Introduction in The Autoconf Manualを参照してください。その中でも主要なマクロは、もちろんAM_GNU_GETTEXTです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.5.1 gettext.m4内のAM_GNU_GETTEXT

AM_GNU_GETTEXTマクロは、Cライブラリーおよびlibintlライブラリー(どちらも共有または静的なライブラリーをサポートしています)に分割されたGNU gettextの関数ファミリー、またはパッケージのintl/ディレクトリーをテストします。このマクロは、ビルド用にパッケージのpo/ディレクトリーを準備するのに、AM_PO_SUBDIRSも呼び出します。

AM_GNU_GETTEXTは、オプションの引数を3つ指定でき、一般的な書式は以下のようになります

AM_GNU_GETTEXT([intlsymbol], [needsymbol], [intldir])

intlsymbolには、‘external’または‘no-libtool’が指定できます。デフォルト(指定されなかったとき、または空のとき)は、‘no-libtool’です。intl/ディレクトリーのないパッケージでは、intlsymbol に ‘external’ を指定する必要があります。intl/ ディレクトリーのあるパッケージでは、intlsymbolに‘no-libtool’を指定することもできるし、‘external’を指定して、他の場所でマクロAM_GNU_GETTEXT_INTL_SUBDIRを使用することにより、それをオーバーライドすることもできます。このintl/の実体を指定する2つの方法は、同じことを行います。どちらもビルド時には、静的なライブラリー$(top_builddir)/intl/libintl.aを作成します。

needsymbolに‘need-ngettext’が指定されると、ngettext()をもたない(libcまたはlibintlの)GNU gettext実装は無視されます。needsymbolに‘need-formatstring-macros’が指定されると、ISO C 99 <inttypes.h>書式文字列マクロをサポートしないGNU gettext実装は無視されます。needsymbolだけを指定することもできます。他の場所でAM_GNU_GETTEXT_NEEDを指定することでも、これらの指定を満たすことはできます。1つ以上指定したときは、もっとも強い指定が使用されるか、AM_GNU_GETTEXT_NEEDマクロを複数回呼び出します。これらの指定は、‘need-formatstring-macros’が‘need-ngettext’を含むような階層になっています。

intldirは、intlを探すのに使用されます。空の場合は、‘$(top_builddir)/intl/’という値が使用されます。

AM_GNU_GETTEXTマクロは、GNU gettextが利用可能で、使用できるかどうかを決定するマクロです。利用できる場合は、変数USE_NLSに‘yes’をセットし、これはautoconfが生成する設定ファイル(通常はconfig.hというファイル)のENABLE_NLSに1を定義し、Makefileで使用される変数LIBINTLLTLIBINTLにリンカーオプションをセットし(LIBINTLはlibtoolなしのときで、LTLIBINTLはlibtoolを使用するとき)、必要なときはCPPFLAGSのオプションに‘-I’を追加し、利用できない場合はUSE_NLSに‘no’をセットし、LIBINTLLTLIBINTLを空にセットして、CPPFLAGSを変更しません。

AM_GNU_GETTEXTが対処する複雑さは、以下のようなものです:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.5.2 gettext.m4内のAM_GNU_GETTEXT_VERSION

AM_GNU_GETTEXT_VERSIONマクロは、パッケージで使用するGNU gettextインフラストラクチャーのバージョン番号を宣言します。

このマクロの使用はオプションで、これを使用するプログラムはautopointだけです(CVSによる統合を参照してください)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.5.3 gettext.m4内のAM_GNU_GETTEXT_NEED

AM_GNU_GETTEXT_NEEDマクロは、GNU gettextの実装に関する制約を宣言するもので、構文は以下のようになります

AM_GNU_GETTEXT_NEED([needsymbol])

needsymbolに‘need-ngettext’を指定した場合、ngettext()関数をもたない、(libcまたはlibintlの)GNU gettext実装は無視されます。needsymbolに‘need-formatstring-macros’を指定した場合、ISO C 99 <inttypes.h>の書式文字列マクロをサポートしないGNU gettext実装は無視されます。

AM_GNU_GETTEXTの2番目のオプション引数も考慮されます。

AM_GNU_GETTEXT_NEED呼び出しは、AM_GNU_GETTEXT呼び出しの前後どちらでもよく、順番は関係ありません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.5.4 intldir.m4内のAM_GNU_GETTEXT_INTL_SUBDIR

AM_GNU_GETTEXT_INTL_SUBDIRマクロは、AM_GNU_GETTEXTの最初の引数に‘external’を指定して呼び出した場合でも、ビルドのためにintl/サブディレクトリーも参照します。

AM_GNU_GETTEXT_INTL_SUBDIR呼び出しは、AM_GNU_GETTEXT呼び出しの前後どちらでもよく、順番は関係ありません。

このマクロはGNU automake 1.10以降、またはGNU autoconf 2.61以降で使用できます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.5.5 po.m4内のAM_PO_SUBDIRS

このマクロはC、C++、Objective C以外のプログラム言語(例: shPythonLisp)による、インターナショナライズされたプログラムで使う必要があります。PO ファイルによるローカリゼーションをサポートするプログラム言語のリストは、その他のプログラミング言語を参照してください。

AM_PO_SUBDIRSマクロは、インターナショナリゼーションを使う必要があるかを決定します。使う必要がある場合にはUSE_NLS変数に‘yes’をセットし、必要ない場合には‘no’をセットします。このマクロは、各po/ディレクトリーのMakefileの変数にたいする適切な値も決定します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.5.6 po.m4内のAM_XGETTEXT_OPTION

AM_XGETTEXT_OPTIONマクロは、パッケージのpo/ディレクトリーでのxgettext呼び出しで使用する、コマンドラインオプションを登録するマクロです。

たとえば、‘error_at_line’という関数を定義しているソースファイルがあり、その関数の5番目の引数には、書式文字列を指定する場合には、以下のように使うことができます

AM_XGETTEXT_OPTION([--flag=error_at_line:5:c-format])

これは、この関数の5番目の引数にたいする‘gettext’呼び出しにたいして、これを翻訳可能な‘c-format’の文字列だとマークするよう、xgettextに指示します。

xgettextに指定できるオプションのリストは、xgettextプログラムの呼び出しを参照してください。

このマクロの使用は、po/Makevarsの中の‘XGETTEXT_OPTIONS’変数の代用となります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.5.7 iconv.m4内のAM_ICONV

AM_ICONVマクロは、Cライブラリー(またはiconvライブラリーに分離された)POSIX/XSI iconv関数が提供されているかテストするマクロです。もし見つかったときはam_cv_func_iconv変数に‘yes’をセットし、autoconfが生成する設定ファイル(通常はconfig.hというファイル)のHAVE_ICONVに1を定義し、iconv()の2番目の引数の型が‘const char **’または‘char **’で定義さされているかにより、ICONV_CONSTに‘const’または空を定義し、Makefileの中で使用されるリンカーオプションの変数LIBICONVおよびLTLIBICONVをセット(LIBICONVはlibtoolなしのとき、LTLIBICONVはlibtoolありのとき)、必要ならCPPFLAGSのオプションに‘-I’を追加します。見つからなかったときは、LIBICONVおよびLTLIBICONVに空をセットして、CPPFLAGSを変更しません。

AM_ICONVが対処する複雑さは、以下のようなものです:

gettext.m4が依存しているので、iconv.m4はGNU gettextの一部として配布されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.6 CVSによる統合

多くのプロジェクトでは分散開発におけるバージョンコントロールとソースのバックアップにCVSを使用しています。このセクションではcvsgettextizeautopointautoconfの使用をどのように管理するかについてのアドバイスを与えます


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.6.1 分散開発におけるバージョンミスマッチを避ける

複数の開発者によるCVSを使ったプロジェクト開発では、gettextの新しいバージョンにアップグレードしたいと望む一人の開発者が、gettextizeを実行して作成または変更しなければならないファイルにリストした変更をほどこした後に、その変更をCVSにコミットするようなことが時折あります。

プロジェクトのすべての開発者が、パッケージのGNU gettextに、同じバージョンのものを使用することを強く推奨します。別の言い方をすると、gettextizeを実行したら、開発者はプロジェクト全体と同じ方法で必要な変更をほどこしてCVSにコミットする必要があります。さもないと以下のような損傷が発生します:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.6.2 CVSバージョンコントロールの配下に置くファイル

CVSレポジトリーのコンテキストで作成されるファイル、たとえばconfigure.acにより生成されるconfigureparser.yから生成されるparser.cgettextizeautopointにより自動インストールされるpo/Makefile.in.inのようなファイルを取り扱うには、基本的に3つの方法があります。

  1. 生成されるすべてのファイルを、常にレポジトリーにコミットする。
  2. 生成されるすべてのファイルを、時々(たとえば毎リリースごとに)レポジトリーにコミットする。
  3. 生成されるファイルを、レポジトリーにコミットされない。

これら3つの方法には、それぞれ異なる利点と欠点があります。

  1. 1番目の方法の利点は、誰でもCVSからその時点で動作するビルドをチェックアウトできる点です。欠点は以下のとおりです:
    1a メンテナーによる頻繁な"cvs commit"操作が必要です。
    1b レポジトリーサイズの増加が早くなります。
  2. 2番目の方法の利点は、誰もがチェックアウトでき、通常は"./configure; make"は動作します。欠点は以下のとおりです:
    2a レポジトリーからチェックアウトした人のPATHにGNU automake、GNU autoconf、GNU m4のようなツールがインストールされている必要があり、ときには特定のバージョンが必要になる。
    2b リリース版が作成されて生成されるファイルもコミットされた後に他の開発者が"cvs update"を行うと、生成されるファイルで競合が発生する点。この競合は簡単に解決できますが、煩わしいものです。
  3. 3番目の方法の利点はメンテナーの作業負荷が軽減されることです。欠点はレポジトリーからチェックアウトした人のPATHにGNU automake, GNU autoconf, GNU m4のようなツールがインストールされている必要があるだけではなく、"./configure; make"をできるようになる前に、パッケージ固有のpre-build(ビルド前)ステップが必要になることです。

1番目と2番目の方法では、変更されたファイルや、gettextize呼び出しにより生成・更新されたファイルは、CVSにコミットする必要があります。

3番目の方法では、gettextizeが"コピー"するすべてのファイルを、CVSレポジトリーから除外できます。そのかわりにconfigure.ac(またはconfigure.in)を、以下のような形式で記述します

AM_GNU_GETTEXT_VERSION(0.18.3)

さらにパッケージのpre-buildスクリプトに‘autopoint’呼び