4 # 本スクリプトは po4a の cfg ファイルと対応する Makefile を自動生成します。
5 # これに伴って関連ファイルも自動生成します。処理にあたっては original ディ
6 # レクトリ配下に original/man[0-9n]/* という、翻訳対象のオリジナル man ページ
10 # po4a{,/man[0-9n]}/<package name>.cfg:
11 # po4a の cfg ファイル (上書き生成)
12 # Makefile: cfg ファイルを処理する Makefile (上書き生成)
13 # translation_list.tmp:
14 # translation_list 相当の初期テンプレートファイル
16 # po4a/add_ja/copyright/man[0-9n]/<manpage name>.[0-9n].txt:
17 # いわゆる"copyright"ファイル (上書きはしない)
18 # def.mk: パッケージ情報を提供するためのファイル
19 # 非存在時にはエラー終了しテンプレートを生成する。
20 # テンプレート内容を適切に書き換えて再実行する。
23 # 翻訳パッケージディレクトリ (jm.git/manual/<package name>) にて実行。
24 # (manual ディレクトリと同列の support ディレクトリに本スクリプトを配置
25 # しており、相対パスで本スクリプトを実行することを前提とする)
27 # $ cd jm.git/manual/<package name>
28 # $ ../../support/genmancfg.sh [options]
30 # オプションは genmancfg.sh -h の出力を参照してください。
31 # ほとんどのオプションは、処理に必要となる名称等を指定するものです。
32 # その中で重要なものが -m または -o であり、これは処理タイプを指定します。
36 # 処理にあたっては二種類の po4a 処理タイプに対応します。
37 # デフォルト(-m, -o の未指定時) は -m (multi) です。
38 # 常時これにしておいて (オプション未指定で) 問題はありません。
40 # これを用いる必要があるケースとして upstream がたった一つの po ファイルを
41 # 提供していることがあり、それと同調して(upstream への提供も考慮して)
42 # たった一つの po ファイルとしたい場合に -o (one) を指定します。
45 # 1つめは処理タイプ one (オプション -o 指定時) です。
46 # original ディレクトリ配下の man ページソースに対応づく ja.po を1つだけ作るタイプです。
48 # (top) --+--original--+--man1
51 # +--po4a--+--<package name>.cfg
52 # +--<package name>.pot
56 # 2つめは処理タイプ multi (オプション -m 指定時; オプション未指定時の
58 # original ディレクトリ配下のサブディレクトリ構造 (man1, man3 など) に合わせて
59 # そのサブディレクトリごとに man1/ja.po, man3/ja.po などを分割して作るタイプです。
61 # (top) --+--original--+--man1
64 # +--po4a--+--man1--+--<package name>-man1.cfg
65 # | +--<package name>-man1.pot
67 # +--man3--+--<package name>-man3.cfg
68 # | +--<package name>-man3.pot
70 # +--man5--+--<package name>-man5.cfg
71 # +--<package name>-man5.pot
78 THISTOOL=`basename $0`
80 # 処理タイプを表す変数 TYPE に multi をデフォルト設定する。
81 # これはオプション引数 -m の指定時に採用されるタイプである。
82 # オプション引数 -o の指定時には one が設定される。
85 # オプション -h 指定時のヘルプ表示(関数)
87 echo "Usage: genmancfg.sh [options]"
88 echo " Create po4a config file as TYPE as follows, in po4a directory."
89 echo " This requires the original man sources under the \"original\" directory."
92 echo " -o: TYPE=one; for creating only one po file."
93 echo " -m: TYPE=multi; for creating po files per man sections [default]."
94 echo " -n STR: name of the package [default: basename of the current directory]."
95 echo " -d STR: release date of the package [default: \"YYYY/MM/DD\"]."
96 echo " -v STR: version of the package [default: \"x.xx\"]."
97 echo " -u STR: user name [default: git config --get user.name if exists]."
98 echo " -e STR: email address [default: git config --get user.email if exists]."
99 echo " -U "STR,..": list of commands untranslated [default: ""]."
100 echo " -h: print this help."
105 # PACKAGE_NAME: パッケージ名
106 # PACKAGE_VER: パッケージバージョン
107 # PACKAGE_DATE: パッケージのリリース日付 ("YYYY/MM/DD" 形式)
108 # これらは def.mk ファイル内に同名変数定義が行われていれば、それを参照して定める。
109 # def.mk ファイルが存在しない場合、def.mk のひながたファイルを出力して終了する。
110 # 上の設定値はそれぞれ、オプション -n (パッケージ名)、-v (バージョン)、-d (リリース
112 if test -f def.mk; then
113 PACKAGE_NAME=`grep "PACKAGE_NAME" def.mk | sed -e "s/.*[ ]*=[ ]*\(.*\)$/\1/"`
114 PACKAGE_VER=`grep "PACKAGE_VER" def.mk | sed -e "s/.*[ ]*=[ ]*\(.*\)$/\1/"`
115 PACKAGE_DATE=`grep "PACKAGE_DATE" def.mk | sed -e "s/.*[ ]*=[ ]*\(.*\)$/\1/"`
117 echo "Error: def.mk not found so newly created;"
118 echo " process again after editting it correctly."
120 PACKAGE_NAME = sample_package
121 PACKAGE_VERSION = x.xx
122 PACKAGE_DATE = YYYY/MM/DD
127 # 当プロジェクトで用いている copyright ファイルに、ユーザー名とメールアドレス
128 # を書き入れるため、そのデフォルト値を git config の user.{name,email} から設定する。
129 # git config から取得できなかった場合は、それぞれ "TRANSLATOR NAME", "EMAIL@ADDRESS"
130 # とする。これはオプション -u (user name), -e (email address) により指定できる。
131 # (なおメールアドレスが正しい書式を有しているかどうかは確認しない。)
132 # これらは translation_list の出力項目にも利用する。
133 USERNAME=`git config --get user.name 2>/dev/null || echo "TRANSLATOR NAME"`
134 EMAILADDR=`git config --get user.email 2>/dev/null || echo "EMAIL@ADDRESS"`
136 # po4a cfg の "-o untranslated=xxxxxxx" に指定したいコマンドを
137 # オプション -U によって指定できるようにしているため、そのオプション値を
138 # 保持するための以下の変数 UNTRANS_INIT をここで初期化する。
139 # 下述の $OPT 処理文の中で、オプション -U が指定されていれば設定される。
140 # roff コマンドの先頭のピリオドは省く。複数指定する場合はカンマで区切る。
141 # 指定方法を誤ってもエラー処理は行わない。po4a 処理においてエラーとなるのみ。
144 # オプション引数を走査して、前述までの各変数を定める。
145 # 処理タイプは、変数 TYPE に対応値 (one か multi か) を設定する。
146 # オプション -h 指定時はヘルプ表示、無効なオプション指定時はエラーとする。
147 while getopts :omn:d:v:u:e:U:h OPT; do
151 n) PACKAGE_NAME="$OPTARG";;
152 d) RELEASEDATE="$OPTARG";;
153 v) VERSION="$OPTARG";;
154 u) USERNAME="$OPTARG";;
155 e) EMAILADDR="$OPTARG";;
156 U) UNTRANS_INIT="$OPTARG";;
158 *) echo "Illegal option: $OPT"; exit 1;;
162 # original ディレクトリ配下に original/man[0-9n] のようなサブディレクトリが
163 # 存在するかどうかをチェックする。この構成でなければエラー終了する。
164 if ! ls original/man[0-9n] >/dev/null 2>&1; then
165 echo "Error: Not exists the original directory or"
166 echo " not contains man[0-9n] subdirectories."
170 # カレントディレクトリ直下に po4a ディレクトリ生成
173 # po4a cfg ファイル内の各処理行に対するオプション指定追加処理
174 # $d, $f, $CFG_NAME などの変数は、上位処理のものを用いる。
175 # $d: man ページディレクトリ名; man1, man3 など。
176 # $f: man ファイル名; gcc.1, acl_check.3 など。
177 # $CFG_NAME: 出力 cfg 名; gcc-man1.cfg など。
180 # (1) groff_code=verbatim 処理
182 # "-o groff_code=verbatim" を宣言すべき roff コマンド候補リストを定義する。
183 # (grep に直接受け渡すため、各コマンド(先頭ピリオド除く)を | (縦棒) で区切る。)
184 GROFF_CANDIDATES="de|ie"
186 # 上のコマンド候補リストがカレントな man ファイルに含まれているか
187 # どうかを grep 検索し、該当していれば cfg ファイルに
188 # "-o groff_code=verbatim" の宣言を出力する。
189 grep "^\.[$GROFF_CANDIDATES]" original/$d/$f >/dev/null 2>&1
190 if test $? -eq 0; then
191 echo -ne " \\\\\n\topt:\"-o groff_code=verbatim\"" >> $CFG_NAME
196 # "-o generated" を宣言すべき記述候補リストを定義する。
197 GENERATED_CANDIDATES=(
199 "DO NOT MODIFY THIS FILE"
201 "Man page generated from reStructuredText."
202 "Automatically generated by Pod::Man"
203 "\.\\\\\"Text automatically generated by"
206 # 上の記述候補リストのそれぞれがカレントな man ファイルに
207 # 含まれているかどうかを順に grep 検索して、含まれていれば cfg ファイルに
208 # "-o generated" の宣言を出力する。
210 for m in "${GENERATED_CANDIDATES[@]}"; do
211 grep "$m" original/$d/$f >/dev/null 2>&1
212 if test $? -eq 0; then
216 if test $GENERATED -eq 1; then
217 echo -ne " \\\\\n\topt:\"-o generated\"" >> $CFG_NAME
220 # (3) untranslated 処理
222 # "-o untranslated" を宣言すべきコマンド候補リストを定義する。
223 UNTRANS_CANDIDATES="\.\. \.\\\\} 'br\\\\} \.als \.bP \.cp \.de1 \.do \.el \.el\\\\{. \.FT \.ie \.INDENT \.LI \.MTO \.NE \.NOP \.NS \.PE \.PS \.Quoted \.rm \.rr \.Sp \.Vb \.UNINDENT \.Ve \.Xw"
225 # 上のコマンド候補リストのそれぞれがカレントな man ファイルに
226 # 含まれているかどうかを順に grep 検索して、含まれていれば cfg ファイルに
227 # "-o untranslated=XX,YY,ZZ,..." の宣言を出力する。
229 for u in $UNTRANS_CANDIDATES; do
231 grep "^$u" original/$d/$f >/dev/null 2>&1
232 if test $? -eq 0; then
233 if test -z "$UNTRANS"; then
234 UNTRANS="\\\\\n\topt:\"-o untranslated="
238 CMD=`echo $u | sed "s/^\\\\\.//g"`
239 if test "$CMD" = "\."; then
243 \'br\\*) CMD=`echo $CMD\' | sed "s/^\'//"`;;
247 UNTRANS="$UNTRANS$CMD"
251 # オプション引数 -U によりコマンドラインから untranslated 対象が指定されて
252 # いれば "-o untranslated=" 行に追加する。
253 if test "$UNTRANS_INIT" != ""; then
254 if test -z "$UNTRANS"; then
255 UNTRANS="\\\\\n\topt:\"-o untranslated="
259 UNTRANS=$UNTRANS$UNTRANS_INIT
262 # untranslated 指定対象が存在していれば cfg ファイルに指定行を出力する。
263 if test -n "$UNTRANS"; then
264 echo -ne " $UNTRANS\"" >> $CFG_NAME
267 echo >> $CFG_NAME # 最終改行調整
270 # cfg 生成処理 (TYPE=one, multi 共通)
271 # (copyright ファイルも同時生成する。)
274 echo "Creating cfg file:" # 処理進捗出力
276 # TYPE=one である場合、cfg ファイルは1つのみをここで作り始める。
277 if test $TYPE = one; then
278 CFG_NAME=po4a/$PACKAGE_NAME.cfg
279 echo "# Created by $THISTOOL, $THISDATE," > $CFG_NAME
280 echo "# with argument(s): $THISARGS" >> $CFG_NAME
281 echo "[po4a_langs] ja" >> $CFG_NAME
282 echo "[po4a_paths] po4a/$PACKAGE_NAME.pot \$lang:po4a/\$lang.po" >> $CFG_NAME
283 echo "[po4a_alias: man] man opt:\"-v --previous\" opt_ja:\"-M UTF-8\"" >> $CFG_NAME
286 # original 配下の man[0-9n] サブディレクトリ $d について
287 for d in `cd original; ls -d man[0-9n]`; do
289 echo -n " $d: " # 処理進捗出力
291 # TYPE=multi である場合、cfg ファイルを man[0-9n] ごとにここから生成する。
292 if test $TYPE = multi; then
294 CFG_NAME=po4a/$d/$PACKAGE_NAME-$d.cfg
295 echo "# Created by $THISTOOL, $THISDATE," > $CFG_NAME
296 echo "# with argument(s): $THISARGS" >> $CFG_NAME
297 echo "[po4a_langs] ja" >> $CFG_NAME
298 echo "[po4a_paths] po4a/$d/$PACKAGE_NAME-$d.pot \$lang:po4a/$d/\$lang.po" >> $CFG_NAME
299 echo "[po4a_alias: man] man opt:\"-v --previous\" opt_ja:\"-M UTF-8\"" >> $CFG_NAME
302 # original/man[0-9n] 配下の各ファイル $f について
303 for f in `cd original/$d; ls *`; do
307 # ファイルがシンボリックリンクである場合
308 if test -L original/$d/$f; then
311 LINECNT=`grep -v '^\.\\\"' original/$d/$f 2>/dev/null | wc -l | gawk -F" " '{print $1}'`
312 SOLINE=`grep -v '^\.\\\"' original/$d/$f 2>/dev/null | sed -n "/^\.so.*/p"`
314 # ファイルが ".so manN/*.N" の形式である場合
315 if ( test $LINECNT = "0" || test $LINECNT = "1" ) && test -n "$SOLINE"; then
316 : # .so 1行構成のものは処理しない
319 # ファイルが通常の場合 (シンボリックリンクや .so 形式でない場合) cfg 処理行を出力する。
321 echo "[type: man] original/$d/$f \$lang:release/$d/$f \\">>$CFG_NAME
322 echo -ne "\tadd_\$lang:?po4a/add_\$lang/copyright/$d/$f.txt">>$CFG_NAME
324 # po4a の処理設定各行においてオプション指定行を出力する。
327 # copyright ファイルの生成 (非存在時のみ)
328 if test -f po4a/add_ja/copyright/$d/$f.txt; then
329 : # 存在時は何もしない (上書き生成しない)
332 mkdir -p po4a/add_ja/copyright/$d
334 # コマンド .TH または .Dd が存在するかどうかを取得する。
335 FIRST=`grep "^\.TH" original/$d/$f >/dev/null 2>&1 && echo "^.TH"`
336 if test -z $FIRST; then
337 FIRST=`grep "^\.Dd" original/$d/$f >/dev/null 2>&1 && echo "^.Dd"`
340 # 上で .TH または .Dd が取得できなかった場合は先頭行を取得。
341 if test $FIRST != "^.TH" && test $FIRST != "^.Dd"; then
342 FIRST=`head -1 original/$d/$f`
345 # copyright ファイルのひながたを出力
346 cat > po4a/add_ja/copyright/$d/$f.txt <<"EOF"
347 PO4A-HEADER: mode=before; position=__FIRST__
349 .\" Translated __DATE__
350 .\" by __USERNAME__ <__EMAILADDR__>
353 # 上記生成ファイルに対して変数部分を置換する。
354 sed -i -e "s/__FIRST__/$FIRST/" \
355 -e "s/__DATE__/$THISDATE/" \
356 -e "s/__USERNAME__/$USERNAME/" \
357 -e "s/__EMAILADDR__/$EMAILADDR/" \
358 po4a/add_ja/copyright/$d/$f.txt
368 # TYPE=one 用の Makefile 生成処理
370 cat > Makefile.tmp <<"EOF"
371 PACKAGE_NAME = __PACKAGE_NAME__
375 PO4AFLAGS += -k $(THRESH) $(EXTFLAGS)
376 PO4ACFG = po4a/$(PACKAGE_NAME).cfg
382 po4a $(PO4AFLAGS) $(PO4ACFG)
385 @msgfmt -v --statistics -o /dev/null $(POFILE)
389 @po4a --force --no-update -k 0 $(PO4ACFG)
391 .PHONY: translate stat page-stat
393 sed -e "s/__PACKAGE_NAME__/$PACKAGE_NAME/" Makefile.tmp >Makefile
397 # TYPE=one 用の Makefile 生成処理
399 cat > Makefile.tmp <<"EOF"
400 PACKAGE_NAME = __PACKAGE_NAME__
401 man_numbers = __MAN_NUMBERS__
405 PO4AFLAGS += -k $(THRESH) $(EXTFLAGS)
407 target-mans = $(addprefix man,$(man_numbers))
408 po_dirs = $(addprefix po4a/,$(target-mans))
409 po_files = $(addsuffix /ja.po,$(po_dirs))
413 translate: $(target-mans)
415 $(target-mans): man%:
416 po4a $(PO4AFLAGS) po4a/man$*/$(PACKAGE_NAME)-man$*.cfg
419 @for po in $(po_files); do \
420 msgfmt -v --statistics -o /dev/null $$po; \
424 @for n in $(man_numbers); do \
425 if test -f po4a/man$$n/$(PACKAGE_NAME)-man$$n.cfg; then \
426 echo po4a/man$$n/$(PACKAGE_NAME)-man$$n.cfg: ;\
427 po4a --force --no-update -k 0 po4a/man$$n/$(PACKAGE_NAME)-man$$n.cfg | \
432 .PHONY: all translate stat page-stat
434 MAN_NUMBERS=`cd original; ls -dm man[0-9n] | sed -e "s/,//g" -e "s/man//g"`
435 sed -e "s/__PACKAGE_NAME__/$PACKAGE_NAME/" \
436 -e "s/__MAN_NUMBERS__/$MAN_NUMBERS/" \
437 Makefile.tmp >Makefile
442 # 変数 TYPE の設定に応じて、それぞれの処理を行う。
443 # これによって TYPE に応じた cfg ファイル、Makefile を生成する。
445 one) create_cfg; makefile_one;; # TYPE=one の場合の処理
446 multi) create_cfg; makefile_multi;; # TYPE=multi の場合の処理
449 # translation_list.tmp 生成処理
450 rm -f translation_list.tmp
452 echo "Creating translation_list.tmp file:" # 処理進捗出力
454 # original 配下の man[0-9n] サブディレクトリ $d について
455 for d in `cd original; ls -d man[0-9n]`; do
457 echo -n " $d: " # 処理進捗出力
459 # original/man[0-9n] 配下の各ファイル $f について
460 for f in `cd original/$d; ls *`; do
464 # ファイルがシンボリックリンクである場合
465 if test -L original/$d/$f; then
467 LINK_ITEM=`readlink original/$d/$f | sed -e "s|\(.*\)\.\([1-9].*\)|\1:\2|"`
468 echo -n "※:" >>translation_list.tmp # 決め打ちで "※" 出力; "@"(リンク先翻訳済み)かどうかは判断できない。
470 LINECNT=`grep -v '^\.\\\"' original/$d/$f 2>/dev/null | wc -l | gawk -F" " '{print $1}'`
471 SOLINE=`grep -v '^\.\\\"' original/$d/$f 2>/dev/null | sed -n "/^\.so .*/p"`
473 # ファイルが ".so manN/*.N" の形式である場合
474 if ( test $LINECNT = "0" || test $LINECNT = "1" ) && test -n "$SOLINE"; then
476 LINK_ITEM=`echo $SOLINE | sed "s|^\.so man\([0-9n]\)/\(.*\)\..*|\2:\1|"`
477 echo -n "※:" >>translation_list.tmp # 決め打ちで "※" 出力; "@"(リンク先翻訳済み)かどうかは判断できない。
479 # ファイルが通常の場合 (シンボリックリンクや .so 形式でない場合)
481 echo -n "▲:" >>translation_list.tmp # 決め打ちで "▲" 出力; "■"(改訂予約)などかどうかは判断できない。
485 man_sect=`echo $d | sed "s/man//"`
486 man_base=`echo $f | sed 's/^\(.*\)\.[^\.]*$/\1/'`
488 # translation_list 用に本日日付を再定義
489 THISDATE=`date '+%Y/%m/%d'`
491 # リンク情報かどうか (LINK 値) の違いを切り分けて translation_list 行を出力する。
492 if test $LINK = "0"; then
493 echo "$PACKAGE_NAME:$PACKAGE_VER:$PACKAGE_DATE:$man_base:$man_sect:$THISDATE::$EMAILADDR:$USERNAME:" \
494 >>translation_list.tmp
496 echo "$PACKAGE_NAME:$PACKAGE_VER:$PACKAGE_DATE:$man_base:$man_sect:$LINK_ITEM" \
497 >>translation_list.tmp