Uliweka alama kwenye maneno kwa ajili ya kutafsiri, ukatengeneza faili za .po, ukatekeleza compilemessages, na programu yako bado inaonyesha Kiingereza. Huko peke yako. Mfumo wa i18n wa Django una nguvu, lakini una makali ambayo yanawakamata hata wasanidi programu wenye uzoefu.
Mwongozo huu unashughulikia sababu 10 za kawaida zaidi ambazo tafsiri za Django zinashindwa kimya kimya, pamoja na dalili halisi na marekebisho kwa kila moja.
1. Kusahau Kutekeleza compilemessages Baada ya Kuhariri Faili za .po
Ulihariri faili ya .po (kwa mkono au kwa zana), lakini maandishi yaliyotafsiriwa hayaonekani kamwe. Programu inaendelea kuonyesha maneno ya asili ya Kiingereza.
Django haisomi faili za .po wakati wa utekelezaji. Inasoma faili za binary .mo (machine object) zilizokusanywa badala yake. Ukihariri faili ya .po bila kukusanya upya, Django haijui kwamba kitu kimebadilika.
Tekeleza compilemessages baada ya kila mabadiliko ya faili ya .po:
python manage.py compilemessages
Ikiwa unaendesha tafsiri zako kiotomatiki na TranslateBot, ongeza compilemessages kama hatua ya mwisho katika mtiririko wako wa kazi:
python manage.py makemessages -a --no-obsolete
python manage.py translate
python manage.py compilemessages
2. {% load i18n %} Haipo katika Templeti
Unatumia {% trans "Hello" %} katika templeti, lakini Django inatoa TemplateSyntaxError. Au mbaya zaidi, lebo haifanyi chochote kimya kimya ikiwa injini yako ya templeti imesanidiwa vibaya.
Lebo za {% trans %} na {% blocktrans %} ziko katika maktaba ya lebo za templeti ya i18n ya Django. Bila kuipakia, injini ya templeti haizitambui.
Ongeza {% load i18n %} juu ya kila templeti inayotumia lebo za tafsiri:
{% load i18n %}
<h1>{% trans "Welcome to our site" %}</h1>
<p>{% blocktrans with name=user.name %}Hello, {{ name }}!{% endblocktrans %}</p>
Hii ni mahitaji kwa kila templeti. Hata kama templeti mama inapakia i18n, templeti za watoto zinazotumia lebo za tafsiri zinahitaji tamko lao la {% load i18n %}.
3. LocaleMiddleware Haipo katika MIDDLEWARE au Iko katika Nafasi Isiyofaa
Django daima hutoa maudhui katika lugha ya chaguo-msingi bila kujali kichwa cha Accept-Language cha kivinjari, kiambishi cha URL, au mipangilio ya kikao.
LocaleMiddleware inaamua lugha inayotumika kwa kila ombi. Bila hiyo, Django inarudi kwa LANGUAGE_CODE na kupuuza mbinu zote za kuchagua lugha. Nafasi yake katika safu ya middleware pia ni muhimu, kwa sababu inahitaji ufikiaji wa data ya kikao na utatuzi wa URL.
Ongeza LocaleMiddleware kwenye mpangilio wako wa MIDDLEWARE, baada ya SessionMiddleware na 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",
]
Pia hakikisha django.conf.urls.i18n imejumuishwa katika usanidi wako wa URL ikiwa unatumia ubadilishaji wa lugha kulingana na URL:
from django.conf.urls.i18n import i18n_patterns
urlpatterns = i18n_patterns(
path("", include("myapp.urls")),
)
4. Misimbo ya Lugha Isiyolingana (mfano pt-br dhidi ya pt_BR)
Tafsiri zipo katika faili zako za .po, compilemessages inafanikiwa, lakini Django inapuuza tafsiri kwa eneo fulani.
Django inatarajia saraka za eneo zifuate muundo wa <language>_<COUNTRY> na kigawanyo cha chini na msimbo wa nchi kwa herufi kubwa. Kwa mfano, pt_BR kwa Kireno cha Brazili. Ikiwa saraka yako inaitwa pt-br, pt-BR, au ptBR, Django haitaipata. Hali hiyo hiyo inatumika kwa mpangilio wa LANGUAGES: misimbo hapo hutumia vistari (pt-br), lakini mfumo wa faili hutumia vigawanyo vya chini (pt_BR).
Hakikisha muundo wako wa saraka unalingana na matarajio ya Django:
locale/
pt_BR/
LC_MESSAGES/
django.po
django.mo
Na katika mipangilio yako, tumia fomu yenye vistari:
LANGUAGES = [
("en", "English"),
("pt-br", "Brazilian Portuguese"),
("zh-hans", "Simplified Chinese"),
]
Unapotekeleza makemessages, tumia fomu yenye kigawanyo cha chini kwa bendera ya eneo:
python manage.py makemessages -l pt_BR
5. Maingizo ya Fuzzy Yanarukwa Kimya Kimya Wakati wa Ukusanyaji
Tafsiri ipo katika faili ya .po, lakini Django inaonyesha neno la asili la Kiingereza wakati wa utekelezaji kwa ingizo hilo mahususi. Hii ni ya kusumbua hasa kwa sababu tafsiri iko hapo katika faili.
Wakati makemessages ya Django inagundua kwamba neno la chanzo limebadilika kidogo, inaweka alama kwenye tafsiri iliyopo kama "fuzzy" (ikimaanisha ni dhana inayohitaji ukaguzi wa binadamu). Amri ya compilemessages inaruka maingizo yote ya fuzzy, ikiyachukulia kama hayajatafsiriwa. Kwa hivyo ingizo linaonekana limetafsiriwa katika faili ya .po, lakini faili ya .mo inaliondoa kabisa.
Ingizo la fuzzy linaonekana hivi:
#, fuzzy
msgid "Welcome to our website!"
msgstr "Welkom op onze website!"
Kagua tafsiri, sasisha msgstr ikiwa ni lazima, kisha ondoa bendera ya #, fuzzy:
msgid "Welcome to our website!"
msgstr "Welkom op onze website!"
Kisha kusanya upya:
python manage.py compilemessages
Katika mradi mkubwa zaidi, maingizo ya fuzzy yanajikusanya na ni rahisi kuyakosa. Amri ya check_translations ya TranslateBot inayakamata kiotomatiki:
python manage.py check_translations
locale/nl/LC_MESSAGES/django.po: 0 untranslated, 3 fuzzy
CommandError: Translation check failed
Iongeze kwenye mtiririko wako wa CI na check_translations --makemessages na hutawahi kutoa ingizo la fuzzy tena.
6. LOCALE_PATHS Haijasanidiwa au Inaelekeza Saraka Isiyofaa
makemessages inatengeneza faili za .po mahali pamoja, lakini Django inazitafuta mahali pengine. Tafsiri zipo kwenye diski lakini hazipakiwi kamwe.
Django inatafuta faili za tafsiri kwa mpangilio maalum: saraka za LOCALE_PATHS kwanza, kisha saraka ya locale/ ya kila programu, na hatimaye saraka ya locale/ ya mradi. Ikiwa LOCALE_PATHS haijawekwa au inaelekeza njia isiyofaa, Django inaweza kamwe isipate faili zako za .po.
Weka LOCALE_PATHS katika mipangilio yako kwa njia kamili:
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
LOCALE_PATHS = [
BASE_DIR / "locale",
]
Thibitisha kuwa saraka ipo na ina muundo unaotarajiwa:
locale/
de/
LC_MESSAGES/
django.po
django.mo
nl/
LC_MESSAGES/
django.po
django.mo
Kosa la kawaida ni kuweka LOCALE_PATHS kwa locale/ (ya jamaa) badala ya njia kamili. Django haiyatatui njia za jamaa kutoka mzizi wa mradi wako. Inategemea saraka ya kazi ya mchakato, ambayo mara nyingi si unayotarajia.
7. Kache Inatoa Tafsiri Zilizopitwa na Wakati
Ulisasisha na kukusanya tafsiri, lakini maandishi ya zamani yanaendelea kuonekana. Kuanzisha upya seva kunarekebisha.
Katalogi ya tafsiri ya Django inapakiwa mara moja kwa kila mchakato. Katika uzalishaji, seva za WSGI/ASGI kama Gunicorn au Uvicorn zinaweka michakato ya wafanyakazi hai kwa muda mrefu. Faili ya .mo inaweza kuwa imebadilika kwenye diski, lakini mchakato unaoendelea bado una tafsiri za zamani katika kumbukumbu. Zaidi ya hayo, ukitumia mfumo wa kache wa Django au proksi ya nyuma kama Nginx au Cloudflare, majibu yaliyohifadhiwa kwenye kache yatatoa maudhui ya zamani hadi yawe na muda wa kumalizika.
Anzisha upya seva yako ya programu baada ya kutuma tafsiri mpya:
# Gunicorn
kill -HUP $(cat /tmp/gunicorn.pid)
# Systemd
sudo systemctl restart myapp
# Docker
docker compose restart web
Kwa mfumo wa kache wa Django, futa kache baada ya kusasisha tafsiri:
from django.core.cache import cache
cache.clear()
Katika maendeleo, runserver inapakia upya kiotomatiki faili za Python zinapobadilika lakini haifuatilii faili za .mo. Utahitaji kuianzisha upya kwa mkono baada ya kutekeleza compilemessages.
8. Maneno Hayajafungwa katika gettext (_() au {% trans %})
makemessages haichukui maneno fulani, kwa hivyo hayaonekani kamwe katika faili zako za .po na hayatafsiriwi kamwe. Hii ni tatizo la msingi zaidi na pia rahisi zaidi kupuuzwa katika msimbo mkubwa.
Amri ya makemessages ya Django inatumia xgettext kuchunguza msimbo wako wa chanzo kwa alama za tafsiri. Ikiwa neno halijafungwa katika gettext() (kwa kawaida linajulikana kama _()), gettext_lazy(), {% trans %}, au {% blocktrans %}, halionekani kwa mchakato wa uchukuaji.
Funga kila neno linalomkabili mtumiaji:
# 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>
Tumia bendera ya --dry-run ya TranslateBot kukagua maneno ambayo bado hayajatafsiriwa, ili uweze kupata maneno ambayo yalirukwa wakati wa uchukuaji:
python manage.py translate --target-lang de --dry-run
Hii inaonyesha maingizo yote ambayo bado hayajatafsiriwa katika faili zako za .po bila kufanya simu yoyote ya API au mabadiliko.
9. f-string Haziwezi Kutafsiriwa (Kizuizi cha Django)
Unafunga f-string katika _() na unapata kosa la sintaksia, au makemessages inachukua neno lililovunjika/sehemu ambalo haliwezi kutafsiriwa.
F-string za Python zinatathminiwa wakati wa utekelezaji. Zana ya uchukuaji xgettext inachambua msimbo wa chanzo kwa njia tuli, kwa hivyo haiwezi kutathmini misemo ya Python ndani ya mabano {}. Hii inamaanisha _(f"Hello, {name}") inachukuliwa kama neno lenye msemo wa {name} halisi (au inashindwa kuchukuliwa kabisa), na ingizo la .po linalotokea halitalingana kamwe na neno wakati wa utekelezaji.
Tumia muundo wa % wa Django au .format() na vishikilia nafasi vilivyopewa majina badala yake:
# 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)
Hii si kizuizi cha TranslateBot au zana. Ni msingi wa jinsi gettext inavyofanya kazi. Neno la chanzo lazima liwe neno tuli ili liweze kuchukuliwa na kutafutwa wakati wa utekelezaji.
TranslateBot inahifadhi miundo yote hii ya vishikilia nafasi (%(name)s, {0}, %s, lebo za HTML) wakati wa tafsiri, kwa hivyo maneno yaliyotafsiriwa yanabaki yanafanya kazi kikamilifu.
10. Makosa ya Muundo wa Vishikilia Nafasi Yanavunja Ukusanyaji wa .po
compilemessages inashindwa na kosa, au faili ya .po ina kutofautiana kwa bendera ya #, python-format, na ingizo linaondolewa kimya kimya.
Wakati neno la chanzo lina vishikilia nafasi vya muundo wa Python kama %(name)s, Django inaweka alama kwenye ingizo la .po na #, python-format. Ikiwa tafsiri ina vishikilia nafasi tofauti (kosa la kuandika kama %(nome)s, kishikilia nafasi kinachokosekana, au ziada), zana za gettext zinaweza kukataa ingizo au compilemessages inaweza kushindwa. Hii hutokea kwa kawaida na tafsiri za mikono au na zana za tafsiri za AI ambazo hazielewi semantiki ya vishikilia nafasi.
Ingizo lililovunjika linaonekana hivi:
#, python-format
msgid "Hello, %(name)s! You have %(count)d new messages."
msgstr "Hallo, %(naam)s! Je hebt %(count)d nieuwe berichten."
Hapa %(naam)s inapaswa kuwa %(name)s. Vishikilia nafasi lazima vilingane na chanzo kwa usahihi.
Hakikisha maneno yaliyotafsiriwa yana vishikilia nafasi sawa kabisa na chanzo. Angalia makosa ya kuandika, vishikilia nafasi vinavyokosekana, na vishikilia nafasi vya ziada.
Hii ni eneo ambapo TranslateBot inatoa faida ya kweli. Mantiki yake ya kuhifadhi vishikilia nafasi inahakikisha kwamba maneno yote ya muundo (%(name)s, {0}, %s) katika matokeo yaliyotafsiriwa yanalingana na chanzo kwa usahihi. Ushughulikiaji wa vishikilia nafasi umefunikwa na ufunikaji wa majaribio wa 100%, kwa hivyo makosa ya muundo wa maneno kutoka kwa tafsiri yanaondolewa katika kiwango cha zana badala ya kukamatwa wakati wa ukusanyaji.
Ikiwa unatafsiri kwa mkono au kwa zana ambayo haishughulikii vishikilia nafasi, thibitisha faili zako za .po na:
msgfmt --check-format locale/de/LC_MESSAGES/django.po
Hii inatekeleza uthibitisho wa muundo wa maneno wa gettext na kuripoti kutofautiana kwowote.
Kuweka Yote Pamoja: Mtiririko wa Kazi wa Kujilinda
Matatizo mengi ya haya yanashiriki sababu moja ya msingi: hatua za mikono ambazo ni rahisi kusahau. Hapa kuna mtiririko wa kazi unaozuia matatizo yote 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
Ongeza hatua ya 4 kwenye mtiririko wako wa CI na maneno ambayo hayajatafsiriwa, maingizo ya fuzzy, na makosa ya muundo yatashindisha ujenzi kabla ya kufikia uzalishaji.
Jedwali la Marejeleo ya Haraka
| Sababu | Dalili | Marekebisho ya Mstari Mmoja |
|---|---|---|
Hakuna compilemessages |
Tafsiri zipo lakini hazionekani | python manage.py compilemessages |
{% load i18n %} haipo |
TemplateSyntaxError kwenye {% trans %} |
Ongeza {% load i18n %} kwenye templeti |
| LocaleMiddleware haipo | Lugha daima ni Kiingereza chaguo-msingi | Ongeza django.middleware.locale.LocaleMiddleware kwenye MIDDLEWARE |
| Msimbo wa lugha haulingani | Saraka ya eneo haipatikani | Tumia pt_BR (kigawanyo cha chini) kwa saraka, pt-br (kistari) kwa mipangilio |
| Maingizo ya fuzzy yanarukwa | Tafsiri katika .po lakini si katika programu |
Ondoa bendera ya #, fuzzy baada ya kukagua |
| LOCALE_PATHS isiyofaa | Faili za .po zipo lakini Django inazipuuza |
Weka LOCALE_PATHS kwa njia kamili |
| Tafsiri zilizohifadhiwa kwenye kache | Maandishi ya zamani yanaonekana baada ya kusasisha | Anzisha upya seva ya programu |
| Neno haliko katika gettext | Neno halipo katika faili za .po |
Funga katika _() au {% trans %} |
| f-string katika gettext | Uchukuaji uliomunjika au kutofautiana wakati wa utekelezaji | Badilisha na vishikilia nafasi vya % au .format() |
| Vishikilia nafasi havilingani | compilemessages inashindwa au ingizo linaondolewa |
Linganisha vishikilia nafasi kwa usahihi kati ya chanzo na tafsiri |
Matatizo mengi ya haya yanapotea unapoendesha hatua ya tafsiri kiotomatiki na kutekeleza ukaguzi katika CI. Amri ya translate ya TranslateBot inashughulikia uhifadhi wa vishikilia nafasi na tafsiri ya hatua kwa hatua, wakati check_translations inakamata chochote kinachopita (maingizo ambayo hayajatafsiriwa, bendera za fuzzy, na matatizo ya muundo wa maneno) kabla ya kufikia uzalishaji.