django / django-localflavor

Country-specific Django helpers, formerly of contrib fame
https://django-localflavor.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
812 stars 289 forks source link

Japanese translations are not supported #494

Closed chrisspen closed 9 months ago

chrisspen commented 9 months ago

Even though it looks like you've included Japanese translations, they aren't accessible by Django's standard gettext() function. Even when forcing Japanese, localflavor still returns English for all names.

>>> from django.utils import translation
>>> from django.utils.translation import gettext as gt
>>> from localflavor.jp.jp_prefectures import JP_PREFECTURES
>>> with translation.override('ja'):
...     print({k: str(gt(v)) for k, v in JP_PREFECTURES})
{'hokkaido': 'Hokkaido', 'aomori': 'Aomori', 'iwate': 'Iwate', 'miyagi': 'Miyagi', 'akita': 'Akita', 'yamagata': 'Yamagata', 'fukushima': 'Fukushima', 'ibaraki': 'Ibaraki', 'tochigi': 'Tochigi', 'gunma': 'Gunma', 'saitama': 'Saitama', 'chiba': 'Chiba', 'tokyo': 'Tokyo', 'kanagawa': 'Kanagawa', 'niigata': 'Niigata', 'toyama': 'Toyama', 'ishikawa': 'Ishikawa', 'fukui': 'Fukui', 'yamanashi': 'Yamanashi', 'nagano': 'Nagano', 'gifu': 'Gifu', 'shizuoka': 'Shizuoka', 'aichi': 'Aichi', 'mie': 'Mie', 'shiga': 'Shiga', 'kyoto': 'Kyoto', 'osaka': 'Osaka', 'hyogo': 'Hyogo', 'nara': 'Nara', 'wakayama': 'Wakayama', 'tottori': 'Tottori', 'shimane': 'Shimane', 'okayama': 'Okayama', 'hiroshima': 'Hiroshima', 'yamaguchi': 'Yamaguchi', 'tokushima': 'Tokushima', 'kagawa': 'Kagawa', 'ehime': 'Ehime', 'kochi': 'Kochi', 'fukuoka': 'Fukuoka', 'saga': 'Saga', 'nagasaki': 'Nagasaki', 'kumamoto': 'Kumamoto', 'oita': 'Oita', 'miyazaki': 'Miyazaki', 'kagoshima': 'Kagoshima', 'okinawa': 'Okinawa'}

The correct output should be Japanese labels contained in https://github.com/django/django-localflavor/blob/master/localflavor/locale/ja/LC_MESSAGES/django.po

claudep commented 9 months ago

You are calling gettext on an already gettextized string. Could you try again without applying gt() on the value?

chrisspen commented 9 months ago

Yes, that was my first attempt. The result is the same.

>>> from django.utils import translation
>>> from localflavor.jp.jp_prefectures import JP_PREFECTURES
>>> with translation.override('ja'):
...     print({k: str(v) for k, v in JP_PREFECTURES})
{'hokkaido': 'Hokkaido', 'aomori': 'Aomori', 'iwate': 'Iwate', 'miyagi': 'Miyagi', 'akita': 'Akita', 'yamagata': 'Yamagata', 'fukushima': 'Fukushima', 'ibaraki': 'Ibaraki', 'tochigi': 'Tochigi', 'gunma': 'Gunma', 'saitama': 'Saitama', 'chiba': 'Chiba', 'tokyo': 'Tokyo', 'kanagawa': 'Kanagawa', 'niigata': 'Niigata', 'toyama': 'Toyama', 'ishikawa': 'Ishikawa', 'fukui': 'Fukui', 'yamanashi': 'Yamanashi', 'nagano': 'Nagano', 'gifu': 'Gifu', 'shizuoka': 'Shizuoka', 'aichi': 'Aichi', 'mie': 'Mie', 'shiga': 'Shiga', 'kyoto': 'Kyoto', 'osaka': 'Osaka', 'hyogo': 'Hyogo', 'nara': 'Nara', 'wakayama': 'Wakayama', 'tottori': 'Tottori', 'shimane': 'Shimane', 'okayama': 'Okayama', 'hiroshima': 'Hiroshima', 'yamaguchi': 'Yamaguchi', 'tokushima': 'Tokushima', 'kagawa': 'Kagawa', 'ehime': 'Ehime', 'kochi': 'Kochi', 'fukuoka': 'Fukuoka', 'saga': 'Saga', 'nagasaki': 'Nagasaki', 'kumamoto': 'Kumamoto', 'oita': 'Oita', 'miyazaki': 'Miyazaki', 'kagoshima': 'Kagoshima', 'okinawa': 'Okinawa'}
chrisspen commented 9 months ago

