feat(#248): bootstrap django i18n from shared locale contract
This commit is contained in:
@@ -1,37 +1,27 @@
|
|||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
from functools import lru_cache
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from django.http import HttpRequest, JsonResponse
|
from django.http import HttpRequest, JsonResponse
|
||||||
from django.utils.translation import get_language_from_request
|
from django.utils.translation import get_language_from_request
|
||||||
|
|
||||||
|
from partyhub.i18n_bootstrap import locale_config, shared_i18n_catalog
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=1)
|
|
||||||
def lobby_i18n_catalog() -> dict:
|
def lobby_i18n_catalog() -> dict:
|
||||||
catalog_path = Path(__file__).resolve().parents[1] / "shared" / "i18n" / "lobby.json"
|
return shared_i18n_catalog()
|
||||||
with catalog_path.open(encoding="utf-8") as handle:
|
|
||||||
return json.load(handle)
|
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=1)
|
|
||||||
def i18n_locale_config() -> tuple[str, tuple[str, ...]]:
|
def i18n_locale_config() -> tuple[str, tuple[str, ...]]:
|
||||||
locales = lobby_i18n_catalog().get("locales", {})
|
return locale_config()
|
||||||
default_locale = str(locales.get("default", "en")).strip().lower() or "en"
|
|
||||||
supported_locales = tuple(
|
|
||||||
locale.strip().lower() for locale in locales.get("supported", ["en", "da"]) if str(locale).strip()
|
|
||||||
) or ("en", "da")
|
|
||||||
return default_locale, supported_locales
|
|
||||||
|
|
||||||
|
|
||||||
def lobby_i18n_errors() -> dict:
|
def lobby_i18n_errors() -> dict:
|
||||||
return lobby_i18n_catalog().get("backend", {}).get("error_codes", {})
|
return shared_i18n_catalog().get("backend", {}).get("error_codes", {})
|
||||||
|
|
||||||
|
|
||||||
def lobby_i18n_error_messages() -> dict:
|
def lobby_i18n_error_messages() -> dict:
|
||||||
return lobby_i18n_catalog().get("backend", {}).get("errors", {})
|
return shared_i18n_catalog().get("backend", {}).get("errors", {})
|
||||||
|
|
||||||
|
|
||||||
def _quality_value(language_candidate: str) -> float | None:
|
def _quality_value(language_candidate: str) -> float | None:
|
||||||
|
|||||||
30
partyhub/i18n_bootstrap.py
Normal file
30
partyhub/i18n_bootstrap.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import json
|
||||||
|
from functools import lru_cache
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
_LOCALE_LABELS = {
|
||||||
|
"en": "English",
|
||||||
|
"da": "Danish",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def shared_i18n_catalog() -> dict:
|
||||||
|
catalog_path = Path(__file__).resolve().parents[1] / "shared" / "i18n" / "lobby.json"
|
||||||
|
with catalog_path.open(encoding="utf-8") as handle:
|
||||||
|
return json.load(handle)
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def locale_config() -> tuple[str, tuple[str, ...]]:
|
||||||
|
locales = shared_i18n_catalog().get("locales", {})
|
||||||
|
default_locale = str(locales.get("default", "en")).strip().lower() or "en"
|
||||||
|
supported_locales = tuple(
|
||||||
|
locale.strip().lower() for locale in locales.get("supported", ["en", "da"]) if str(locale).strip()
|
||||||
|
) or ("en", "da")
|
||||||
|
return default_locale, supported_locales
|
||||||
|
|
||||||
|
|
||||||
|
def django_languages() -> list[tuple[str, str]]:
|
||||||
|
_default_locale, supported_locales = locale_config()
|
||||||
|
return [(locale, _LOCALE_LABELS.get(locale, locale.upper())) for locale in supported_locales]
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from partyhub.i18n_bootstrap import django_languages, locale_config
|
||||||
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
@@ -90,11 +92,8 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||||||
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
|
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
|
||||||
]
|
]
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en'
|
LANGUAGE_CODE, _SUPPORTED_LOCALES = locale_config()
|
||||||
LANGUAGES = [
|
LANGUAGES = django_languages()
|
||||||
('en', 'English'),
|
|
||||||
('da', 'Danish'),
|
|
||||||
]
|
|
||||||
LOCALE_PATHS = [BASE_DIR / 'locale']
|
LOCALE_PATHS = [BASE_DIR / 'locale']
|
||||||
TIME_ZONE = 'Europe/Copenhagen'
|
TIME_ZONE = 'Europe/Copenhagen'
|
||||||
USE_I18N = True
|
USE_I18N = True
|
||||||
|
|||||||
28
partyhub/tests_i18n_bootstrap.py
Normal file
28
partyhub/tests_i18n_bootstrap.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from partyhub.i18n_bootstrap import django_languages, locale_config, shared_i18n_catalog
|
||||||
|
|
||||||
|
|
||||||
|
class I18nBootstrapTests(TestCase):
|
||||||
|
def test_shared_catalog_bootstraps_default_and_supported_locales(self):
|
||||||
|
default_locale, supported_locales = locale_config()
|
||||||
|
|
||||||
|
self.assertEqual(default_locale, "en")
|
||||||
|
self.assertEqual(supported_locales, ("en", "da"))
|
||||||
|
|
||||||
|
def test_django_language_settings_bootstrap_from_shared_i18n_catalog(self):
|
||||||
|
default_locale, supported_locales = locale_config()
|
||||||
|
|
||||||
|
self.assertEqual(settings.LANGUAGE_CODE, default_locale)
|
||||||
|
self.assertEqual(tuple(code for code, _ in settings.LANGUAGES), supported_locales)
|
||||||
|
self.assertEqual(settings.LANGUAGES, django_languages())
|
||||||
|
|
||||||
|
def test_locale_contract_in_catalog_matches_django_language_codes(self):
|
||||||
|
catalog_locales = shared_i18n_catalog()["locales"]
|
||||||
|
|
||||||
|
self.assertEqual(settings.LANGUAGE_CODE, catalog_locales["default"])
|
||||||
|
self.assertEqual(
|
||||||
|
[code for code, _ in settings.LANGUAGES],
|
||||||
|
catalog_locales["supported"],
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user