بلاگ پر واپس جائیں

Django ترجمے کیوں ٹوٹتے ہیں (اور 10 سب سے عام وجوہات کو کیسے ٹھیک کریں)

2026-02-04 12 منٹ پڑھنے کا وقت
Django ترجمے کیوں ٹوٹتے ہیں (اور 10 سب سے عام وجوہات کو کیسے ٹھیک کریں)

آپ نے ترجمے کے لیے سٹرنگز کو نشان زد کیا، .po فائلیں بنائیں، compilemessages چلایا، اور آپ کی ایپ اب بھی انگریزی دکھا رہی ہے۔ آپ اکیلے نہیں ہیں۔ Django کا i18n فریم ورک طاقتور ہے، لیکن اس میں ایسی تیز دھاریں ہیں جو تجربہ کار ڈویلپرز کو بھی پکڑ لیتی ہیں۔

یہ گائیڈ Django ترجمے خاموشی سے ناکام ہونے کی 10 سب سے عام وجوہات کا احاطہ کرتی ہے، ہر ایک کے لیے درست علامات اور حل کے ساتھ۔

1. .po فائلیں ایڈٹ کرنے کے بعد compilemessages چلانا بھول جانا

آپ نے ایک .po فائل ایڈٹ کی (دستی طور پر یا کسی ٹول سے)، لیکن ترجمہ شدہ ٹیکسٹ کبھی نظر نہیں آتا۔ ایپ اصل انگریزی سٹرنگز دکھاتی رہتی ہے۔

Django رن ٹائم پر .po فائلیں نہیں پڑھتا۔ یہ کمپائل شدہ .mo (مشین آبجیکٹ) بائنری فائلیں پڑھتا ہے۔ اگر آپ .po فائل کو دوبارہ کمپائل کیے بغیر ایڈٹ کرتے ہیں، تو Django کو معلوم ہی نہیں ہوتا کہ کچھ بدلا ہے۔

ہر .po فائل کی تبدیلی کے بعد compilemessages چلائیں:

python manage.py compilemessages

اگر آپ TranslateBot سے اپنے ترجمے خودکار کرتے ہیں، تو اپنے ورک فلو کے آخری مرحلے کے طور پر compilemessages شامل کریں:

python manage.py makemessages -a --no-obsolete
python manage.py translate
python manage.py compilemessages

2. ٹیمپلیٹس میں {% load i18n %} غائب

آپ ایک ٹیمپلیٹ میں {% trans "Hello" %} استعمال کرتے ہیں، لیکن Django ایک TemplateSyntaxError پھینکتا ہے۔ یا اس سے بھی بدتر، اگر آپ کا ٹیمپلیٹ انجن غلط طریقے سے ترتیب دیا گیا ہے تو ٹیگ خاموشی سے کچھ نہیں کرتا۔

{% trans %} اور {% blocktrans %} ٹیگز Django کی i18n ٹیمپلیٹ ٹیگ لائبریری میں ہیں۔ اسے لوڈ کیے بغیر، ٹیمپلیٹ انجن انہیں نہیں پہچانتا۔

ترجمے کے ٹیگز استعمال کرنے والے ہر ٹیمپلیٹ کے اوپر {% load i18n %} شامل کریں:

{% load i18n %}

<h1>{% trans "Welcome to our site" %}</h1>
<p>{% blocktrans with name=user.name %}Hello, {{ name }}!{% endblocktrans %}</p>

یہ فی ٹیمپلیٹ ضرورت ہے۔ اگر ایک پیرنٹ ٹیمپلیٹ i18n لوڈ کرتا بھی ہے، ترجمے کے ٹیگز استعمال کرنے والے چائلڈ ٹیمپلیٹس کو اپنی {% load i18n %} اعلان کی ضرورت ہوتی ہے۔

3. LocaleMiddleware MIDDLEWARE میں نہیں ہے یا غلط پوزیشن میں ہے

براؤزر کے Accept-Language ہیڈر، URL پریفکس، یا سیشن سیٹنگز سے قطع نظر Django ہمیشہ ڈیفالٹ زبان میں مواد فراہم کرتا ہے۔

