Skip to content

Commit

Permalink
[Django 4.1+] Make i18n works for LANGUAGE_CODE with a country code (#…
Browse files Browse the repository at this point in the history
…206)

When using a `LANGUAGE_CODE` with a country code and a supported
language (_ie_: `fr-FR`) the current implementation of
`Select2Mixin.i18n_name` will return `None` which means default
_select2_ language, so English.


Co-authored-by: Johannes Maron <[email protected]>
  • Loading branch information
rsebille and codingjoe authored May 23, 2023
1 parent f0e9555 commit ed1af30
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ To install the package and its dependencies for development
including tests dependencies, please do:

python -m pip install -e .[test]

You may ran the tests via::

python -m pytest
Expand Down
15 changes: 11 additions & 4 deletions django_select2/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,11 @@

import django
from django import forms
from django.contrib.admin.widgets import SELECT2_TRANSLATIONS, AutocompleteMixin
from django.contrib.admin.widgets import AutocompleteMixin
from django.core import signing
from django.db.models import Q
from django.forms.models import ModelChoiceIterator
from django.urls import reverse
from django.utils.translation import get_language

from .cache import cache
from .conf import settings
Expand Down Expand Up @@ -89,7 +88,15 @@ class Select2Mixin:
@property
def i18n_name(self):
"""Name of the i18n file for the current language."""
return SELECT2_TRANSLATIONS.get(get_language())
if django.VERSION < (4, 1):
from django.contrib.admin.widgets import SELECT2_TRANSLATIONS
from django.utils.translation import get_language

return SELECT2_TRANSLATIONS.get(get_language())
else:
from django.contrib.admin.widgets import get_select2_language

return get_select2_language()

def build_attrs(self, base_attrs, extra_attrs=None):
"""Add select2 data attributes."""
Expand Down Expand Up @@ -258,7 +265,7 @@ def __init__(self, attrs=None, choices=(), **kwargs):
if dependent_fields is not None:
self.dependent_fields = dict(dependent_fields)
if not (self.data_view or self.data_url):
raise ValueError('You must ether specify "data_view" or "data_url".')
raise ValueError('You must either specify "data_view" or "data_url".')
self.userGetValTextFuncName = kwargs.pop("userGetValTextFuncName", "null")

def get_url(self):
Expand Down
71 changes: 71 additions & 0 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
from collections.abc import Iterable

import django
import pytest
from django.db.models import QuerySet
from django.urls import reverse
Expand Down Expand Up @@ -822,3 +823,73 @@ def test_dependent_fields_clear_after_change_parent(
)
)
assert city2_container.text == ""


@pytest.fixture(
name="widget",
params=[
(Select2Widget, {}),
(HeavySelect2Widget, {"data_view": "heavy_data_1"}),
(HeavySelect2MultipleWidget, {"data_view": "heavy_data_1"}),
(ModelSelect2Widget, {}),
(ModelSelect2TagWidget, {}),
],
ids=lambda p: p[0],
)
def widget_fixture(request):
widget_class, widget_kwargs = request.param
return widget_class(**widget_kwargs)


@pytest.mark.skipif(django.VERSION < (4, 1), reason="Only for Django 4.1+")
@pytest.mark.parametrize(
"locale,expected",
[
("fr-FR", "fr"),
# Some locales with a country code are natively supported by select2's i18n
("pt-BR", "pt-BR"),
("sr-Cyrl", "sr-Cyrl"),
],
ids=repr,
)
def test_i18n_name_property_with_country_code_in_locale(widget, locale, expected):
"""Test we fall back to the language code if the locale contain an unsupported country code."""
with translation.override(locale):
assert widget.i18n_name == expected


@pytest.mark.skipif(django.VERSION < (4, 1), reason="Only for Django 4.1+")
def test_i18n_media_js_with_country_code_in_locale(widget):
translation.activate("fr-FR")
assert tuple(widget.media._js) == (
"admin/js/vendor/select2/select2.full.min.js",
"admin/js/vendor/select2/i18n/fr.js",
"django_select2/django_select2.js",
)


@pytest.mark.skipif(django.VERSION >= (4, 1), reason="Only for Django 4.0 and previous")
@pytest.mark.parametrize(
"locale,expected",
[
("fr-FR", None),
# Some locales with a country code are natively supported by select2's i18n
("pt-BR", "pt-BR"),
("sr-Cyrl", "sr-Cyrl"),
],
)
def test_i18n_name_property_with_country_code_in_locale_for_older_django(
widget, locale, expected
):
"""No fallback for locale with an unsupported country code."""
with translation.override(locale):
assert widget.i18n_name == expected


@pytest.mark.skipif(django.VERSION >= (4, 1), reason="Only for Django 4.0 and previous")
def test_i18n_media_js_with_country_code_in_locale_for_older_django(widget):
translation.activate("fr-FR")
assert tuple(widget.media._js) == (
"admin/js/vendor/select2/select2.full.min.js",
"django_select2/django_select2.js",
)

0 comments on commit ed1af30

Please sign in to comment.