Communitygithub.com

asadeisa/arabic-office-skills

PDF, Word, PowerPoint에서 올바른 아랍어/RTL 출력을 생성하는 에이전트 스킬 — PNG 미리보기로 시각적 검증 지원

arabic-office-skills란 무엇인가요?

이 스킬은 reportlab, Pillow, Word, PowerPoint 등 다양한 문서 생성 도구에서 아랍어 및 RTL(오른쪽에서 왼쪽) 텍스트를 올바르게 렌더링하기 위한 솔루션을 제공합니다. 가장 핵심적인 기능은 `scripts/arabic_pdf.py` 빌더로, reportlab의 네이티브 아랍어 처리 한계(글자 분리, 단어 순서 역전, 문단 뒤섞임)를 해결합니다. `arabic-reshaper`, `python-bidi`, 수동 줄바꿈, 미러링 문자 처리, 라틴어 격리 기법을 통해 올바른 시각적 순서를 보장합니다. 또한 `preview()` 함수로 PDF를 PNG로 변환하여 텍스트 추출로는 잡을 수 없는 시각적 결함을 반드시 확인하도록 설계되었습니다. `arabic-docx`와 `arabic-pptx` 스킬과 함께 사용되며, 각 플랫폼의 텍스트 엔진 차이(시각적 순서 vs 논리적 순서)를 이해해야 합니다. Cursor, Claude Code, Codex 등 AI 코딩 에이전트에서 문서 생성 시 아랍어 관련 버그를 예방하는 데 필수적입니다.

