1# -*- coding: utf-8 -*- 2from contextlib import contextmanager 3 4from django.conf import settings 5from django.utils import translation 6from django.utils.translation import ugettext_lazy as _ 7from django.urls import get_resolver 8 9from cms.exceptions import LanguageError 10from cms.utils.compat.dj import LocalePrefixPattern 11from cms.utils.conf import get_cms_setting, get_site_id 12 13 14@contextmanager 15def force_language(new_lang): 16 old_lang = get_current_language() 17 if old_lang != new_lang: 18 translation.activate(new_lang) 19 yield 20 translation.activate(old_lang) 21 22 23def get_languages(site_id=None): 24 site_id = get_site_id(site_id) 25 result = get_cms_setting('LANGUAGES').get(site_id) 26 if not result: 27 result = [] 28 defaults = get_cms_setting('LANGUAGES').get('default', {}) 29 for code, name in settings.LANGUAGES: 30 lang = {'code': code, 'name': _(name)} 31 lang.update(defaults) 32 result.append(lang) 33 get_cms_setting('LANGUAGES')[site_id] = result 34 return result 35 36 37def get_site_language_from_request(request, site_id=None): 38 from cms.utils import get_current_site 39 40 language = request.GET.get('language', None) 41 42 if site_id is None: 43 site_id = get_current_site().pk 44 45 if is_valid_site_language(language, site_id=site_id): 46 return language 47 48 language = getattr(request, 'LANGUAGE_CODE', None) 49 50 if is_valid_site_language(language, site_id=site_id): 51 return language 52 return get_default_language_for_site(site_id=site_id) 53 54 55def get_language_code(language_code, site_id=None): 56 """ 57 Returns language code while making sure it's in LANGUAGES 58 """ 59 if not language_code: 60 return None 61 62 languages = get_language_list(site_id) 63 64 if language_code in languages: # direct hit 65 return language_code 66 67 for lang in languages: 68 if language_code.split('-')[0] == lang: # base language hit 69 return lang 70 if lang.split('-')[0] == language_code: # base language hit 71 return lang 72 return language_code 73 74 75def get_current_language(): 76 """ 77 Returns the currently active language 78 79 It's a replacement for Django's translation.get_language() to make sure the LANGUAGE_CODE will be found in LANGUAGES. 80 Overcomes this issue: https://code.djangoproject.com/ticket/9340 81 """ 82 language_code = translation.get_language() 83 return get_language_code(language_code) 84 85 86def get_language_list(site_id=None): 87 """ 88 :return: returns a list of iso2codes for this site 89 """ 90 return ([lang['code'] for lang in get_languages(site_id)] if settings.USE_I18N 91 else [settings.LANGUAGE_CODE]) 92 93 94def get_language_tuple(site_id=None): 95 """ 96 :return: returns an list of tuples like the old CMS_LANGUAGES or the LANGUAGES for this site 97 """ 98 return [(lang['code'], lang['name']) for lang in get_languages(site_id)] 99 100 101def get_language_dict(site_id=None): 102 """ 103 :return: returns an dict of cms languages 104 """ 105 return dict(get_language_tuple(site_id)) 106 107 108def get_public_languages(site_id=None): 109 """ 110 :return: list of iso2codes of public languages for this site 111 """ 112 return [lang['code'] for lang in get_language_objects(site_id) 113 if lang.get('public', True)] 114 115 116def get_language_object(language_code, site_id=None): 117 """ 118 :param language_code: RFC5646 language code 119 :return: the language object filled up by defaults 120 """ 121 for language in get_languages(site_id): 122 if language['code'] == get_language_code(language_code): 123 return language 124 raise LanguageError('Language not found: %s' % language_code) 125 126 127def get_language_objects(site_id=None): 128 """ 129 returns list of all language objects filled up by default values 130 """ 131 return list(get_languages(site_id)) 132 133 134def get_default_language(language_code=None, site_id=None): 135 """ 136 Returns default language depending on settings.LANGUAGE_CODE merged with 137 best match from get_cms_setting('LANGUAGES') 138 139 Returns: language_code 140 """ 141 if not language_code: 142 language_code = get_language_code(settings.LANGUAGE_CODE) 143 144 languages = get_language_list(site_id) 145 146 # first try if there is an exact language 147 if language_code in languages: 148 return language_code 149 150 # otherwise split the language code if possible, so iso3 151 language_code = language_code.split("-")[0] 152 153 if not language_code in languages: 154 return settings.LANGUAGE_CODE 155 156 return language_code 157 158 159def get_default_language_for_site(site_id): 160 return get_language_list(site_id)[0] 161 162 163def get_fallback_languages(language, site_id=None): 164 """ 165 returns a list of fallback languages for the given language 166 """ 167 try: 168 language = get_language_object(language, site_id) 169 except LanguageError: 170 language = get_languages(site_id)[0] 171 return language.get('fallbacks', []) 172 173 174def get_redirect_on_fallback(language, site_id=None): 175 """ 176 returns if you should redirect on language fallback 177 :param language: 178 :param site_id: 179 :return: Boolean 180 """ 181 language = get_language_object(language, site_id) 182 return language.get('redirect_on_fallback', True) 183 184 185def hide_untranslated(language, site_id=None): 186 """ 187 Should untranslated pages in this language be hidden? 188 :param language: 189 :param site_id: 190 :return: A Boolean 191 """ 192 obj = get_language_object(language, site_id) 193 return obj.get('hide_untranslated', True) 194 195 196def is_language_prefix_patterns_used(): 197 """ 198 Returns `True` if the `LocaleRegexURLResolver` or `LocalePrefixPattern` is 199 used at root level of the urlpatterns, else it returns `False`. 200 """ 201 return any( 202 isinstance( 203 getattr(url_pattern, 'pattern', url_pattern), 204 LocalePrefixPattern 205 ) 206 for url_pattern in get_resolver(None).url_patterns 207 ) 208 209 210def is_valid_site_language(language, site_id): 211 return language in get_language_list(site_id) 212