منتقلی¶
اگر آپ کا پروجیکٹ پہلے ہی gettext استعمال کرتا ہے، تو یہ فیصلہ کرنے والے سوال کہ یہ لائبریری اپنائی جا سکتی ہے یا نہیں، محدود سے ہیں: کیا یہ آپ کے موجودہ کیٹلاگ بے کار کر دیتی ہے، کیا یہ اُس کوڈ کے ساتھ چل سکتی ہے جسے بدلنے کے لیے آپ ابھی تیار نہیں، اور اس سفر کا کتنا حصہ ایک ہی وقت میں طے کرنا لازم ہے۔ جواب، سب سے مختصر پہلے:
| سوال | جواب |
|---|---|
کیا موجودہ .po اور .mo فائلیں اب بھی چلتی ہیں؟ |
ہاں۔ وہی فائلیں، وہی اوزار۔ |
| کیا پرانی اور نئی کالیں ایک ہی فائل میں رہ سکتی ہیں؟ | ہاں، اور ایک ہی استخراج کار نقشہ دونوں کو ڈھانپ لیتا ہے۔ |
| کیا msgid بدلتا ہے؟ | .format() سے نہیں۔ %-فارمیٹ سے ہاں۔ |
| کیا پورے پروجیکٹ کو ایک ساتھ منتقل ہونا پڑے گا؟ | نہیں۔ ایک کال کی جگہ بھی جائز تبدیلی ہے۔ |
| Jinja، Django ٹیمپلیٹ اور JavaScript کا کیا بنے گا؟ | کچھ نہیں بدلتا، وہی کیٹلاگ۔ |
اس صفحے کا باقی حصہ ان میں سے ہر ایک کی تفصیل ہے۔
.format() سے: msgid نہیں بدلتا¶
یہی وہ صورت ہے جس میں منتقلی کی قیمت تقریباً کچھ بھی نہیں۔ str.format والا
پیغام اور t-string والا پیغام ایک ہی کیٹلاگ کلید اخذ کرتے ہیں، کیونکہ دونوں
صورتوں میں کلید وہی متن ہے جس میں {name} جوں کا توں موجود رہتا ہے:
# Before
_("Hello {name}").format(name=name)
# After — the msgid is still "Hello {name}"
tr(t"Hello {name}")
چنانچہ موجودہ ترجمہ جڑا رہتا ہے۔ ایسے کیٹلاگ سے شروع کیجیے جس میں یہ ہو
کال بدلیے، دوبارہ نکالیے، اور اپ ڈیٹ کیجیے:
$ pybabel extract -F babel.cfg -o locales/messages.pot .
extracting messages from app.py (encoding="utf-8")
writing PO template file to locales/messages.pot
$ pybabel update -i locales/messages.pot -d locales
updating catalog locales/ja/LC_MESSAGES/messages.po based on locales/messages.pot
جو اندراج واپس آتا ہے وہ صرف میٹا ڈیٹا کی دو سطروں میں مختلف ہوتا ہے اور کہیں نہیں — ایک نشان لگانے والا تبصرہ جو اسے t-string پیغام کے طور پر پہچانتا ہے، اور ماخذ کی سطر کا نمبر:
نہ کوئی fuzzy نشان، نہ دوبارہ ترجمہ، کسی بھی زبان میں نہیں۔ پیغام فوراً
رینڈر ہو جاتا ہے:
$ pybabel compile -d locales
compiling catalog locales/ja/LC_MESSAGES/messages.po to locales/ja/LC_MESSAGES/messages.mo
$ python app.py
こんにちは Ada
update --check کیٹلاگوں کو پرانا بتائے گا
وہی نشان لگانے والا تبصرہ اور کھسکے ہوئے سطر نمبر
pybabel update --check کے لیے یہ کہنے کو کافی ہیں کہ کیٹلاگ دوبارہ بنانا
ہے، کیونکہ وہ پورے اندراج کا موازنہ کرتا ہے، صرف ترجمے کا نہیں۔ اصل
pybabel update کوڈ کی تبدیلی والے کمٹ ہی میں چلائیے، اور کیٹلاگ اسی کے
ساتھ کمٹ کیجیے — یہی عادت CI گیٹ پہلے ہی
مانگتا ہے۔
%-فارمیٹ سے: msgid بدلتا ہے، لہٰذا ترجمے fuzzy ہو جاتے ہیں¶
printf کی نحو پیغام کے اندر رہتی ہے، لہٰذا اسے بدلنا کیٹلاگ کی کلید نئے سرے
سے لکھ دیتا ہے۔ اس سے بچنے کا کوئی راستہ نہیں، اور %(name)s کو پیچھے چھوڑنے
کی یہی سچی قیمت ہے:
pybabel update نئے پیغام کو ہٹائے گئے پیغام کا قریبی رشتہ دار پہچان لیتا ہے
اور پرانا ترجمہ ساتھ لے آتا ہے، fuzzy نشان کے ساتھ:
#. gettext-tstrings
#: app.py:4
#, fuzzy, python-brace-format, python-format
msgid "Hello {name}"
msgstr "こんにちは %(name)s"
اس حالت کے بارے میں تین باتیں جاننے کی ہیں:
- رن ٹائم پر کچھ نہیں ٹوٹتا۔ fuzzy اندراج کمپائل شدہ
.moسے خارج رہتے ہیں، لہٰذا جب تک کوئی انسان اس جوڑے کی تصدیق نہ کرے، ایپلی کیشن ماخذ پیغام رینڈر کرتی ہے — وہی تنزل جس سے ہر ازسرِنو لکھا گیا پیغام گزرتا ہے۔ - جب تک وہ fuzzy ہیں، CI سبز رہتی ہے۔ پلیس ہولڈر چیکر fuzzy اندراج چھوڑ
دیتا ہے، بالکل جیسے
msgfmt --check-formatکرتا ہے، کیونکہ جو اندراج رن ٹائم تک پہنچ ہی نہیں سکتا اسے بلڈ ناکام نہیں کرنی چاہیے۔ جس لمحے کوئی مترجم یہ نشان ہٹاتا ہے، اندراج ہر دوسرے کی طرح جانچا جاتا ہے — چنانچہ تصدیق شدہ ترجمے میں رہ جانے والا%(name)sتبھی پکڑا جاتا ہے، اور یہی وہ لمحہ ہے جب وہ ورنہ رینڈر ہونا شروع کر دیتا۔ - پرانا
python-formatنشان ساتھ چلا آتا ہے اور اسےfuzzyنشان کے ساتھ ہی مٹا دینا چاہیے، ورنہmsgfmt --check-formatbrace-format والے پیغام پر printf کے قواعد لگاتا رہے گا۔
نام والے printf پلیس ہولڈرز کے لیے یہ تدوین مشینی ہے — %(name)s {name} بن
جاتا ہے اور کچھ نہیں ہلتا — لہٰذا بڑا کیٹلاگ ایک اسکرپٹ شدہ دور اور اس کے بعد
مترجم کے جائزے کا معاملہ ہے، نہ کہ دوبارہ ترجمے کا۔ ترتیبی %s مشینی نہیں: اس
کا کوئی نام ہے ہی نہیں کہ ساتھ لے جایا جائے، اور نام چننا ہی اس تبدیلی کا
مقصد ہے۔
اس لیے منتقلی اُسی رفتار سے آگے بڑھ سکتی ہے جو جائزہ اجازت دے: غیر تبدیل شدہ fuzzy اندراج کیٹلاگ میں نظر آتا ہوا کام ہے، ٹوٹا ہوا بلڈ نہیں۔
پرانی اور نئی کالیں ساتھ ساتھ¶
جو استخراج کار t-string پڑھتا ہے وہ عام gettext کالیں بھی پڑھتا ہے، لہٰذا ایک ہی نقشہ اُس فائل کو ڈھانپ لیتا ہے جو منتقلی کے بیچ میں ہو:
from gettext_tstrings import tr
from myapp.i18n import _
name = "Ada"
print(_("Save changes"))
print(tr(t"Hello {name}"))
دونوں پیغام ایک ہی ٹیمپلیٹ میں اترتے ہیں، اور صرف t-string والے پر وہ نشان لگانے والا تبصرہ آتا ہے جو اس لائبریری کی اضافی جانچ کو فعال کرتا ہے:
#: app.py:5
msgid "Save changes"
msgstr ""
#. gettext-tstrings
#: app.py:6
#, python-brace-format
msgid "Hello {name}"
msgstr ""
یہ _() کو، gettext کے چار معیاری ناموں کو، tr() / ntr() کے دوسرے ناموں
کو، اور مؤخر lazy_gettext() / lazy_pgettext() کو پہچانتا ہے۔ اپنے کسی
مددگار کا نقشے میں نام دینا
لازم ہے۔
رن ٹائم پر دونوں اسلوب برابر کے خودمختار ہیں: gettext.translation() ایک
translations آبجیکٹ لوٹاتا ہے، اور _ بھی اور اس لائبریری کے داخلی راستے بھی
اسی سے پڑھتے ہیں۔
کیا منتقل نہیں ہوتا¶
- ٹیمپلیٹ زبانیں۔ Jinja2 کا
{% trans %}، Django کے ٹیمپلیٹ ٹیگ، اور ان کے Babel استخراج کار جوں کے توں چلتے رہتے ہیں اور انہی PO کیٹلاگوں کو بھرتے رہتے ہیں۔ t-string Python کی نحو ہیں؛ ان کا اطلاق Python ماخذ پر ہوتا ہے۔ - آپ کی کیٹلاگ فائلیں۔ نہ صورت بدلتی ہے، نہ کوئی نئی فائل، نہ کوئی تبدیلی کا مرحلہ۔
- آپ کا ترجمے کا پلیٹ فارم۔
.poکا تبادلہ بالکل وہی ہے، اورpython-brace-formatکا جو نشان t-string پیغام اٹھاتا ہے وہی نشان.format()پیغام بھی اٹھاتا ہے — لہٰذا پلیس ہولڈر QA چلتی رہتی ہے۔ - غیر Python کوڈ۔ اسی پروجیکٹ میں موجود JavaScript یا C کا کیٹلاگ متاثر نہیں ہوتا۔
منتقلی کی فہرست¶
- جہاں
pybabelچلتا ہے وہاںbabelاضافی جزو شامل کیجیے، اورbabel.cfgمیںpythonنقشے کوgettext_tstringsطریقے میں بدل دیجیے — ایک ہی نقشہ پھر دونوں اسلوب ڈھانپ لیتا ہے، اور عام کالوں کے لیے-kبدستور کام کرتا ہے۔ - پہلے
.format()والی کال کی جگہیں بدلیے۔ دوبارہ نکالیے،pybabel updateچلائیے، اور کیٹلاگ کوڈ کے ساتھ کمٹ کیجیے؛ کسی fuzzy اندراج کی توقع نہ رکھیے۔ %-فارمیٹ والی کال کی جگہیں ایسے بستوں میں بدلیے جن کا جائزہ کرایا جا سکے، ساتھ آنے والے پلیس ہولڈرز نئے سرے سے لکھتے ہوئے اورfuzzyاورpython-formatنشان مٹاتے ہوئے۔- جو کچھ پابندی مسترد کرے اسے درست کیجیے: انٹرپولیشن کا سادہ نام ہونا لازم
ہے، لہٰذا
t"Hello {user.name}"پہلے کوئی مقامی متغیر بنتا ہے۔ یہ کال کی جگہ کی تدوین ہے، کیٹلاگ کی نہیں۔ - جھاڑو مکمل ہو جانے پر استخراج کار کے نقشے میں
strict = trueچلا دیجیے، تاکہ جو پیغام نکالا نہ جا سکے وہ ٹیمپلیٹ سے غائب ہونے کے بجائے بلڈ ناکام کرے۔ - پروڈکشن میں والی رن ٹائم جانچ شامل کیجیے: ہر
بھیجی جانے والی زبان کا ایک پیغام کسی سخت
Translatorسے رینڈر کیجیے۔
مرحلہ 2 اور 3 عام کمٹ ہیں۔ اس فہرست میں کسی چیز کو کسی "پرچم دن" کی ضرورت نہیں۔