지원 대상✓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],                              # عرض الأعمدة بالسنتيمتر
)

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()를 호출하고 읽기 도구로 PNG를 확인하세요. 텍스트 추출은 RTL 결함을 잡을 수 없습니다. 문자는 모두 존재하고 올바르지만, 순서와 모양만 잘못되기 때문입니다. 특히 다음을 확인하세요:

  • 각 단락의 첫 단어가 오른쪽 상단에 위치하는가?
  • 라틴 용어(PostgreSQL, FastAPI)가 문장 중간에 제자리에 있는가, 줄 맨 왼쪽으로 튀어나가지 않는가?
  • 글자가 연결되어 있는가, 아니면 ا ل س ل ا م처럼 분리되어 있는가?
  • 검은색 사각형이 보이는가? 폰트에 해당 글리프가 없습니다 — 다른 폰트를 선택하세요.
  • 괄호 방향이 올바른가 — (20 فأكثر)가 아니라 )20 فأكثر(가 아닌가?
  • 라틴 용어 내의 쌍이 올바른가 — Array<String>, DECIMAL(5,2)?
  • 테이블 행 하나가 다음 페이지로 분리되지 않았는가?

나중에 결함을 찾아 수정하는 비용은 문서가 이미 수신자에게 전달된 후에 훨씬 더 큽니다.

올바름을 달성하는 방법

빌더를 수정하거나 특이한 문서를 디버깅할 때 유용합니다.

  1. 모양 형성(shaping) — arabic_reshaper가 문자를 위치 기반 표시 형태로 매핑하여 글자가 연결되도록 합니다.
  2. 명시적 기본 방향이 있는 양방향 처리 — get_display(..., base_dir="R"). base_dir이 없으면 첫 번째 강한 문자에서 방향이 추론되므로, 라틴어 단어로 시작하는 줄은 왼쪽에서 오른쪽으로 배치되고 뒤의 아랍어가 잘못 위치합니다. 이는 "대부분 맞지만 일부 줄이 뒤섞인" 경우의 가장 흔한 원인입니다.
  3. 수동 줄바꿈 — 재구성된 텍스트는 시각적 순서입니다. reportlab이 줄바꿈하면 다음 줄로 밀려나는 단어는 논리적으로 첫 번째 단어이므로 줄이 뒤섞입니다. 빌더가 먼저 줄바꿈하고, 각 줄을 별도로 재구성한 후 <br/>로 결합하여 reportlab이 다시 줄바꿈하지 않도록 합니다. 8pt 안전 여백으로 측정 차이를 보상하며, 1pt만 넘쳐도 줄이 역전될 수 있습니다.
  4. 미러링(mirroring) — get_display는 순서를 재정렬하지만 양방향 규칙 L4를 적용하지 않습니다. 이 규칙은 오른쪽에서 왼쪽으로 배치된 미러링 문자가 대응 문자로 그려지도록 합니다. 이 규칙 없이 (20 فأكثر)는 두 괄호의 위치가 바뀌고 원래 글리프로 반환되어 )20 فأكثر(로 출력됩니다. prepare()가 먼저 대체하여 재정렬이 올바른 글리프를 이동시키도록 합니다.
  5. 라틴어 섬(island) — <와 >는 미러링되지만 유니코드 쌍 괄호가 아니므로 DECIMAL(5,2)를 유지하는 규칙이 적용되지 않습니다. Array<String>의 >는 뒤의 아랍어 방향을 따라 맨 왼쪽으로 이동합니다. 각 라틴어 범위를 LRI…PDI로 감싸고 재정렬 후 격리 문자를 제거하여 PDF에 아무것도 보이지 않도록 합니다.
  6. 재구성 후 이스케이프 — reportlab은 &, <, >를 이스케이프해야 하지만, 먼저 이스케이프하면 &lt;가 4개의 문자로 양방향 패스에 전달되고 마지막 ;가 줄 맨 오른쪽으로 밀려납니다. 먼저 모양을 형성한 후 이스케이프합니다.
  7. 테이블 열 반전 — reportlab은 열을 왼쪽에서 오른쪽으로 배치하므로, 빌더가 열을 반전하여 자연스러운 읽기 순서로 열을 전달할 수 있게 합니다.
  8. 테이블에 KeepTogether 적용 — 단일 행이 새 페이지로 분리되는 것을 방지합니다.

포인트 4~6은 arabic-docx에 설명된 분할 괄호 실행(run)과 동일한 결함 클래스이지만, 반대 방향에서 접근합니다. 거기서는 쌍이 실행 간에 분리되지 않아야 하고, 여기서는 쌍이 절반만 미러링되지 않아야 합니다. 모든 미러링 문자는 파트너 문자와 함께 처리되어야 합니다.

폰트

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
텍스트 엔진없음완전한 양방향 엔진
입력 기대값최종 시각적 순서 글리프원시 논리적 순서 유니코드
기술재구성 + 양방향 + 수동 줄바꿈XML의 방향 플래그

사전 모양 형성은 여기서 필수이지만, 저기서는 파괴적입니다. Word와 PowerPoint는 렌더링 시 모양을 형성하므로, 표시 형태를 전달하면 두 번째로 모양이 형성되어 글리프가 깨지고, 텍스트를 검색, 복사, 맞춤법 검사할 수 없게 됩니다. 두 접근 방식은 반대이며, 변형이 아닙니다.

.docx에는 arabic-docx를, .pptx에는 arabic-pptx를 사용하세요. 두 방식이 왜 다른지 다시 읽지 않고 세 방식 간에 코드를 포팅하지 마세요.

참고 사항

  • arabic_digits("38") → 아랍-인도 숫자가 필요할 때 "٣٨"입니다. 순전히 미용상의 차이입니다. 서양 숫자는 아랍어 기술 문서에서 완전히 정상적입니다.
  • 기본적으로 서식을 절제하세요 — 검은색 텍스트, 얇은 선. 학술 및 공식 아랍어 문서는 그렇게 더 신뢰할 수 있어 보이며, "간단한" 문서를 원하는 사용자는 그 의미를 알고 있습니다.
  • 동일한 메커니즘이 페르시아어, 우르두어, 히브리어도 처리합니다. 폰트만 해당 문자를 지원하면 됩니다.

생성된 아랍어를 생성된 것처럼 보이게 만드는 요소

어휘가 아닙니다 — 추가된 내용입니다. 아래 각 습관은 문서의 주제보다는 어떻게 작성되었는지에 대해 독자에게 알려주며, 수동 편집자는 이 모두를 삭제합니다. 문장을 쓰되, 문장을 쓰는 과정에 대한 설명을 쓰지 마세요.

습관대신작성
글쓰기 행위를 서술«الشروط ثلاثة، نذكرها صراحة فيما يلي»«الشروط ثلاثة:»
다른 섹션을 가리킴«…ونعود إلى هذه النقطة لاحقاً»عبارة احذف
제목에 버전/상태 레이블«الخطة (النسخة الثانية — معتمدة)»«الخطة»
아무도 제기하지 않은 옵션에 반박«نحفظ المسار فقط. تخزين الملف كاملاً يضخّم الحجم بلا فائدة.»«نحفظ المسار فقط.»
요구사항에 누락된 내용으로 결정을 정당화«لم يرد ذلك في الطلب، غير أن طبيعة العمل تفرضه.»«طبيعة العمل تفرض ذلك.»
1인칭 단수«وأستطيع لاحقاً تحليل الحالات»«ويمكن لاحقاً تحليل الحالات»
문서가 이미 제공한 사실을 반복같은 정보를 다른 섹션에서 반복반복 제거

공식 아랍어는 «أنا»보다 비인칭 또는 복수를 선호합니다. 단수형은 문서가 아닌 개인 메모처럼 읽힙니다.

관련 스킬