Skip to content

[Django 4.1+] Make i18n works for LANGUAGE_CODE with a country code #206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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",
)