組み込み以外の言語で帳票を出す
エンジンにコンパイル済みで入っている言語は、ja-JP と en-US の二つだけです。 残りはファイルです。 packs/locale/ に置かれた YAML を一つ読ませると、その言語の帳票PDFが出ます。 エンジンのビルドは変わりません。
この設計にした理由は単純で、レンダリングしない言語のデータをバイナリに入れたくないからです。 台湾向けの請求書しか出さない環境に、ヒンディー語の月名を持たせても仕方がありません。 組み込みの二つを残しているのは、ファイルを何も置かなくても動くようにするためです。
ロケールパックが決めるもの
一つのパックが持っているのは、その言語の帳票で読み手が目にする値です。
- 通貨:既定の通貨コード、記号、言語ごとの通貨名、記号を数字のどちら側に置くか
- 日付:
d MMM yのような書式と、月名、曜日名 - 数値:桁区切りと小数点の記号、桁のまとめ方
- 単位:「3 รายการ」の「รายการ」のような、数量に添える語
- フォント:その言語のグリフを持つフォントパックと、ラテン文字を補うフォールバック
テンプレート側には言語が書かれていません。 defaults.locale に書くのはタグ一つで、値の見た目はパックが決めます。 ギャラリーのレシートは、同じ座標と同じ組み方で六つのロケールぶん置いてあります。 違うのはロケールのタグと、その言語で書かれたラベルだけです。
置き方
テンプレートに一行足します。
defaults:
locale: zh-TW
currency: TWDあとはパックのファイルをエンジンに見つけさせるだけです。 コマンドラインなら --locale-dir を渡すか、$SHOJIKU_LOCALE_DIR を設定します。 どちらも無ければ ./packs/locale を見ます。
shojiku render --templates templates.yml --params params.json \
--locale-dir ./packs/locale --output out.pdfブラウザや Workers のように読めるファイルが無い環境では、パックの中身を文字列で渡します。 setLocale(tag, text) がその入口です。
タグに対応するパックも組み込みも無いときは、エンジンは代わりに別の言語を使ったりしません。 組み込みのタグ一覧と探したディレクトリを添えたエラーになります。
出荷しているパック
| ロケール | 通貨 | 日付 | フォント |
|---|---|---|---|
zh-TW | TWD | y年M月d日 | Noto Sans TC |
zh-CN | CNY | y年M月d日 | Noto Sans SC |
hi-IN | INR | d MMM y | Noto Sans Devanagari + Noto Sans |
fil-PH | PHP | MMM d, y | Noto Sans |
th-TH | THB | d MMM y | Noto Sans Thai + Noto Sans |
フォントも同じ考え方で、パックが名前で参照するだけです。 デーヴァナーガリーとタイ文字の書体はその文字しか持たないので、ラテン文字は noto-sans から補います。 フィリピン語はラテン文字なので、自前のフォントを持ちません。
言語によって組版そのものが変わるところ
パックはデータなので、足しても組版は変わりません。 それでも三つの言語には、エンジン側に専用の処理があります。
中国語の禁則:閉じ括弧や句読点が行頭に来てしまうとき、前の行の最後の文字を次の行へ送り、その文字を行頭にします。 日本語と同じ文字クラスを共有していて、lineBreak で強さを選べます。
インドの桁区切り:₹1,23,45,678 のように、右から三桁、そのあとは二桁ずつ区切ります。 区切りの幅はパックが持つ数値なので、エンジンのアルゴリズムは言語を知りません。
タイ語の分かち書きと仏暦:タイ語は単語のあいだに空白を置きません。 折り返す場所は単語分割器が決めます(詳細)。 日付は仏暦で入り、2026 年は 2569 年になります。 西暦で出したいときは日付の書式に gregorian を指定します。
新しい言語を足す
ロケールを一つ増やすのに、エンジンのコードは触りません。 scripts/gen-locale-builtins.py の PACK_CONFIG に一項目書いて、スクリプトを流すとパックができます。 値の出どころは CLDR です。 必要なフォントパックが無い場合は、それを別に用意する必要があります。
訳文について
このページを書いた人間は、タイ語と中国語のどちらも読めません。 数値や書式は CLDR のデータをそのまま出していますが、 語の選び方や、その言語の帳票として自然かどうかまでは確かめられていません。 おかしなところを見つけたら Issue で教えてください。