Communitygithub.com

asadeisa/arabic-office-skills

アラビア語/RTLのPDF、Word、PowerPoint出力を正しく生成するエージェントスキル。PNGプレビューによる視覚検証機能付き。

arabic-office-skills とは?

このスキルは、アラビア語(RTL)文書を正しく生成するためのビルダーを提供します。特にreportlabライブラリを使ったPDF生成において、アラビア文字の連結、双方向テキスト(bidi)の正しい順序、および手動での行折り返し処理を行い、文字がバラバラに表示されたり、単語や行が逆順になったりする問題を解決します。スクリプト`scripts/arabic_pdf.py`を使用することで、これらの複雑な処理を自分で実装する必要がなくなります。また、`pypdfium2`によるPNGプレビュー機能が必須であり、テキスト抽出では検出できない視覚的な欠陥(括弧の向き、ラテン語の挿入位置など)を確認できます。このスキルはClaude CodeやCursorなどのAIエージェント環境で利用でき、アラビア語の技術文書を正しく出力するために重要な役割を果たします。なお、Word(.docx)やPowerPoint(.pptx)には別の専用スキル(arabic-docx、arabic-pptx)が必要であり、同じアプローチは使えません。

対応✓Claude Code~Codex CLI~Cursor
npx skills add asadeisa/arabic-office-skills

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

アラビア語 / RTL PDF 生成

素朴なreportlabコードでは、アラビア語が微妙かつ根本的に間違って生成されます。文字がつながって表示されず、行内の単語が逆順になり、段落内の行が入れ替わります。これらの問題はテキスト抽出では見えず、レンダリングでのみ確認できます。このスキルには、これらの問題を解決済みのビルダーがバンドルされています。

リシェイプロジックをゼロから書くのではなく、scripts/arabic_pdf.pyを使用してください。 以下の各障害モードは、実際のドキュメントで遭遇したものです。

依存関係

pip install reportlab arabic-reshaper python-bidi pypdfium2

pypdfium2はプレビューのためだけのものですが、プレビューは必須です。以下の「検証」を参照してください。

ドキュメントの構築

ビルダーをインポートするには、scripts/arabic_pdf.pyを生成スクリプトの隣にコピーするか、このスキルのscripts/フォルダをsys.pathに追加します。

import pathlib, sys
sys.path.insert(0, str(pathlib.Path.home() / ".claude" / "skills" / "arabic-pdf" / "scripts"))
from arabic_pdf import ArabicPDF, preview

pdf = ArabicPDF("report.pdf", doc_title="عنوان المستند", page_numbers=True)

pdf.title("عنوان المستند")
pdf.subtitle("سطر فرعي")

pdf.heading("أولاً — المقدمة")
pdf.para("فقرة عربية تتضمن مصطلحات لاتينية مثل PostgreSQL و FastAPI.")

pdf.heading("ثانياً — جدول")
pdf.table(
    ["البند", "التفصيل"],                     # 右端の列から順に
    [["الواجهة الخلفية", "Python — FastAPI"],
     ["قاعدة البيانات", "PostgreSQL — SQLAlchemy"]],
    [5.0, 11.0],                              # 列幅(cm)
)

pdf.bullets(["نقطة أولى", "نقطة ثانية"])
pdf.save()

preview("report.pdf")     # ページごとに1つのPNG

スキルが別の場所にある場合はパスを調整してください。ビルダーの他の部分はインストール場所に依存しません。

メソッドはチェーン可能で、pdf.heading(...).para(...) のようにも記述できます。

メソッド目的
title / subtitle中央揃えのドキュメント見出し
heading右揃えの太字セクション見出し
para本文段落
bullets(items, marker="–")各項目を右揃えで1行ずつ表示
table(header, rows, widths_cm)RTLテーブル。自然な読む順序で列を渡し、出力時に逆順に配置
spacer(pts) / page_break()レイアウト制御
save()ファイルを書き込み、パスを返す

セルおよび段落のテキストには、改行を強制するために\nを含めることができます。

検証 — 常にレンダリングして確認する

