براہِ راست مواد پر جائیں

منتقلی

اگر آپ کا پروجیکٹ پہلے ہی 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}")

چنانچہ موجودہ ترجمہ جڑا رہتا ہے۔ ایسے کیٹلاگ سے شروع کیجیے جس میں یہ ہو

#: app.py:6
#, python-brace-format
msgid "Hello {name}"
msgstr "こんにちは {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 پیغام کے طور پر پہچانتا ہے، اور ماخذ کی سطر کا نمبر:

#. gettext-tstrings
#: app.py:4
#, python-brace-format
msgid "Hello {name}"
msgstr "こんにちは {name}"

نہ کوئی 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 کو پیچھے چھوڑنے کی یہی سچی قیمت ہے:

# Before
_("Hello %(name)s") % {"name": name}

# After — a different msgid
tr(t"Hello {name}")

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-format brace-format والے پیغام پر printf کے قواعد لگاتا رہے گا۔

نام والے printf پلیس ہولڈرز کے لیے یہ تدوین مشینی ہے — %(name)s {name} بن جاتا ہے اور کچھ نہیں ہلتا — لہٰذا بڑا کیٹلاگ ایک اسکرپٹ شدہ دور اور اس کے بعد مترجم کے جائزے کا معاملہ ہے، نہ کہ دوبارہ ترجمے کا۔ ترتیبی %s مشینی نہیں: اس کا کوئی نام ہے ہی نہیں کہ ساتھ لے جایا جائے، اور نام چننا ہی اس تبدیلی کا مقصد ہے۔

اس لیے منتقلی اُسی رفتار سے آگے بڑھ سکتی ہے جو جائزہ اجازت دے: غیر تبدیل شدہ fuzzy اندراج کیٹلاگ میں نظر آتا ہوا کام ہے، ٹوٹا ہوا بلڈ نہیں۔

پرانی اور نئی کالیں ساتھ ساتھ

جو استخراج کار t-string پڑھتا ہے وہ عام gettext کالیں بھی پڑھتا ہے، لہٰذا ایک ہی نقشہ اُس فائل کو ڈھانپ لیتا ہے جو منتقلی کے بیچ میں ہو:

[gettext_tstrings: **.py]
encoding = utf-8
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 کا کیٹلاگ متاثر نہیں ہوتا۔

منتقلی کی فہرست

  1. جہاں pybabel چلتا ہے وہاں babel اضافی جزو شامل کیجیے، اور babel.cfg میں python نقشے کو gettext_tstrings طریقے میں بدل دیجیے — ایک ہی نقشہ پھر دونوں اسلوب ڈھانپ لیتا ہے، اور عام کالوں کے لیے -k بدستور کام کرتا ہے۔
  2. پہلے .format() والی کال کی جگہیں بدلیے۔ دوبارہ نکالیے، pybabel update چلائیے، اور کیٹلاگ کوڈ کے ساتھ کمٹ کیجیے؛ کسی fuzzy اندراج کی توقع نہ رکھیے۔
  3. %-فارمیٹ والی کال کی جگہیں ایسے بستوں میں بدلیے جن کا جائزہ کرایا جا سکے، ساتھ آنے والے پلیس ہولڈرز نئے سرے سے لکھتے ہوئے اور fuzzy اور python-format نشان مٹاتے ہوئے۔
  4. جو کچھ پابندی مسترد کرے اسے درست کیجیے: انٹرپولیشن کا سادہ نام ہونا لازم ہے، لہٰذا t"Hello {user.name}" پہلے کوئی مقامی متغیر بنتا ہے۔ یہ کال کی جگہ کی تدوین ہے، کیٹلاگ کی نہیں۔
  5. جھاڑو مکمل ہو جانے پر استخراج کار کے نقشے میں strict = true چلا دیجیے، تاکہ جو پیغام نکالا نہ جا سکے وہ ٹیمپلیٹ سے غائب ہونے کے بجائے بلڈ ناکام کرے۔
  6. پروڈکشن میں والی رن ٹائم جانچ شامل کیجیے: ہر بھیجی جانے والی زبان کا ایک پیغام کسی سخت Translator سے رینڈر کیجیے۔

مرحلہ 2 اور 3 عام کمٹ ہیں۔ اس فہرست میں کسی چیز کو کسی "پرچم دن" کی ضرورت نہیں۔