LocaleMiddleware ہر درخواست کے لیے فعال زبان کا تعین کرتا ہے۔ اس کے بغیر، Django LANGUAGE_CODE پر ڈیفالٹ ہو جاتا ہے اور تمام زبان کے انتخاب کے طریقوں کو نظرانداز کرتا ہے۔ مڈل ویئر اسٹیک میں اس کی پوزیشن بھی اہم ہے، کیونکہ اسے سیشن ڈیٹا اور URL ریزولوشن تک رسائی درکار ہوتی ہے۔

اپنی MIDDLEWARE سیٹنگ میں LocaleMiddleware شامل کریں، SessionMiddleware اور CommonMiddleware کے بعد:

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.locale.LocaleMiddleware",  # Must be after SessionMiddleware
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
]

اگر آپ URL پر مبنی زبان کی تبدیلی استعمال کرتے ہیں تو یقینی بنائیں کہ django.conf.urls.i18n آپ کی URL ترتیب میں شامل ہے:

from django.conf.urls.i18n import i18n_patterns

urlpatterns = i18n_patterns(
    path("", include("myapp.urls")),
)

4. زبان کے کوڈ کا عدم مطابقت (مثلاً pt-br بمقابلہ pt_BR)

ترجمے آپ کی .po فائلوں میں موجود ہیں، compilemessages کامیاب ہوتا ہے، لیکن Django بعض لوکیلز کے لیے ترجمے کو نظرانداز کرتا ہے۔

Django توقع کرتا ہے کہ لوکیل ڈائریکٹریز <language>_<COUNTRY> فارمیٹ کی پیروی کریں، انڈرسکور سیپریٹر اور بڑے حروف والے ملکی کوڈ کے ساتھ۔ مثال کے طور پر، برازیلی پرتگالی کے لیے pt_BR۔ اگر آپ کی ڈائریکٹری کا نام pt-br، pt-BR، یا ptBR ہے، تو Django اسے نہیں پائے گا۔ یہی بات LANGUAGES سیٹنگ پر بھی لاگو ہوتی ہے: وہاں کے کوڈز ہائفن (pt-br) استعمال کرتے ہیں، لیکن فائل سسٹم انڈرسکور (pt_BR) استعمال کرتا ہے۔

یقینی بنائیں کہ آپ کی ڈائریکٹری ساخت Django کی توقعات سے ملتی ہے:

locale/
    pt_BR/
        LC_MESSAGES/
            django.po
            django.mo

اور اپنی سیٹنگز میں، ہائفنیٹڈ شکل استعمال کریں:

LANGUAGES = [
    ("en", "English"),
    ("pt-br", "Brazilian Portuguese"),
    ("zh-hans", "Simplified Chinese"),
]

makemessages چلاتے وقت، لوکیل فلیگ کے لیے انڈرسکور شکل استعمال کریں:

python manage.py makemessages -l pt_BR

5. Fuzzy اندراجات کمپائلیشن کے دوران خاموشی سے چھوڑ دیے جاتے ہیں

ایک ترجمہ .po فائل میں موجود ہے، لیکن Django اس مخصوص اندراج کے لیے رن ٹائم پر اصل انگریزی سٹرنگ دکھاتا ہے۔ یہ خاص طور پر مایوس کن ہے کیونکہ ترجمہ فائل میں موجود ہے۔

جب Django کا makemessages پتہ لگاتا ہے کہ ایک سورس سٹرنگ تھوڑی سی بدل گئی ہے، تو یہ موجودہ ترجمے کو "fuzzy" (یعنی یہ ایک اندازہ ہے جسے انسانی جائزے کی ضرورت ہے) کے طور پر نشان زد کرتا ہے۔ compilemessages کمانڈ تمام fuzzy اندراجات کو چھوڑ دیتی ہے، انہیں غیر ترجمہ شدہ سمجھتے ہوئے۔ اس لیے اندراج .po فائل میں ترجمہ شدہ نظر آتا ہے، لیکن .mo فائل اسے مکمل طور پر خارج کر دیتی ہے۔

