最初の一歩2020/12/13に公開2024/10/245件LinuxshellUNIX翻訳gettexttech要約あなたのプログラムや文書をいろんな国のひとに使ってもらえる可能性が増える方法として国際化(i18n)[1]がある。worldレベルのshellスクリプトをgettext.sh使って国際化する方法を書いている。repositoryも用意している。はじめにシェルスクリプトは、多くのひとに使われています。自分や他人のために自動化スクリプトを書いたひとはいるでしょう。最近はありがたいことにUTF-8のシステムが増えて、日本語など英語以外の言語でも、コンピュータ上で表示しやすくなりました。コンピュータ上で複数の言語を扱うにはいくつか方法があります。その中でメジャーな実装の1つが、gettextです。プログラマが新しく言語を覚えたいときはまず環境構築をします。出力するプログラムを書くことがあります。scriptを例に文章を書きます。gettextはプログラムが出力する言語を切り替えるために使われてきました。使って文書の翻訳に使う例もあります。技術文書のように頻繁に更新され翻訳が追いつかない部分は英語でいいから把握したいというニーズに応えます。最初「ssftはいいぞ」という文章を書きたかったのですが、その前提となるgettext.shについて自分にとってわかりやすい文章がなかったので書きました。gettextを扱えるひとが増えて、より多くの優れたソフトウェアや技術文書が言語のカベを越えて流通することで自分もそれにあやかりたい。文書を書いて公開することで、より詳しい人からツッコミを入れてもらい自分の理解を深めるためです。この文章はだれ向けか自分の書いたプログラムが、自分の母語を越えて利用されるプログラマ、または、自分の書いたプログラムを母語以外のひとにも使ってほしいプログラマ向けです。使えるのは日常的にシェルスクリプトを書いている人で、複数の言語への対応をしたいと考えている人です。例題はシェルスクリプトですが、gettextにおける作業手順について他のプログラム言語でgettextを扱うとき応用ができるように書きます。この文書の読み方この文書は、読んだ人が手を動かして追体験ができるように、下記の順番で進めます。比較的冗長に書くので、読者の側で分かっている部分については飛ばして読んで下さい。具体的には、先に仕組みや説明を知りたいひとは実践している部分は飛ばして、背景を読んでから戻ってくるのもいいでしょう。GNU/Linux上での環境設定gettext.shの説明をしてリポジトリのクローンをして、プログラムが動くのを確認します。その背景の説明をします。環境設定この文章を試すのに必要なパッケージは、gettextgitです。その他のプログラムはご自分でお好きに選んでください。Debian標準はdashをshとして使っているのでdashを利用しますが、たぶんbashでも動くでしょう。bullseye/sidです。gettextは充分に古いので、他のUnix系でも何らかの方法でパッケージなどがあるでしょう。私はすでにgettextをパッケージで導入していたので、gettext-baseが入っていました。gettext.shがどのパッケージにあるのか確認する方法は下記です。gettextを参考に入れて下さい。ドキュメントはお好みでofflineでも参照できる文書が欲しい派なのでわたしは入れています。cloneしてください。コマンドが生成したものを1、msginitコマンドが生成したものを2という風に変化を見るべく置いていました。こんにちは世界こんにちは世界と、表示されます。LANGが、ja_JP.UTF-8に設定してあるからです。./hello.shを実行してください。Worldと表示されているでしょうか。日本語がUTF-8でない環境の人は、異なるエンコードでファイルを作成してみるのもいいでしょう。日本語と英語以外を追加してみるのもいいでしょう。World"プログラムなので簡単です。その前の各種設定についての説明が主体となります。2023-01-20にgettextを生で使うのから、eval_gettextを使うようにサンプルを変更した。コメントで指摘していただきありがとうございました。おかげで私の理解が進みました。World"`"1行め:実行内容をトレースしながら動け4行め:おまじない7行め:実行プログラム名などを入れる。翻訳の入ったmoファイル名でもあります。10行め:どこにmoファイルを置くlocaleディレクトリが存在しているか。絶対ディレクトリで指定します。pwdコマンドが効いてきます。13行め:eval_gettextに文字を渡して、翻訳した結果を受け取ります。echoで改行してます。14行め:echoを先に書きたい派の人はこっちを使います。この段階では、13行めと14行めの書き方は好みの範囲です。変数が関係するとエスケープの個数を変化させる必要があります。いまはこれ以上踏み込みません。ここまでで、やりたいことの半分が達成できました。後の半分は、ご自分で別のサンプルプログラムを作って実践をお願いします。scriptから、翻訳すべき文字列を取り出す。指定がなければmessage.poファイルを生成する。msginitコマンドで、ロケール情報、扱う文字列のエンコード情報などの情報をあたえて、日本語で指定がないなら、ja.poファイルを生成する。好きなエディタで、poファイルを編集する。翻訳ができあがったらmsgfmtコマンドでmoファイルを生成します。その時ファイル名はTEXTDOMAINと合わせること。moファイルができたらつぎのようにします。TEXTDIMAINDIRで指定されているpwd/localeを起点として、ja(地域と同じ)のディレクトリ配下にLC_MESSAGESのディレクトリがあることを確認します。英語圏ならjaの代わりにenです。フランス語ならfrです。同一地域で複数言語ならbn_ID,bn_BDになるのでしょう。en@arabicのような表記については不勉強なのですいませんがわかりません。pwd/local/ja/LC_MESSAGES/ファイルをコピーします。プログラムを作っているプロジェクトの構成に応じて、もっと柔軟に変更できる例を出すことができるといいのですが。プログラムを開発していくと表示するメッセージが増えたり、減ったりするのも普通にあります。対象となるプログラムファイルが単一だとも限りません。上記については別の機会に書きたいです。いまでも充分長い文章なので。gettextとはロケール(Locale)にしたがって、日本語、英語など複数の言語を表示するしくみです。Unix系のOSであれば、localeにしたがって画面に表示する文字を切り替えることができます。わたしの環境では、下記のように表示します。$LANGja_JP.UTF-8いま見てもらったのは、端末(Terminal)で、日本語入力や表示をする仕組みの一部です。書いたプログラムにgettextを適用し、先ほど見たLANG環境変数によって表示する文字列を切り替えます。英語から日本語のように。ちなみに、先ほどのLANGにCを代入することで、一時的に文字列を英語にして、プログラムでパースしやすくするというテクニックをご存知のひとも多いでしょう。日本語を扱う[3]場合には、最近のUnix系システムでは、UTF-8というエンコード[4]を使っています。日本という地域の日本語をUTF-8エンコードで扱います。いう宣言をしています。地域によっては、小数点がdotだけでなくcommaのことがあります。数字の区切りが3桁や4桁、それ以外など異なっています。このように元が同じデータであっても、その地域に応じた表示を必要とします。gettextは、そのうち表示文字について翻訳する部分を担当しています。gettextizeと呼びます。技術者の間では、会話の情報密度をあげるのに複数のことがらを1つにまとめる言葉を専門用語として使っていることがあります。使う手順gettextを適用するオリジナルのプログラムを作ったり、見つけて改変します。どのように改変するかは、後述します。xgettextコマンドで翻訳対象とする文字列が入ったファイル、(指示をしなければ)message.poファイルを作成するmsginitコマンドで前述のmessage.poファイルを入力とし、コマンドラインから取得した情報を入れてja.poなどのファイルとして出力します。[5]このプログラムを使うと手で書く部分が減って間違いが減ります。ja.poを慣れているエディタで開いて翻訳します。多くのエディタ(vimやEmacsなど)はpoファイルを編集するのに便利な機能を提供しています。余裕があれば調べておくと良いでしょう。人間が読みやすいja.poファイルから、msgfmtコマンドを用いて、gettextプログラムが扱いやすいmoファイル形式へ変更します。生成された、既定のファイルをプログラムが読み取る場所にコピーします。fooが翻訳対象になり、LANGの値によって書き換わります。messages.poを生成します。プログラムの開発が進むと表示すべき文字列の増減や変更はしばしばあります。その変更に追従するためgettextコマンドを実行する必要があります。やって翻訳内容を追従させるのです。いくつか書く必要があるオプションを書き出します。"shell"を渡します。これはmanからの引用なので、ソースコードは確認していません。入力ファイルやディレクトリを指定するオプション出力ファイルやディレクトリを指定するオプション。default-domainはそのプログラム名、またはプロジェクト名の概念なので、インターネットのドメインと取り違えないように。(調べて書く必要がある)コメントどのように使うかは例示がいるか。msgidに不具合があったときの連絡メールアドレスを設定する。パッケージの概念や、バージョニングの概念自体はどういう風にするかは裁量があるのだろう。翻訳による著作権の話は発生する。プログラミングから翻訳まで全部同一人物でやるなら、なんら問題はない。問題となる前に対処して置くのがいいでしょう。翻訳はすべてソースコードと矛盾しないオープンソースなライセンスにするなどです。