diff --git a/modeltrans/apps.py b/modeltrans/apps.py index b187047..9e0dd6c 100644 --- a/modeltrans/apps.py +++ b/modeltrans/apps.py @@ -4,7 +4,7 @@ import django.apps from django.apps import AppConfig -from .conf import check_fallback_chain +from .conf import check_fallback_chain, check_lang_code_duplicates from .translator import translate_model @@ -14,6 +14,7 @@ class RegistrationConfig(AppConfig): def ready(self): check_fallback_chain() + check_lang_code_duplicates() for Model in django.apps.apps.get_models(): translate_model(Model) diff --git a/modeltrans/conf.py b/modeltrans/conf.py index f043d2c..93d946e 100644 --- a/modeltrans/conf.py +++ b/modeltrans/conf.py @@ -26,12 +26,10 @@ def get_available_languages_setting(): defaults to the list of language codes extracted from django setting LANGUAGES """ languages = tuple( - set( - getattr( - settings, - "MODELTRANS_AVAILABLE_LANGUAGES", - (code for code, _ in getattr(settings, "LANGUAGES")), - ) + getattr( + settings, + "MODELTRANS_AVAILABLE_LANGUAGES", + (code for code, _ in getattr(settings, "LANGUAGES")), ) ) @@ -48,14 +46,13 @@ def get_available_languages(include_default=True): """ Returns a tuple of available languages for django-modeltrans. """ - MODELTRANS_AVAILABLE_LANGUAGES = get_available_languages_setting() + MODELTRANS_AVAILABLE_LANGUAGES = tuple(get_available_languages_setting()) if include_default: - return tuple( - set(itertools.chain(MODELTRANS_AVAILABLE_LANGUAGES, (get_default_language(),))) - ) - else: - return MODELTRANS_AVAILABLE_LANGUAGES + default_language = get_default_language() + if default_language not in MODELTRANS_AVAILABLE_LANGUAGES: + return tuple(itertools.chain((default_language,), MODELTRANS_AVAILABLE_LANGUAGES)) + return MODELTRANS_AVAILABLE_LANGUAGES def check_fallback_chain(): @@ -77,6 +74,17 @@ def check_fallback_chain(): raise ImproperlyConfigured(message_fmt.format(l)) +def check_lang_code_duplicates(): + available_languages = get_available_languages() + if len(available_languages) != len(set(available_languages)): + raise ImproperlyConfigured( + ( + "MODELTRANS_AVAILABLE_LANGUAGES or LANGUAGES " + "should not contain duplicates, current list: {}" + ).format(available_languages) + ) + + def get_fallback_chain(lang): """ Returns the list of fallback languages for language `lang`. diff --git a/tests/test_conf.py b/tests/test_conf.py index bd06697..066b1c6 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -1,7 +1,12 @@ from django.core.exceptions import ImproperlyConfigured from django.test import TestCase, override_settings -from modeltrans.conf import check_fallback_chain, get_available_languages_setting +from modeltrans.conf import ( + check_fallback_chain, + check_lang_code_duplicates, + get_available_languages, + get_available_languages_setting, +) class FallbackConfTest(TestCase): @@ -37,3 +42,16 @@ def test_available_languages_should_be_str(self): message = "MODELTRANS_AVAILABLE_LANGUAGES should be an iterable of strings" with self.assertRaisesMessage(ImproperlyConfigured, message): get_available_languages_setting() + + @override_settings(MODELTRANS_AVAILABLE_LANGUAGES=("nl", "nl", "de")) + def test_lang_code_duplicates_validation(self): + message = ( + "MODELTRANS_AVAILABLE_LANGUAGES or LANGUAGES should not contain duplicates, current list: {}" + ).format(get_available_languages()) + with self.assertRaisesMessage(ImproperlyConfigured, message): + check_lang_code_duplicates() + + @override_settings(MODELTRANS_AVAILABLE_LANGUAGES=("nl", "bg", "ar"), LANGUAGE_CODE="en") + def test_languages_ordering(self): + self.assertEqual(("en", "nl", "bg", "ar"), get_available_languages()) + self.assertEqual(("nl", "bg", "ar"), get_available_languages(include_default=False)) diff --git a/tox.ini b/tox.ini index 3b23571..e6228cf 100644 --- a/tox.ini +++ b/tox.ini @@ -23,7 +23,7 @@ basepython = # workaround for Error installing '...django-tables2': editable mode is not supported for pyproject.toml-style projects. # https://github.com/pypa/pip/issues/6434 -install_command = python -m pip install --no-use-pep517 {opts} {packages} +# install_command = python -m pip install --no-use-pep517 {opts} {packages} usedevelop = true pip_pre = true