forked from ungleich-public/dynamicweb
255 lines
7.8 KiB
Python
255 lines
7.8 KiB
Python
from contextlib import contextmanager
|
|
|
|
from django.conf import settings
|
|
from django.urls import LocalePrefixPattern, get_resolver
|
|
from django.utils import translation
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from cms.exceptions import LanguageError
|
|
from cms.utils.compat.warnings import RemovedInDjangoCMS60Warning
|
|
from cms.utils.conf import get_cms_setting, get_site_id
|
|
|
|
|
|
def _ensure_site_id(site_id, name):
|
|
"""
|
|
Ensure that the site_id is an integer.
|
|
"""
|
|
if site_id is None:
|
|
import warnings
|
|
|
|
warnings.warn(
|
|
f"{name} called without specifying 'site_id'. This may lead to unexpected behavior. "
|
|
f"Call {name} with 'site_id=<some_id>' instead.", RemovedInDjangoCMS60Warning, stacklevel=3
|
|
)
|
|
return get_site_id(None)
|
|
return site_id
|
|
|
|
|
|
@contextmanager
|
|
def force_language(new_lang):
|
|
old_lang = get_current_language()
|
|
if old_lang != new_lang:
|
|
translation.activate(new_lang)
|
|
yield
|
|
translation.activate(old_lang)
|
|
|
|
|
|
def get_languages(site_id=None):
|
|
site_id = _ensure_site_id(site_id, "get_languages")
|
|
site_id = get_site_id(site_id)
|
|
result = get_cms_setting('LANGUAGES').get(site_id)
|
|
if not result:
|
|
result = []
|
|
defaults = get_cms_setting('LANGUAGES').get('default', {})
|
|
for code, name in settings.LANGUAGES:
|
|
lang = {'code': code, 'name': _(name)}
|
|
lang.update(defaults)
|
|
result.append(lang)
|
|
get_cms_setting('LANGUAGES')[site_id] = result
|
|
return result
|
|
|
|
|
|
def get_site_language_from_request(request, site_id=None):
|
|
from cms.utils import get_current_site
|
|
|
|
if site_id is None:
|
|
site_id = get_current_site(request).pk
|
|
|
|
# Level 1: language get parameter
|
|
language = request.GET.get('language', None)
|
|
if is_valid_site_language(language, site_id=site_id):
|
|
return language
|
|
|
|
# Level 2: LANGUAGE_CODE request parameter
|
|
language = getattr(request, 'LANGUAGE_CODE', None)
|
|
if is_valid_site_language(language, site_id=site_id):
|
|
return language
|
|
|
|
# Last resort: default language
|
|
return get_default_language_for_site(site_id=site_id)
|
|
|
|
|
|
def get_language_code(language_code, site_id=None):
|
|
"""
|
|
Returns language code while making sure it's in LANGUAGES
|
|
"""
|
|
if not language_code:
|
|
return None
|
|
|
|
site_id = _ensure_site_id(site_id, "get_language_code")
|
|
languages = get_language_list(site_id)
|
|
|
|
if language_code in languages: # direct hit
|
|
return language_code
|
|
|
|
for lang in languages:
|
|
if language_code.split('-')[0] == lang: # base language hit
|
|
return lang
|
|
if lang.split('-')[0] == language_code: # base language hit
|
|
return lang
|
|
return language_code
|
|
|
|
|
|
def get_current_language():
|
|
"""
|
|
Returns the currently active language
|
|
|
|
It's a replacement for Django's translation.get_language() to make sure the
|
|
LANGUAGE_CODE will be found in LANGUAGES.
|
|
Overcomes this issue: https://code.djangoproject.com/ticket/9340
|
|
"""
|
|
site_id = getattr(settings, 'SITE_ID', None)
|
|
language_code = translation.get_language()
|
|
if site_id:
|
|
return get_language_code(language_code, site_id=site_id)
|
|
|
|
# We do not know the site, return an entry from settings.LANGUAGES
|
|
languages = dict(getattr(settings, 'LANGUAGES', ((language_code, language_code), ))).keys()
|
|
|
|
if language_code in languages:
|
|
return language_code # direct hit
|
|
|
|
for lang in languages:
|
|
if language_code.split('-')[0] == lang: # base language hit
|
|
return lang
|
|
if lang.split('-')[0] == language_code: # base language hit
|
|
return lang
|
|
return language_code
|
|
|
|
|
|
def get_language_list(site_id=None):
|
|
"""
|
|
:return: returns a list of iso2codes for this site
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "get_language_list")
|
|
return ([lang['code'] for lang in get_languages(site_id)] if settings.USE_I18N
|
|
else [settings.LANGUAGE_CODE])
|
|
|
|
|
|
def get_language_tuple(site_id=None):
|
|
"""
|
|
:return: returns an list of tuples like the old CMS_LANGUAGES or the LANGUAGES for this site
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "get_language_tuple")
|
|
return [(lang['code'], lang['name']) for lang in get_languages(site_id)]
|
|
|
|
|
|
def get_language_dict(site_id=None):
|
|
"""
|
|
:return: returns an dict of cms languages
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "get_language_dict")
|
|
return dict(get_language_tuple(site_id))
|
|
|
|
|
|
def get_public_languages(site_id=None):
|
|
"""
|
|
:return: list of iso2codes of public languages for this site
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "get_public_languages")
|
|
return [lang['code'] for lang in get_language_objects(site_id)
|
|
if lang.get('public', True)]
|
|
|
|
|
|
def get_language_object(language_code, site_id=None):
|
|
"""
|
|
:param language_code: RFC5646 language code
|
|
:return: the language object filled up by defaults
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "get_language_object")
|
|
for language in get_languages(site_id):
|
|
if language['code'] == get_language_code(language_code, site_id):
|
|
return language
|
|
raise LanguageError('Language not found: %s' % language_code)
|
|
|
|
|
|
def get_language_objects(site_id=None):
|
|
"""
|
|
returns list of all language objects filled up by default values
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "get_language_objects")
|
|
return list(get_languages(site_id))
|
|
|
|
|
|
def get_default_language(language_code=None, site_id=None):
|
|
"""
|
|
Returns default language depending on settings.LANGUAGE_CODE merged with
|
|
best match from get_cms_setting('LANGUAGES')
|
|
|
|
Returns: language_code
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "get_default_language")
|
|
if not language_code:
|
|
language_code = get_language_code(settings.LANGUAGE_CODE, site_id=site_id)
|
|
|
|
languages = get_language_list(site_id)
|
|
|
|
# first try if there is an exact language
|
|
if language_code in languages:
|
|
return language_code
|
|
|
|
# otherwise split the language code if possible, so iso3
|
|
language_code = language_code.split("-")[0]
|
|
|
|
if language_code not in languages:
|
|
return settings.LANGUAGE_CODE
|
|
|
|
return language_code
|
|
|
|
|
|
def get_default_language_for_site(site_id):
|
|
return get_language_list(site_id)[0]
|
|
|
|
|
|
def get_fallback_languages(language, site_id=None):
|
|
"""
|
|
returns a list of fallback languages for the given language
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "get_fallback_languages")
|
|
try:
|
|
language = get_language_object(language, site_id)
|
|
except LanguageError:
|
|
language = get_languages(site_id)[0]
|
|
return language.get('fallbacks', [])
|
|
|
|
|
|
def get_redirect_on_fallback(language, site_id=None):
|
|
"""
|
|
returns if you should redirect on language fallback
|
|
:param language:
|
|
:param site_id:
|
|
:return: Boolean
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "get_redirect_on_fallback")
|
|
language = get_language_object(language, site_id)
|
|
return language.get('redirect_on_fallback', True)
|
|
|
|
|
|
def hide_untranslated(language, site_id=None):
|
|
"""
|
|
Should untranslated pages in this language be hidden?
|
|
:param language:
|
|
:param site_id:
|
|
:return: A Boolean
|
|
"""
|
|
site_id = _ensure_site_id(site_id, "hide_untranslated")
|
|
obj = get_language_object(language, site_id)
|
|
return obj.get('hide_untranslated', True)
|
|
|
|
|
|
def is_language_prefix_patterns_used():
|
|
"""
|
|
Returns `True` if the `LocaleRegexURLResolver` or `LocalePrefixPattern`
|
|
is used at root level of the urlpatterns and doesn't have empty
|
|
language_prefix, else it returns `False`.
|
|
"""
|
|
for url_pattern in get_resolver(None).url_patterns:
|
|
pattern = getattr(url_pattern, 'pattern', url_pattern)
|
|
if isinstance(pattern, LocalePrefixPattern):
|
|
if pattern.language_prefix != '':
|
|
return True
|
|
return False
|
|
|
|
|
|
def is_valid_site_language(language, site_id):
|
|
return language in get_language_list(site_id)
|