ایک fuzzy اندراج اس طرح نظر آتا ہے:

#, fuzzy
msgid "Welcome to our website!"
msgstr "Welkom op onze website!"

ترجمے کا جائزہ لیں، ضرورت ہو تو msgstr اپڈیٹ کریں، پھر #, fuzzy فلیگ ہٹا دیں:

msgid "Welcome to our website!"
msgstr "Welkom op onze website!"

پھر دوبارہ کمپائل کریں:

python manage.py compilemessages

بڑے پروجیکٹ میں، fuzzy اندراجات جمع ہوتے رہتے ہیں اور انہیں نظرانداز کرنا آسان ہے۔ TranslateBot کی check_translations کمانڈ انہیں خود بخود پکڑتی ہے:

python manage.py check_translations
locale/nl/LC_MESSAGES/django.po: 0 untranslated, 3 fuzzy
CommandError: Translation check failed

اسے اپنی CI پائپ لائن میں check_translations --makemessages کے ساتھ شامل کریں اور آپ کبھی بھی fuzzy اندراج شپ نہیں کریں گے۔

6. LOCALE_PATHS ترتیب نہیں دیا گیا یا غلط ڈائریکٹری کی طرف اشارہ کر رہا ہے

makemessages ایک جگہ پر .po فائلیں بناتا ہے، لیکن Django انہیں کہیں اور تلاش کرتا ہے۔ ترجمے ڈسک پر موجود ہیں لیکن کبھی لوڈ نہیں ہوتے۔

Django ایک مخصوص ترتیب میں ترجمے کی فائلیں تلاش کرتا ہے: پہلے LOCALE_PATHS ڈائریکٹریز، پھر ہر ایپ کی locale/ ڈائریکٹری، اور آخر میں پروجیکٹ کی locale/ ڈائریکٹری۔ اگر LOCALE_PATHS سیٹ نہیں ہے یا غلط راستے کی طرف اشارہ کرتا ہے، تو Django شاید آپ کی .po فائلیں کبھی نہ پائے۔

اپنی سیٹنگز میں LOCALE_PATHS کو مکمل راستے پر سیٹ کریں:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

LOCALE_PATHS = [
    BASE_DIR / "locale",
]

تصدیق کریں کہ ڈائریکٹری موجود ہے اور متوقع ساخت رکھتی ہے:

locale/
    de/
        LC_MESSAGES/
            django.po
            django.mo
    nl/
        LC_MESSAGES/
            django.po
            django.mo

ایک عام غلطی LOCALE_PATHS کو locale/ (نسبتی) پر سیٹ کرنا ہے مکمل راستے کی بجائے۔ Django آپ کے پروجیکٹ روٹ سے نسبتی راستوں کو حل نہیں کرتا۔ یہ پروسیس کی ورکنگ ڈائریکٹری پر منحصر ہے، جو اکثر آپ کی توقع سے مختلف ہوتی ہے۔

7. کیش پرانے ترجمے فراہم کر رہا ہے

آپ نے ترجمے اپڈیٹ اور کمپائل کیے، لیکن پرانا ٹیکسٹ نظر آتا رہتا ہے۔ سرور دوبارہ شروع کرنے سے ٹھیک ہو جاتا ہے۔

Django کا ترجمے کا کیٹلاگ فی پروسیس ایک بار لوڈ ہوتا ہے۔ پروڈکشن میں، Gunicorn یا Uvicorn جیسے WSGI/ASGI سرورز ورکر پروسیسز کو طویل عرصے تک فعال رکھتے ہیں۔ .mo فائل ڈسک پر بدل چکی ہو سکتی ہے، لیکن چلتے ہوئے پروسیس میں ابھی بھی پرانے ترجمے میموری میں ہیں۔ اس کے علاوہ، اگر آپ Django کا کیش فریم ورک یا Nginx یا Cloudflare جیسا ریورس پراکسی استعمال کرتے ہیں، تو کیش شدہ جوابات میعاد ختم ہونے تک پرانا مواد فراہم کریں گے۔

