'django translation not working for me
i cant force django to translate strings, choosen language from request is correct, but i have no translated strings.
maybe here could be problem: when i run shell, returned language_code
is not equal as i have in settings.py
gettext = lambda s: s
USE_I18N = True
USE_L10N = True
LANGUAGE_CODE = 'en'
LANGUAGES = (
('cs', gettext('Czech')),
('en', gettext('English')),
)
>>> from django.utils import translation
>>>
>>> translation.get_language()
'en-us'
>>> from django.conf import settings
>>> settings.LANGUAGE_CODE
'en'
my message file is in locale/cs/LC_MESSAGES/django.{mo,po}
i have this content there (translated abbr of week short names):
msgid "Mo Tu We Th Fr Sa Su"
msgstr "Po Út St Čt Pá So Ne"
in view, when i am getting right value 'cs'
print get_language()
'cs'
and next line is ugettext
ugettext('Mo Tu We Th Fr Sa Su')
'Mo Tu We Th Fr Sa Su'
but i am expecting
'Po Út St Čt Pá So Ne'
can somebody tell me where could be problem? :o)
Solution 1:[1]
It is possible that translation is in .po
file however is missing in .mo
file. Try recompile messages by running
./manage.py compilemessages
Solution 2:[2]
I tracked the code whole night and found some clues. Mainly in trans_real.py and gettext.py. You can put a breakpoint in "translation" function.
- The translation code are executed only once when app starts. So you need to reload the uwsgi to load the new version.
- Po file is never used. gettext.py use "mo" file only.(in my laptop). So you have to compile messages after changing.
- The "-" in the language code will be converted to "_" in locale path. For example "zh-CN" will be converted to "zh_CN". That's why the translation file cannot be found. I think it will be better if just using two characters as the language code. And the case sensitive should be considered in Linux system.
Solution 3:[3]
1. Make sure you have a correct-translated .mo
file:
Execute msgunfmt ./locale/jp/LC_MESSAGES/django.mo
to decompile .mo
file:
Example output:
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "world"
msgstr "????"
2. Make sure Python's builtin gettext
worked
Execute python
under project root, enter the Python shell
, then execute:
import gettext
assert gettext.translation("django", "locale", ['jp']).gettext("world") == "????"
3. Make sure LOCALE_PATHS
is correctly set
Execute python manage.py
under project root, enter the Django shell
, then execute:
from django.conf import settings
assert len(settings.LOCALE_PATHS) > 0
4. Make sure Django's gettext
worked under corresponding language context
Enter Django shell
, Execute:
from django.utils import translation
with translation.override("jp"):
assert translation.gettext("world") == "????"
5. Make sure you have a standard language code, and django supports it
Enter Django shell
, Execute:
from django.utils import translation
assert 'ja' in translation.trans_real.get_languages()
assert 'zh-hans' in translation.trans_real.get_languages()
assert 'zh-hant' in translation.trans_real.get_languages()
assert 'zh-cn' not in translation.trans_real.get_languages()
6. Make sure you have the correct language context
Server code:
from django.contrib import admin
from django.http import JsonResponse
from django.urls import path
from django.utils.translation import gettext_lazy, get_language
def home(_):
return JsonResponse(dict(
language=get_language(),
hello=gettext_lazy("world")
), json_dumps_params=dict(ensure_ascii=False, indent=4))
urlpatterns = [
path('admin/', admin.site.urls),
path('', home)
]
Test it:
curl 'http://localhost:8000' -H 'Accept-Language: ja'
Example response:
{
"language": "ja",
"hello": "????"
}
The required config but not in default Django project:
LOCALE_PATHS
Thelocale
path is required for django to find.mo
filesMIDDLEWARE
TheLocaleMiddleware
is required for web project to detect context's language
BASE_DIR = Path(__file__).resolve().parent.parent
LOCALE_PATHS = (
BASE_DIR / "locale", # Here
)
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', # And here
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Another note:
Do not execute mkdir locale
to create locale
folder manually, python manage.py makemessages
will create locale
folder if your settings worked.
The correct i18n
steps for a new Django
project:
- Set
LOCALE_PATHS
- Set
LocaleMiddleware
python manage.py makemessages
python manage.py compilemessages
python manage.py runserver
to see if it worked.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | mark |
Solution 3 |