🎬 manim-fa
افزونهی مانیم برای نمایش صحیح متن فارسی (راستبهچپ)، با فونت داخلی، تبدیل فینگلیش به فارسی، و قالببندیِ بولد/ایتالیک/زیرخط/هایلایت.
نصب
pip install -e .
وابستگیها (manim, manimpango) بهصورت خودکار نصب میشوند.
استفادهی سریع
from manim import *
from manim_fa import FaText, fa_write
class Demo(Scene):
def construct(self):
t = FaText("به مانیم فارسی خوش آمدید!", font_size=48, color=BLUE)
self.play(fa_write(t)) # نوشتن از راست به چپ (طبیعی برای فارسی)
self.wait(1)
قالببندیِ درونمتنی (بولد، ایتالیک، زیرخط، هایلایت)
نیازی به دانستنِ کد یا اندیسِ کاراکتر نیست — کافی است داخلِ خودِ متن از این نشانهها استفاده کنید:
| نحو | نتیجه |
|---|---|
**متن** |
بولد |
*متن* |
ایتالیک |
__متن__ |
زیرخطدار |
==متن== |
هایلایت با رنگ پیشفرض (زرد) |
==متن|رنگ== |
هایلایت با رنگ دلخواه، مثل ==نکتهی مهم|orange== |
FaText("این متن **بولد**، این *ایتالیک*، این __زیرخطدار__ و این ==هایلایت== است.")
FaText("رنگ دلخواه: ==نکتهی مهم|orange==")
برای نوشتنِ خودِ نویسههای *، _، = بهصورت عادی (بدون تفسیر بهعنوان
قالببندی)، قبلشان یک بکاسلش بگذارید: \*, \_, \=.
اگر متنِ شما بهطور طبیعی حاویِ این نویسههاست و اصلاً نمیخواهید تفسیر
شوند، از markup=False استفاده کنید:
FaText("۳*۴=۱۲", markup=False)
انیمیشنِ نوشتنِ راستبهچپ با fa_write
از fa_write(mobject) بهجای Write(mobject) استفاده کنید تا حروف از
راست به چپ (جهتِ طبیعیِ نوشتنِ فارسی) ظاهر شوند — با همان افکتِ اصیلِ
«دستنویسی» (اول خطدورِ حرف کشیده میشود، بعد پر میشود) که خودِ
Write() مانیم دارد؛ چون در پسِ صحنه دقیقاً از همان مکانیزم استفاده
میکند. تنها تفاوتش با Write(reverse=True) این است که با متنِ دارای
هایلایت هم درست کار میکند (جعبهی هایلایت همیشه همراه با متنِ خودش
ظاهر میشود، نه با تاخیر یا جلوتر):
t = FaText("این متن ==هایلایت== و **بولد** دارد.")
self.play(fa_write(t, run_time=3))
سایر امکانات
متن ترکیبی (فارسی + انگلیسی + عدد)
FaText("این متن ترکیبی است: Hello 123 پایان.")
تبدیل فینگلیش به فارسی
FaText("Salam be Manim", translit=True)
⚠️ توجه: این تبدیل یک جایگزینیِ حرفبهحرفِ ساده است، نه آوانگاری زبانشناختیِ کامل. مصوت کوتاه «a» همیشه به «ا» تبدیل میشود، پس مثلاً «shab» به «شاب» تبدیل میشود نه «شب». برای متن مهم، همیشه خروجی را بازبینی کنید.
فونت دلخواه
FaText("سلام", font="IRTitr") # اگر روی سیستم نصب باشد استفاده میشود
FaText("سلام") # وگرنه از فونت داخلی «وزیرمتن» استفاده میشود
فونت همراه پلاگین
فونت وزیرمتن (Vazirmatn) با
مجوز SIL Open Font License 1.1 همراه پلاگین توزیع میشود
(manim_fa/fonts_data/، مجوز در همان پوشه در OFL.txt). این یک فونت
مدرن با پشتیبانیِ کامل OpenType برای اتصالِ حروفِ فارسی/عربی است.
معماریِ فنی (برای مشارکتکنندگان)
manim_fa/text.py— تابعِFaText: تبدیل فینگلیش (اختیاری) ← تفسیرِ نشانههای قالببندی به Pango Markup ← ساختِMarkupTextبا فونتِ تضمینشده.manim_fa/markup.py— پارسرِ نحوِ ساده (**,*,__,==) به Pango Markup، با escape کردنِ نویسههای XML و پشتیبانی از بکاسلشبراینویسهیخام.manim_fa/fonts.py— ثبتِ خودکارِ فونتِ داخلی نزد Pango/ManimPango و انتخابِ بهترین فونتِ در دسترس.manim_fa/translit.py— تبدیلِ قاعدهمبنایِ فینگلیش به فارسی.manim_fa/animation.py— تابعِfa_write: نسخهی راستبهچپِWrite()که فقط ترتیبِ سطحِ بالا را برعکس میکند (نه بازگشتی) تا هم افکتِ اصیلِ دستنویسی حفظ شود، هم هایلایتها سالم بمانند.
چرا هیچجا arabic_reshaper/python-bidi استفاده نشده؟
با رندرِ واقعی و بررسیِ OCR ثابت شد که موتور متنِ خودِ مانیم (Pango + HarfBuzz) کاملاً از الگوریتم دوجهتهی یونیکد و اتصالِ حروفِ فارسی/عربی پشتیبانی میکند. اضافهکردنِ این کتابخانهها باعثِ «پردازشِ دوباره» و درنتیجه بههمریختنِ حروف میشود.
چرا fa_write بهجای Write(reverse=True) مستقیم؟
Write(reverse=True) خودِ مانیم از mobject.invert(recursive=True)
استفاده میکند که ترتیبِ همهی سطوحِ تودرتو را برعکس میکند، نه فقط
سطحِ بالا. این باعث میشد بلوکِ ادغامشدهی هایلایت (جعبه + حروفش، که در
FaText عمداً در یک VGroup قرار میگیرند) از داخل هم برعکس شود و جعبه
از متنِ خودش جدا بیفتد. به همین دلیل fa_write از یک زیرکلاسِ کوچک
استفاده میکند که فقط ترتیبِ سطحِ بالا را برعکس میکند (نه بازگشتی)، تا
ترتیبِ داخلیِ هر هایلایت (جعبه، سپس حروفش) همیشه دستنخورده بماند.
اجرای تستها
pip install pytest
pytest tests/
مثالها
پوشهی examples/ شامل چند صحنهی نمونه است:
cd examples
manim -pql demo.py Demo
manim -pql demo_formatting.py FormattingShowcase
manim -pql demo_comparison.py Comparison
محدودیتهای شناختهشده
translit_to_faیک تبدیلِ تقریبی است (بالا توضیح داده شد).- نشانههای قالببندی (
**,*,__,==) با هم تودرتو پشتیبانی نمیشوند (مثلاً بولدِ ایتالیک). - ترکیبِ چند عبارتِ لاتین/عددیِ متوالی داخلِ یک جملهی فارسی، طبقِ خودِ الگوریتمِ دوجهتهی یونیکد میتواند رفتارِ ظریفی داشته باشد (محدودیتِ خودِ استانداردِ یونیکد است، نه پلاگین).
سازگاری
با Manim Community v0.21.0 (جدیدترین نسخه) و ManimPango 0.6.1 با رندرِ واقعی تست شده است.
مجوز
این پروژه تحت مجوز MIT منتشر میشود. ساختهشده توسط علی تابش برای جامعهی فارسیزبانِ Manim.
🤝 مشارکت
Pull Request یا Issue خوشآمد است.
Release files for manim-fa 1.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| manim_fa-1.1.1.tar.gz | 155.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| manim_fa-1.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 307.8 kB
Release files / manim_fa-1.1.1.tar.gz
| Download URL | manim_fa-1.1.1.tar.gz |
|---|---|
| Size | 155.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f446eb7e11795e4be9cecc506555f95dd335f4b4f76dcc1dfd391307c2206e94
|
|
BLAKE2b-256 checksum How to use checksums |
b7b393eb9f471893dacf46598f0a2b72de7258251f640f339115be87beba0768
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / manim_fa-1.1.1-py3-none-any.whl
| Download URL | manim_fa-1.1.1-py3-none-any.whl |
|---|---|
| Size | 152.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b2d76115044391cfc8d86b37c94336747b9e27f0b57aa00065e26c04f763208b
|
|
BLAKE2b-256 checksum How to use checksums |
611450adbd4982b4fdb67a474b01baaa7fb7d84002fb7315bd62764487fcd405
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|