نئے ترجمے تعینات کرنے کے بعد اپنا ایپلیکیشن سرور دوبارہ شروع کریں:

# Gunicorn
kill -HUP $(cat /tmp/gunicorn.pid)

# Systemd
sudo systemctl restart myapp

# Docker
docker compose restart web

Django کے کیش فریم ورک کے لیے، ترجمے اپڈیٹ کرنے کے بعد کیش صاف کریں:

from django.core.cache import cache
cache.clear()

ڈویلپمنٹ میں، runserver Python فائلیں بدلنے پر آٹو ری لوڈ ہوتا ہے لیکن .mo فائلیں نہیں دیکھتا۔ compilemessages چلانے کے بعد آپ کو اسے دستی طور پر دوبارہ شروع کرنا ہوگا۔

8. سٹرنگز gettext (_() یا {% trans %}) میں لپٹی نہیں ہیں

makemessages بعض سٹرنگز ایکسٹریکٹ نہیں کرتا، اس لیے وہ کبھی آپ کی .po فائلوں میں نظر نہیں آتیں اور کبھی ترجمہ نہیں ہوتیں۔ یہ سب سے بنیادی مسئلہ ہے اور بڑے کوڈبیس میں سب سے آسانی سے نظرانداز ہونے والا بھی۔

Django کی makemessages کمانڈ آپ کے سورس کوڈ کو ترجمے کے نشانوں کے لیے اسکین کرنے کے لیے xgettext استعمال کرتی ہے۔ اگر کوئی سٹرنگ gettext() (عام طور پر _() کے طور پر عرف)، gettext_lazy()، {% trans %}، یا {% blocktrans %} میں لپٹی نہیں ہے، تو یہ ایکسٹریکشن پروسیس کے لیے پوشیدہ ہے۔

ہر صارف کو نظر آنے والی سٹرنگ لپیٹیں:

# Python code
from django.utils.translation import gettext_lazy as _

class Article(models.Model):
    class Meta:
        verbose_name = _("article")
        verbose_name_plural = _("articles")

# Views
from django.utils.translation import gettext as _

def my_view(request):
    message = _("Your changes have been saved.")
    return HttpResponse(message)
<!-- Templates -->
{% load i18n %}
<h1>{% trans "Welcome" %}</h1>
<p>{% blocktrans with count=items|length %}You have {{ count }} items.{% endblocktrans %}</p>

TranslateBot کے --dry-run فلیگ کا استعمال کریں فی الحال غیر ترجمہ شدہ سٹرنگز کا جائزہ لینے کے لیے، تاکہ آپ ایکسٹریکشن کے دوران چھوٹی ہوئی سٹرنگز پکڑ سکیں:

python manage.py translate --target-lang de --dry-run

یہ کوئی API کال یا تبدیلیاں کیے بغیر آپ کی .po فائلوں میں تمام غیر ترجمہ شدہ اندراجات دکھاتا ہے۔

9. f-string کا ترجمہ نہیں ہو سکتا (Django کی حد)

آپ _() میں ایک f-string لپیٹتے ہیں اور یا تو سنٹیکس ایرر ملتا ہے، یا makemessages ایک ٹوٹی/جزوی سٹرنگ ایکسٹریکٹ کرتا ہے جس کا ترجمہ نہیں ہو سکتا۔

Python f-string رن ٹائم پر ایویلیوایٹ ہوتی ہیں۔ xgettext ایکسٹریکشن ٹول سورس کوڈ کو سٹیٹکلی پارس کرتا ہے، اس لیے یہ {} بریسز کے اندر Python ایکسپریشنز کو ایویلیوایٹ نہیں کر سکتا۔ اس کا مطلب ہے کہ _(f"Hello, {name}") ایک ایسی سٹرنگ کے طور پر ایکسٹریکٹ ہوتی ہے جس میں لٹرل {name} ایکسپریشن ہے (یا مکمل طور پر ایکسٹریکٹ ہونے میں ناکام)، اور نتیجے میں .po اندراج کبھی رن ٹائم سٹرنگ سے نہیں ملے گا۔

