Communitygithub.com

asadeisa/arabic-office-skills

代理技能,用於在 PDF、Word 和 PowerPoint 中產生正確的阿拉伯文/從右到左 (RTL) 輸出,並附帶 PNG 預覽以進行視覺驗證。

arabic-office-skills 是什麼?

這個 AI 代理技能專門解決在程式化產生 PDF、Word 或 PowerPoint 文件時,阿拉伯文(以及波斯文、烏爾都文、希伯來文等從右到左書寫系統)常見的格式錯誤。錯誤包括字母斷開、單詞順序反向或段落錯亂——這些在提取的文字中無法察覺,只能在渲染後的視覺輸出中看到。該技能提供一個現成的建構器 (`scripts/arabic_pdf.py`),它封裝了正確的處理流程:使用 `arabic_reshaper` 進行文字塑形、使用 `python-bidi` 並明確設定基底方向為 RTL 以處理雙向文字、手動換行以防止 ReportLab 錯誤重排、鏡像處理配對符號(如括號)、以及保護拉丁文字島(如程式碼片段)不被打亂。此技能支援在 Claude Code、Cursor 等環境中使用,並強烈建議使用 `pypdfium2` 生成 PNG 預覽,以進行視覺驗證——這是因為文字提取無法捕捉 RTL 佈局缺陷。它適用於 ReportLab(需要預塑形),但明確警告不要將此方法用於 Word 或 PowerPoint,因為那些平台具有內建的雙向引擎,預塑形反而會造成破壞。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add asadeisa/arabic-office-skills

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

阿拉伯文 / 從右到左 (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],                              # 欄寬,單位公分
)

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

preview("report.pdf")     # 每頁產生一個 PNG

如果技能安裝在其他位置,請調整路徑——建構器的其他部分不依賴於其安裝位置。

方法可以鏈式調用,所以 pdf.heading(...).para(...) 也能正常運作。

方法目的
title / subtitle置中的文件標題
heading靠右對齊的粗體章節標題
para正文段落
bullets(items, marker="–")每個項目靠右對齊的單行列表
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. 塑形 (Shaping)——arabic_reshaper 將字元映射到位置相關的呈現形式,使字母得以連接。
  2. 明確指定基底方向的雙向處理 (Bidi)——get_display(..., base_dir="R")。若不指定 base_dir,方向會從第一個強字元推斷,因此以拉丁單詞開頭的行會從左到右排列,後面的阿拉伯文就會錯位。這是「大部分正確但某些行錯亂」最常見的原因。
  3. 手動換行——重塑後的文字是視覺順序。如果 reportlab 對其換行,它推到下一行的單詞反而是邏輯上第一個,因此各行會被打亂。建構器先換行,再對每行分別重塑,然後用 <br/> 連接,這樣 reportlab 就不會再重新換行。我們使用 8pt 的安全邊距來補償測量差異;哪怕多一個點的溢出都足以反轉該行。
  4. 鏡像處理 (Mirroring)——get_display 會重新排序,但從不套用 bidi 規則 L4,該規則規定從右到左排列的鏡像字元應以其配對字元繪製。沒有這個處理,(20 فأكثر) 會變成兩個括號位置互換且使用原始字形,因此印出 )20 فأكثر(。prepare() 會先替換它們,這樣重新排序時就能移動到正確的字形。
  5. 拉丁文字島 (Latin islands)——< 和 > 是鏡像字元,但不是 Unicode 配對括號,因此保持 DECIMAL(5,2) 完整的規則不適用於它們;Array<String> 中的 > 會採用其後阿拉伯文的方向,而被扔到最遠的一側。每個拉丁文字段都被包裹在 LRI…PDI 中,並在重新排序後移除這些隔離符,因此沒有不可見的東西進入 PDF。
  6. 塑形後再跳脫字元——reportlab 需要跳脫 &、<、>,但如果先跳脫,&lt; 會作為四個字元通過雙向處理,其尾端的 ; 會被丟到行的最遠一側。正確順序是先塑形,再跳脫。
  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 在渲染時才進行塑形,因此給予它們呈現形式會導致它們進行第二次塑形——產生破碎的字形,且文字無法再被搜尋、複製或進行拼字檢查。這兩種方法完全相反,而非僅是變體。

請對 .docx 使用 arabic-docx,對 .pptx 使用 arabic-pptx。在未重新閱讀它們為何不同的情況下,請勿在這三者之間移植程式碼。

備註

  • arabic_digits("38") → "٣٨"(當需要阿拉伯-印度數字時)。純屬裝飾性;西方式數字在阿拉伯技術寫作中完全正常。
  • 預設情況下請保持格式簡潔——黑色文字、細線條。學術和正式阿拉伯文件這樣讀起來更可信,要求「簡單」的使用者通常就是這個意思。
  • 同樣的機制也適用於波斯文、烏爾都文和希伯來文;只需要字型能支援這些書寫系統即可。

什麼讓產生的阿拉伯文讀起來像機器生成的

不是詞彙——而是那些添加物。以下每個習慣都在告訴讀者文件是如何寫成的,而非文件的主題是什麼,而手動編輯的讀者會全部刪除它們。寫句子本身,而不是寫關於寫句話的說明。

習慣不該這樣寫應該這樣寫
敘述寫作行為«الشروط ثلاثة، نذكرها صراحة فيما يلي»«الشروط ثلاثة:»
指向另一個章節«…ونعود إلى هذه النقطة لاحقاً»刪除該句
在標題中加入版本或狀態標籤«الخطة (النسخة الثانية — معتمدة)»«الخطة»
反駁一個沒人提出的選項«نحفظ المسار فقط. تخزين الملف كاملاً يضخّم الحجم بلا فائدة.»«نحفظ المسار فقط.»
用需求規格書沒提到的內容來為選擇辯護«لم يرد ذلك في الطلب، غير أن طبيعة العمل تفرضه.»«طبيعة العمل تفرض ذلك.»
第一人稱單數«وأستطيع لاحقاً تحليل الحالات»«ويمكن لاحقاً تحليل الحالات»
重複文件已提供的資訊在其他章節重複資訊刪除重複內容

正式阿拉伯文偏好非人稱或複數形式,而非「أنا」;單數形式讀起來像是給自己的筆記,而非正式文件。

相關技能