def negotiate_locale(preferred_locale: str, available_locales: List[str]) -> Optional[str]: negotiated_locale = babel.negotiate_locale([preferred_locale], available_locales) if negotiated_locale is not None: return negotiated_locale preferred_locale = preferred_locale.split('-', 1)[0] for available_locale in available_locales: negotiated_locale = babel.negotiate_locale( [preferred_locale], [available_locale.split('-', 1)[0]]) if negotiated_locale is not None: return available_locale
def set_best_lang(): """ Get the best language/locale for the current user. This means that first the session will be checked, and then in the absence of an explicitly-set language, we will try to guess it from the browser settings and only after that fall back to the server's default. """ if not has_request_context(): return 'en_GB' if current_app.config['TESTING'] else HelperMaKaCInfo.getMaKaCInfoInstance().getLang() elif session.lang is not None: return session.lang # try to use browser language preferred = [x.replace('-', '_') for x in request.accept_languages.values()] resolved_lang = negotiate_locale(preferred, list(get_all_locales()), aliases=LOCALE_ALIASES) if not resolved_lang: if current_app.config['TESTING']: return 'en_GB' with DBMgr.getInstance().global_connection(): # fall back to server default minfo = HelperMaKaCInfo.getMaKaCInfoInstance() resolved_lang = minfo.getLang() session.lang = resolved_lang return resolved_lang
def getkey(self, key): locales = [] for locale, strings in self._data.items(): if key in strings: locales += [locale] locale = negotiate_locale(self._languages, locales) return self._data.get(locale, {}).get(key, False)
def set_best_lang(): """ Get the best language/locale for the current user. This means that first the session will be checked, and then in the absence of an explicitly-set language, we will try to guess it from the browser settings and only after that fall back to the server's default. """ if not has_request_context(): return 'en_GB' if current_app.config[ 'TESTING'] else HelperMaKaCInfo.getMaKaCInfoInstance().getLang() elif session.lang is not None: return session.lang # try to use browser language preferred = [ x.replace('-', '_') for x in request.accept_languages.values() ] resolved_lang = negotiate_locale(preferred, list(get_all_locales()), aliases=LOCALE_ALIASES) if not resolved_lang: if current_app.config['TESTING']: return 'en_GB' with DBMgr.getInstance().global_connection(): # fall back to server default minfo = HelperMaKaCInfo.getMaKaCInfoInstance() resolved_lang = minfo.getLang() session.lang = resolved_lang return resolved_lang
def detect_language(): if 'lang' in request.args: requested_locale = request.args['lang'] locales = [unicode(l) for l in babel.list_translations()] locale = negotiate_locale([requested_locale,], locales) session['locale'] = locale flask_babel.refresh()
def set_best_lang(check_session=True): """ Get the best language/locale for the current user. This means that first the session will be checked, and then in the absence of an explicitly-set language, we will try to guess it from the browser settings and only after that fall back to the server's default. """ from indico.core.config import Config if not has_request_context(): return 'en_GB' if current_app.config['TESTING'] else Config.getInstance().getDefaultLocale() elif 'lang' in g: return g.lang elif check_session and session.lang is not None: return session.lang # try to use browser language preferred = [x.replace('-', '_') for x in request.accept_languages.values()] resolved_lang = negotiate_locale(preferred, list(get_all_locales()), aliases=LOCALE_ALIASES) if not resolved_lang: if current_app.config['TESTING']: return 'en_GB' # fall back to server default resolved_lang = Config.getInstance().getDefaultLocale() # As soon as we looked up a language, cache it during the request. # This will be returned when accessing `session.lang` since there's code # which reads the language from there and might fail (e.g. by returning # lazy strings) if it's not set. g.lang = resolved_lang return resolved_lang
def gettext(self, english_text): locales = [] for locale, strings in self._data.items(): if english_text in strings: locales += [locale] locale = negotiate_locale(self._languages, locales) return self._data.get(locale, {}).get(english_text, english_text)
def get_user_locale(): preferred = [x.replace('-', '_') for x in request.accept_languages.values()] if 'l' in request.args: preferred = [request.args['l']] elif 'fb_locale' in request.args: preferred = [request.args['fb_locale']] return negotiate_locale(preferred, AVAILABLE_LOCALES)
def set_best_lang(check_session=True): """ Get the best language/locale for the current user. This means that first the session will be checked, and then in the absence of an explicitly-set language, we will try to guess it from the browser settings and only after that fall back to the server's default. """ from indico.core.config import config if not has_request_context(): return 'en_GB' if current_app.config['TESTING'] else config.DEFAULT_LOCALE elif 'lang' in g: return g.lang elif check_session and session.lang is not None: return session.lang # try to use browser language preferred = [x.replace('-', '_') for x in request.accept_languages.values()] resolved_lang = negotiate_locale(preferred, list(get_all_locales()), aliases=LOCALE_ALIASES) if not resolved_lang: if current_app.config['TESTING']: return 'en_GB' # fall back to server default resolved_lang = config.DEFAULT_LOCALE # As soon as we looked up a language, cache it during the request. # This will be returned when accessing `session.lang` since there's code # which reads the language from there and might fail (e.g. by returning # lazy strings) if it's not set. g.lang = resolved_lang return resolved_lang
def set_best_lang(check_session=True): """Get the best language/locale for the current user. This means that first the session will be checked, and then in the absence of an explicitly-set language, we will try to guess it from the browser settings and only after that fall back to the server's default. """ from indico.core.config import config if not has_request_context(): return 'en_GB' if current_app.config[ 'TESTING'] else config.DEFAULT_LOCALE elif 'lang' in g: return g.lang elif check_session and session.lang is not None: return session.lang # chinese uses `zh-Hans-CN`, but browsers send `zh-CN` all_locales = { _remove_locale_script(loc).lower(): loc for loc in get_all_locales() } # try to use browser language preferred = [ x.replace('-', '_') for x in request.accept_languages.values() ] resolved_lang = negotiate_locale(preferred, list(all_locales), aliases=LOCALE_ALIASES) if not resolved_lang: if current_app.config['TESTING']: return 'en_GB' # fall back to server default resolved_lang = config.DEFAULT_LOCALE # restore script information if necessary try: resolved_lang = all_locales[resolved_lang.lower()] except KeyError: # this happens if we have e.g. a development setup with no built languages. # in this case `get_all_locales()` only contains `en_EN` return 'en_GB' # normalize to xx_YY capitalization resolved_lang = re.sub( r'^([a-zA-Z]+)_([a-zA-Z]+)$', lambda m: '{}_{}'.format(m.group(1).lower(), m.group(2).upper()), resolved_lang) # As soon as we looked up a language, cache it during the request. # This will be returned when accessing `session.lang` since there's code # which reads the language from there and might fail (e.g. by returning # lazy strings) if it's not set. g.lang = resolved_lang return resolved_lang
def get_locale(): user = getattr(g, 'user', None) if user is not None: return user.locale or 'en' preferred = [ x.replace('-', '_') for x in list(request.accept_languages.values()) ] return negotiate_locale(preferred, ['pt_BR', 'en_US'])
def getkey(self, key, lang_code=None): locales = [] for locale, strings in self._data.items(): if key in strings: locales += [locale] target_locales = [lang_code] if lang_code else self._languages locale = negotiate_locale(target_locales, locales) return self._data.get(locale, {}).get(key, False)
def get_locale(locale=None): global locales if locales is None: locales = babel.localedata.list() locale = util_get_locale(locale) return babel.negotiate_locale([locale, 'en'], locales)
def get_locale(): from_cookie = request.cookies.get('lang', None) if from_cookie and from_cookie in config.LOCALE_PREFER: return from_cookie else: preferred = [x.replace('-', '_') for x in request.accept_languages.values()] return negotiate_locale(preferred, config.LOCALE_PREFER)
def __get_language_match(self, languageCode, languageIds): """Compares ``languageCode`` to the provided ``languageIds`` to find the closest match and returns it, if a match is not found returns ``None``. e.g. if ``languageCode`` is ``en_CA`` and ``languageIds`` contains ``en``, the return value will be ``en`` """ # special case if languageCode == 'zh': return 'zh-Hans' # this will take care of cases such as mapping en_CA to en if '-' in languageCode: match = negotiate_locale([languageCode], languageIds, sep='-') else: match = negotiate_locale([languageCode], languageIds) if match: return match # handle other cases if '-' in languageCode: locale = Locale.parse(languageCode, sep='-') else: locale = Locale.parse(languageCode) for languageId in languageIds: if '-' not in languageId: continue # normalize the languageId nLanguageId = Locale.parse(languageId, sep='-') # 1. lang subtag must match # 2. either script or territory subtag must match AND # one of them must not be None, i.e. do not allow None == None if locale.language == nLanguageId.language and \ (((locale.script or nLanguageId.script) and (locale.script == nLanguageId.script)) or \ (locale.territory or nLanguageId.territory) and (locale.territory == nLanguageId.territory)): return languageId return None
def get_locale(): locales = app.config.get("LOCALES", {}).keys() sent = request.accept_languages.values() g.locale = negotiate_locale((v.replace("-", "_") for v in sent), locales) if not g.locale: g.locale = "en" return g.locale
def get_locale(): from_cookie = request.cookies.get('lang', None) if from_cookie and from_cookie in config.LOCALE_PREFER: return from_cookie else: preferred = [ x.replace('-', '_') for x in request.accept_languages.values() ] return negotiate_locale(preferred, config.LOCALE_PREFER)
def select_language(self, lang: str): """ Usage: with Jinja2Env().select_language(lang) as env: txt = env.get_template('template.jinja2').render(*args, **kwargs) """ neg_lang = babel.negotiate_locale(preferred=[lang], available=self.translations.keys()) translation = self.translations.get(neg_lang, self.translations['en']) # install_gettext_translations is available when instantiating env with extension jinja2.ext.i18n self.env.install_gettext_translations(translation, newstyle=True) yield self.env
def __init__( self, request, locales, default_locale=(None, None), dirname=None, domain=None, timezone=None, default_timezone=None ): """ A locale with negotiated language and territory In: - ``request`` -- the HTTP request object - ``locales`` -- tuples of (language, territory) accepted by the application (i.e ``[('fr', 'FR'), ('de', 'DE'), ('en',)]``) - ``default_locale`` -- tuple of (language, territory) to use if the negociation failed - ``dirname`` -- the directory containing the ``MO`` files - ``domain`` -- the messages domain - ``timezone`` -- the timezone (timezone object or code) (i.e ``pytz.timezone('America/Los_Angeles')`` or ``America/Los_Angeles``) - ``default_timezone`` -- default timezone when a ``datetime`` object has no associated timezone. If no default timezone is given, the ``timezone`` value is used """ locale = negotiate_locale( request.accept_language, map('-'.join, locales), '-' ) if not locale: language, territory = (default_locale + (None,))[:2] else: locale = core.LOCALE_ALIASES.get(locale, locale).replace('_', '-') if '-' not in locale: language = locale territory = None else: language, territory = locale.split('-') territory = territory.upper() super(NegotiatedLocale, self).__init__( language, territory, dirname=dirname, domain=domain, timezone=timezone, default_timezone=default_timezone )
def __init__( self, request, locales, default_locale=(None, None), dirname=None, domain=None, timezone=None, default_timezone=None ): """ A locale with negotiated language and territory In: - ``request`` -- the HTTP request object - ``locales`` -- tuples of (language, territory) accepted by the application (i.e ``[('fr', 'FR'), ('de', 'DE'), ('en',)]``) - ``default_locale`` -- tuple of (language, territory) to use if the negociation failed - ``dirname`` -- the directory containing the ``MO`` files - ``domain`` -- the messages domain - ``timezone`` -- the timezone (timezone object or code) (i.e ``pytz.timezone('America/Los_Angeles')`` or ``America/Los_Angeles``) - ``default_timezone`` -- default timezone when a ``datetime`` object has no associated timezone. If no default timezone is given, the ``timezone`` value is used """ locale = negotiate_locale( map(itemgetter(0), sorted(request.accept_language.parsed or (), key=itemgetter(1), reverse=True)), ['-'.join(locale).rstrip('-') for locale in locales], '-' ) if not locale: language, territory = (default_locale + (None,))[:2] else: locale = core.LOCALE_ALIASES.get(locale, locale).replace('_', '-') if '-' not in locale: language = locale territory = None else: language, territory = locale.split('-') territory = territory.upper() super(NegotiatedLocale, self).__init__( language, territory, dirname=dirname, domain=domain, timezone=timezone, default_timezone=default_timezone )
def negotiate_localizeds(preferred_locale: str, localizeds: Iterable[Localized]) -> Localized: localizeds = list(localizeds) negotiated_locale = negotiate_locale( [preferred_locale], map(lambda localized: localized.locale, localizeds), '-') if negotiated_locale is None: if len(localizeds) > 0: return localizeds[0] else: raise ValueError( 'Cannot negotiate if there are no localized values.') for localized in localizeds: if localized.locale == negotiated_locale: return localized
def get_locale(): # if a user is logged in, use the locale from the user settings user = getattr(g, 'user', None) if user is not None and hasattr(user, "locale"): if user.name != 'Guest': # if the account is the guest account bypass the config lang settings return user.locale preferred = list() if request.accept_languages: for x in request.accept_languages.values(): try: preferred.append(str(Locale.parse(x.replace('-', '_')))) except (UnknownLocaleError, ValueError) as e: log.debug('Could not parse locale "%s": %s', x, e) return negotiate_locale(preferred or ['en'], get_available_translations())
def get_locale(): if current_user() and current_user().locale_code: return current_user().locale_code # look for session variable in pre-logged-in state # confirm request context - not available from celery tasks if has_request_context(): if session.get('locale_code'): return session['locale_code'] browser_pref = negotiate_locale( preferred=(l.replace('-', '_') for l in request.accept_languages.values()), available=(c.code for c in Coding.query.filter_by( system=IETF_LANGUAGE_TAG)), ) if browser_pref: return browser_pref return current_app.config.get("DEFAULT_LOCALE")
def negociate_locale(): # if a user is logged in, use the locale from the user settings user = getattr(g, 'user', None) # user = None if user is not None and hasattr(user, "locale"): if user.nickname != 'Guest': # if the account is the guest account bypass the config lang settings return user.locale preferred = set() if request.accept_languages: for x in request.accept_languages.values(): try: preferred.add(str(LC.parse(x.replace('-', '_')))) except (UnknownLocaleError, ValueError) as e: log.warning('Could not parse locale "%s": %s', x, e) # preferred.append('en') return negotiate_locale(preferred or ['en'], _BABEL_TRANSLATIONS)
def select_locale(): """Select a suitable locale Try to pick a locale from the following ordered sources: 1. The user's explicit locale setting 2. The best match according to the ``Accept-Language`` request header :returns: The locale string :rtype: str """ locale = get_user_locale_setting() if locale is not None: return str(locale) return negotiate_locale( request.accept_languages.values(), list(map(str, possible_locales())), sep='-')
def get_locale(): if current_user() and current_user().locale_code: return current_user().locale_code # look for session variable in pre-logged-in state # confirm request context - not available from celery tasks if has_request_context(): if session.get('locale_code'): return session['locale_code'] browser_pref = negotiate_locale( preferred=( l.replace('-', '_') for l in request.accept_languages.values() ), available=( c.code for c in Coding.query.filter_by(system=IETF_LANGUAGE_TAG) ), ) if browser_pref: return browser_pref return current_app.config.get("DEFAULT_LOCALE")
def get_locale(): # Safari (macOS and iOS) sends Accept-Language: zh-cn, but Werkzeug cannot # match it to zh. Fix it here. # https://github.com/pallets/werkzeug/issues/450#issuecomment-26621966 preferred = [x.replace('-', '_') for x in request.accept_languages.values()] locale = negotiate_locale(preferred, settings['locales'].keys()) if request.preferences.get_value('locale') != '': locale = request.preferences.get_value('locale') if 'locale' in request.args\ and request.args['locale'] in settings['locales']: locale = request.args['locale'] if 'locale' in request.form\ and request.form['locale'] in settings['locales']: locale = request.form['locale'] if locale == 'zh_TW': locale = 'zh_Hant_TW' return locale
def get_locale(): preferred = [x.replace('-', '_') for x in request.accept_languages.values()] return negotiate_locale(preferred, config.SUPPORTED_LOCALES)
def negotiate_locale(self, accept_langs): def normalize_locale(loc): return unicode(loc).replace('-', '_') langs = map(normalize_locale, accept_langs) return negotiate_locale(langs, self.available_locales, sep="_") or self.default_locale_name
def get_locale(): preferred = [ x.replace('-', '_') for x in request.accept_languages.values() ] return negotiate_locale(preferred, config.SUPPORTED_LOCALES)
def _init_translate(self, alert): """Run in background at startup, initializes data, contacts server, does that sort of setup procedure. """ # XXX: Maybe instead of failing here, how about creating a transient # local server, would use whatever web APIs possible. Not really # sure. if not self.client.can_connect(): self.remove_alert(alert) self._create_alert( _("Connection error"), _("Couldn't connect to the server!")) from_lang_store = self.lang_from.get_model() # Try to set the default from language selection to the user's # locale. # XXX: If default_locale fails (theoretically could if ENV isn't # proper), this will raise babel.core.UnknownLocaleError. locale = babel.default_locale(category="LANG") self.locale = Locale(locale) self._logger.info("Setting locale to %s", repr(self.locale)) pairs = self.client.language_pairs() from_langs = set() # TODO: maybe try falling back to first two letters? for pair in pairs: try: from_locale = Locale.parse(pair[0]) from_name = from_locale.get_language_name(self.locale) except (babel.UnknownLocaleError, ValueError): # Fall back to language code from_name = pair[0] self._logger.error('Failed to get a locale for %s', pair[0]) from_langs.add((pair[0], from_name)) from_langs = sorted(list(from_langs), (lambda x, y: cmp(x[1], y[1]))) for lang in from_langs: from_lang_store.append(lang) # Fall back to whatever the first option is. self.lang_from.set_active(0) for idx, lang in enumerate(from_langs): # Check if the user's locale is "good enough". # # e.g. if locale is "en_US", and "en" is in the combobox, then will # return non-None. if babel.negotiate_locale([lang[0]], [locale]) is not None: self.lang_from.set_active(idx) break # Make sure the to_lang combobox is up to date self._lang_from_changed_cb(self.lang_from) # Enable the button self.translate_button.set_sensitive(True) self.remove_alert(alert)