اس کی بجائے Django کی % فارمیٹنگ یا نامزد پلیس ہولڈرز کے ساتھ .format() استعمال کریں:

# Wrong -- f-string cannot be extracted
message = _(f"Hello, {user.name}! You have {count} new messages.")

# Correct -- named placeholders
message = _("Hello, %(name)s! You have %(count)d new messages.") % {
    "name": user.name,
    "count": count,
}

# Also correct -- .format() with positional args
message = _("Hello, {0}! You have {1} new messages.").format(user.name, count)

یہ TranslateBot یا ٹولنگ کی حد نہیں ہے۔ یہ gettext کے کام کرنے کے طریقے کے لیے بنیادی ہے۔ سورس سٹرنگ ایک سٹیٹک لٹرل ہونی چاہیے تاکہ اسے رن ٹائم پر ایکسٹریکٹ اور تلاش کیا جا سکے۔

TranslateBot ترجمے کے دوران ان تمام پلیس ہولڈر فارمیٹس (%(name)s، {0}، %s، HTML ٹیگز) کو محفوظ رکھتا ہے، اس لیے ترجمہ شدہ سٹرنگز مکمل طور پر فعال رہتی ہیں۔

10. پلیس ہولڈر فارمیٹ سٹرنگ ایررز .po کمپائلیشن توڑ رہے ہیں

compilemessages ایک ایرر کے ساتھ ناکام ہوتا ہے، یا .po فائل میں #, python-format فلیگ کی عدم مطابقت ہے، اور اندراج خاموشی سے ہٹا دیا جاتا ہے۔

جب ایک سورس سٹرنگ میں %(name)s جیسے Python فارمیٹ پلیس ہولڈرز ہوتے ہیں، تو Django .po اندراج کو #, python-format سے نشان زد کرتا ہے۔ اگر ترجمے میں مختلف پلیس ہولڈرز ہیں (ایک ٹائپو جیسے %(nome)s، ایک غائب پلیس ہولڈر، یا ایک اضافی)، تو gettext ٹولز اندراج کو مسترد کر سکتے ہیں یا compilemessages ناکام ہو سکتا ہے۔ یہ عام طور پر دستی ترجموں یا AI ترجمے کے ٹولز کے ساتھ ہوتا ہے جو پلیس ہولڈر سیمنٹکس کو نہیں سمجھتے۔

ایک ٹوٹا ہوا اندراج اس طرح نظر آتا ہے:

#, python-format
msgid "Hello, %(name)s! You have %(count)d new messages."
msgstr "Hallo, %(naam)s! Je hebt %(count)d nieuwe berichten."

یہاں %(naam)s کو %(name)s ہونا چاہیے۔ پلیس ہولڈرز کو سورس سے بالکل ملنا چاہیے۔

یقینی بنائیں کہ ترجمہ شدہ سٹرنگز میں سورس جیسے بالکل وہی پلیس ہولڈرز ہوں۔ ٹائپوز، غائب پلیس ہولڈرز، اور اضافی پلیس ہولڈرز کی جانچ کریں۔

یہ ایک ایسا شعبہ ہے جہاں TranslateBot حقیقی فائدہ فراہم کرتا ہے۔ اس کی پلیس ہولڈر تحفظ کی منطق یقینی بناتی ہے کہ ترجمہ شدہ آؤٹ پٹ میں تمام فارمیٹ سٹرنگز (%(name)s، {0}، %s) سورس سے بالکل ملتی ہیں۔ پلیس ہولڈر ہینڈلنگ 100% ٹیسٹ کوریج سے محفوظ ہے، اس لیے ترجمے سے فارمیٹ سٹرنگ ایررز کمپائل ٹائم پر پکڑے جانے کی بجائے ٹول کی سطح پر ختم ہو جاتے ہیں۔

اگر آپ دستی طور پر یا ایسے ٹول سے ترجمہ کر رہے ہیں جو پلیس ہولڈرز کو نہیں سنبھالتا، تو اپنی .po فائلوں کی تصدیق کریں:

msgfmt --check-format locale/de/LC_MESSAGES/django.po