save()の後、preview()を呼び出し、ReadツールでPNGを表示します。テキスト抽出ではRTLの欠陥を検出できません。なぜなら、文字はすべて存在し正しいからです。間違っているのは順序と形状だけです。具体的に以下を確認してください。

  • 各段落の最初の単語が右上に配置されていますか?
  • ラテン語の用語(PostgreSQL, FastAPI)は文中の正しい位置にあり、行の左端に飛んでいませんか?
  • 文字は結合されていますか、それともا ل س ل ا مのように離れていますか?
  • 真っ黒なボックスはありませんか?フォントにそのグリフが不足しています — 別のフォントを選んでください。
  • 括弧の向きは正しいですか — (20 فأكثر) であって )20 فأكثر( ではありませんか?
  • ラテン語の用語内のペアはそのままですか — Array<String>, DECIMAL(5,2)?
  • テーブルの単一の行が次のページに孤立していませんか?

確認しなかった欠陥を後で修正するのは、ドキュメントがすでに受信者の手元にある場合、はるかにコストがかかります。

正しさを達成する方法

ビルダーを適応させたり、特殊なドキュメントをデバッグしたりする際に役立ちます。

  1. シェイピング — arabic_reshaper が文字を位置別の表示形態にマッピングし、文字が結合するようにします。
  2. 明示的なベース方向を用いた双方向テキスト処理 — get_display(..., base_dir="R") を使用します。base_dir がないと、方向は最初の強い文字から推測されるため、ラテン語の単語で始まる行は左から右にレイアウトされ、後続のアラビア語が間違った位置に表示されます。これが「ほとんど正しいが、一部の行がスクランブルされる」という最も一般的な原因です。
  3. 手動による行折り返し — リシェイプされたテキストは視覚的な順序になっています。reportlabがこれを折り返すと、次の行に送られる単語は論理的に先頭の単語になるため、行がシャッフルされてしまいます。ビルダーは最初に折り返し、各行を個別にリシェイプし、<br/>で結合することで、reportlabが再折り返しを行わないようにします。8ptの安全マージンで計測誤差をカバーしています。1ポイントでもオーバーフローすると行が逆転する可能性があります。
  4. ミラーリング — get_display は並べ替えを行いますが、双方向テキストルールL4(右から左にレイアウトされるミラー文字は対応するパートナーとして描画される)は適用しません。これがないと、(20 فأكثر) は2つの括弧の位置が入れ替わり、元のグリフのままになり、)20 فأكثر( と印刷されます。prepare() が最初にそれらを置換し、並べ替えによって正しいグリフが移動するようにします。
  5. ラテン語アイランド — < と > はミラー文字ですが、Unicodeの対になった括弧ではないため、DECIMAL(5,2) をまとめておくルールはこれらには適用されません。Array<String> の > は後続のアラビア語の方向を取り、遠くの端に投げ出されます。各ラテン語スパンは LRI…PDI で囲まれ、並べ替え後にアイソレートが除去されるため、PDFに不可視の文字が残ることはありません。
  6. シェイピング後のエスケープ — reportlabは &, <, > のエスケープを必要としますが、先にエスケープすると、&lt; が双方向テキストパスを4文字として通過し、末尾の ; が行の遠端に排出されます。シェイプしてからエスケープします。
  7. テーブル列の逆順 — reportlabは列を左から右に配置するため、ビルダーは列を逆順にし、自然な読み順で列を渡せるようにします。
  8. テーブルへのKeepTogether — 単一の行が新しいページに孤立するのを防ぎます。

ポイント4~6は、arabic-docx で説明されている分割された括弧ランと同じ種類の欠陥であり、逆の方向からアプローチしています。そこではペアがランをまたいで分割されてはならず、ここではペアが半分だけミラーされてはいけません。ミラー文字は、そのパートナーと一緒に解決する必要があります。

フォント

register_fonts() はアラビア語対応フォントを検索します。WindowsではArial、次いでTahoma、macOSではArial、LinuxではNoto Naskh Arabic、次いでDejaVu Sansです。特定の書体(AmiriやCairoは正式文書に適しています)を使用するには、次のようにします。

from arabic_pdf import register_fonts
register_fonts("/path/Amiri-Regular.ttf", "/path/Amiri-Bold.ttf")   # ArabicPDF(...) の前に

Reportlabの組み込みフォントにはアラビア語のカバレッジがないため、TTFを登録する必要があります。これが、フォントがない場合にエラーではなく黒いボックスとして表示される理由です。

このアプローチをWordやPowerPointに持ち込まないでください

これは、RTLスキル全体において最も重要な境界です。

reportlab / PillowWord / PowerPoint
テキストエンジンなし完全な双方向エンジン
期待する入力最終的な視覚順序のグリフ生の論理順序Unicode
手法リシェイプ + 双方向処理 + 手動折り返しXML内の方向フラグ

プリシェイピングはここでは必須ですが、WordやPowerPointでは破壊的です。WordとPowerPointは描画時にシェイプするため、表示形態を渡すと二重にシェイプされ、グリフが壊れ、テキストの検索、コピー、スペルチェックができなくなります。2つのアプローチは正反対であり、バリエーションではありません。

.docx には arabic-docx を、.pptx には arabic-pptx を使用してください。なぜそれらが異なるのかを再確認せずに、コードを3つの間で移植しないでください。

注意点

  • arabic_digits("38") は、アラビア・インド数字が必要な場合に "٣٨" を返します。純粋に外観上の問題です。西洋数字はアラビア語の技術文書では完全に普通です。
  • デフォルトでは書式を控えめに保ってください — 黒いテキスト、細い罫線。学術的および公式のアラビア語文書はその方が信頼性が高く、ユーザーが「シンプル」を求めているなら、それは本気です。
  • 同じ仕組みでペルシャ語、ウルドゥー語、ヘブライ語も処理できます。フォントがそのスクリプトをカバーしていることだけが必要です。

生成されたアラビア語が生成されたと読者に思わせるもの

語彙の問題ではありません — 追加されたものの問題です。以下の各習慣は、読者にドキュメントの主題についてではなく、どのように書かれたかについて何かを伝えます。手作業で編集する読者はこれらをすべて削除します。文章を書きなさい。それを書いたという記述を書いてはいけません。

習慣使う代わりにこう書く
執筆行為を語る«الشروط ثلاثة، نذكرها صراحة فيما يلي»«الشروط ثلاثة:»
別のセクションを指す«…ونعود إلى هذه النقطة لاحقاً»そのフレーズを削除
タイトルにバージョンやステータスラベル«الخطة (النسخة الثانية — معتمدة)»«الخطة»
誰も挙げていない選択肢に対して反論«نحفظ المسار فقط. تخزين الملف كاملاً يضخّم الحجم بلا فائدة.»«نحفظ المسار فقط.»
指示に含まれていなかったことで選択を正当化«لم يرد ذلك في الطلب، غير أن طبيعة العمل تفرضه.»«طبيعة العمل تفرض ذلك.»
一人称単数«وأستطيع لاحقاً تحليل الحالات»«ويمكن لاحقاً تحليل الحالات»
ドキュメントがすでに示した事実を繰り返す別のセクションで情報を繰り返す繰り返しを削除

正式なアラビア語では、«أنا»ではなく非人称または複数形が好まれます。単数形はドキュメントではなく、自分自身へのメモとして読まれます。

関連スキル