After digging through Django's gettext internals in django/utils/translation/trans_real.py, it looks like the override isn't doing anything, as the language remains set at "en".

However, even if I force set the global language variable to Japanese, it still doesn't render Japanese.

>>> from django.conf import settings
>>> from django.utils.translation import trans_real
>>> from localflavor.jp.jp_prefectures import JP_PREFECTURES
>>> settings.LANGUAGE_CODE = 'ja'
>>> trans_real._default = trans_real.translation(settings.LANGUAGE_CODE)
>>> print({k: str(v) for k, v in JP_PREFECTURES})
{'hokkaido': 'Hokkaido', 'aomori': 'Aomori', 'iwate': 'Iwate', 'miyagi': 'Miyagi', 'akita': 'Akita', 'yamagata': 'Yamagata', 'fukushima': 'Fukushima', 'ibaraki': 'Ibaraki', 'tochigi': 'Tochigi', 'gunma': 'Gunma', 'saitama': 'Saitama', 'chiba': 'Chiba', 'tokyo': 'Tokyo', 'kanagawa': 'Kanagawa', 'niigata': 'Niigata', 'toyama': 'Toyama', 'ishikawa': 'Ishikawa', 'fukui': 'Fukui', 'yamanashi': 'Yamanashi', 'nagano': 'Nagano', 'gifu': 'Gifu', 'shizuoka': 'Shizuoka', 'aichi': 'Aichi', 'mie': 'Mie', 'shiga': 'Shiga', 'kyoto': 'Kyoto', 'osaka': 'Osaka', 'hyogo': 'Hyogo', 'nara': 'Nara', 'wakayama': 'Wakayama', 'tottori': 'Tottori', 'shimane': 'Shimane', 'okayama': 'Okayama', 'hiroshima': 'Hiroshima', 'yamaguchi': 'Yamaguchi', 'tokushima': 'Tokushima', 'kagawa': 'Kagawa', 'ehime': 'Ehime', 'kochi': 'Kochi', 'fukuoka': 'Fukuoka', 'saga': 'Saga', 'nagasaki': 'Nagasaki', 'kumamoto': 'Kumamoto', 'oita': 'Oita', 'miyazaki': 'Miyazaki', 'kagoshima': 'Kagoshima', 'okinawa': 'Okinawa'}
claudep commented 9 months ago

I guess if translation.override is not changing the language, the issue is in your translation infrastructure. Check the various i18n settings first (USE_I18N, LANGUAGE_CODE, LANGUAGES, etc.).

chrisspen commented 9 months ago

That's what I thought at first, but otherwise, I have multi-language support working everywhere else in my project. I have USE_I18N, LANGUAGE_CODE, LANGUAGES, etc all configured correctly enough so that Japanese is showing for all gettext_lazy wrapped labels. Other Django packages seem to translate correctly too.

>>> from django.conf import settings
>>> settings.USE_I18N
True
>>> settings.LANGUAGE_CODE
'ja'
>>> settings.LANGUAGES
[('en', '英語'), ('ja', '日本')]

The only holdout is django-localflavor, so I figured the problem might be here. Hopefully I'm missing something.

claudep commented 9 months ago

You can check if language is correctly activated with get_language:

from django.utils import translation
with translation.override('ja'):
    print(translation.get_language())

If the result is anything different than ja, then you have an issue on your installation.

chrisspen commented 9 months ago
>>> from django.utils import translation
>>> with translation.override('ja'):
    ... print(translation.get_language())
ja

Looks like everything's correct on my end.

Can you get JP_PREFECTURES to render correctly? If all the values are correctly wrapped in gettext_lazy, then shouldn't it render in the selected language?

chrisspen commented 9 months ago

I found I could get it working by by avoiding Django altogether and using gettext directly:

>>> import gettext
>>> gettext.translation('django', '/path/to/my/pythonvirtualenv/lib/python3.11/site-packages/localflavor/locale', ['ja'], fallback=True).gettext('Okinawa')
'沖縄県'

Why doesn't Django automatically look in localflavor's locale directory?

chrisspen commented 9 months ago

Well I feel silly. Turns out the issue was I had forgotten to add localflavor to INSTALLED_APPS. Go figure...