یہ gettext کی فارمیٹ سٹرنگ کی توثیق چلاتا ہے اور کسی بھی عدم مطابقت کی اطلاع دیتا ہے۔

سب کچھ ایک ساتھ: ایک دفاعی ورک فلو

ان میں سے زیادہ تر مسائل ایک مشترکہ بنیادی وجہ رکھتے ہیں: دستی اقدامات جو بھولنا آسان ہے۔ یہاں ایک ورک فلو ہے جو تمام 10 مسائل کو روکتا ہے:

# 1. Extract strings (catches #8 -- any new gettext-wrapped strings)
python manage.py makemessages -a --no-obsolete

# 2. Translate (catches #1, #5, #8, #9, #10 -- handles untranslated,
#    fuzzy, and placeholder issues automatically)
python manage.py translate

# 3. Compile (catches #1 -- generates .mo files)
python manage.py compilemessages

# 4. Verify in CI (catches everything that slipped through)
python manage.py check_translations --makemessages

مرحلہ 4 کو اپنی CI پائپ لائن میں شامل کریں اور غیر ترجمہ شدہ سٹرنگز، fuzzy اندراجات، اور فارمیٹ ایررز پروڈکشن تک پہنچنے سے پہلے بلڈ کو ناکام کر دیں گے۔

فوری حوالہ جات کی جدول

وجہ علامت ایک سطری حل
compilemessages نہیں چلایا ترجمے موجود ہیں لیکن نظر نہیں آتے python manage.py compilemessages
{% load i18n %} غائب {% trans %} پر TemplateSyntaxError ٹیمپلیٹ میں {% load i18n %} شامل کریں
LocaleMiddleware غائب زبان ہمیشہ انگریزی پر ڈیفالٹ MIDDLEWARE میں django.middleware.locale.LocaleMiddleware شامل کریں
زبان کے کوڈ کی عدم مطابقت لوکیل ڈائریکٹری نہیں ملی ڈائریکٹریز کے لیے pt_BR (انڈرسکور)، سیٹنگز کے لیے pt-br (ہائفن) استعمال کریں
Fuzzy اندراجات چھوڑے گئے ترجمہ .po میں ہے لیکن ایپ میں نہیں جائزے کے بعد #, fuzzy فلیگ ہٹائیں
غلط LOCALE_PATHS .po فائلیں موجود ہیں لیکن Django نظرانداز کرتا ہے LOCALE_PATHS کو مکمل راستے پر سیٹ کریں
کیش شدہ ترجمے اپڈیٹ کے بعد پرانا ٹیکسٹ نظر آتا ہے ایپلیکیشن سرور دوبارہ شروع کریں
سٹرنگ gettext میں نہیں سٹرنگ .po فائلوں سے غائب _() یا {% trans %} میں لپیٹیں
gettext میں f-string ٹوٹا ایکسٹریکشن یا رن ٹائم عدم مطابقت % یا .format() پلیس ہولڈرز سے بدلیں
پلیس ہولڈر عدم مطابقت compilemessages ناکام یا اندراج ہٹایا گیا سورس اور ترجمے کے درمیان پلیس ہولڈرز بالکل ملائیں

جب آپ ترجمے کے مرحلے کو خودکار کرتے ہیں اور CI میں جانچ نافذ کرتے ہیں تو ان میں سے زیادہ تر مسائل غائب ہو جاتے ہیں۔ TranslateBot کی translate کمانڈ پلیس ہولڈر تحفظ اور بتدریج ترجمے کو سنبھالتی ہے، جبکہ check_translations پروڈکشن تک پہنچنے سے پہلے کسی بھی چیز کو پکڑتی ہے جو نکل جائے (غیر ترجمہ شدہ اندراجات، fuzzy فلیگز، اور فارمیٹ سٹرنگ مسائل)۔

.po فائلوں کو دستی طور پر ترمیم کرنا بند کریں

TranslateBot، AI کے ساتھ Django ترجمے خودکار بناتا ہے۔ ایک کمانڈ، تمام زبانیں، فی ترجمہ چند پیسے۔