def set_translators(): global _lang_trans, lcdata # To test different translations invoke as # CALIBRE_OVERRIDE_LANG=de_DE.utf8 program lang = get_lang() t = buf = iso639 = None if 'CALIBRE_TEST_TRANSLATION' in os.environ: buf = load_po( os.path.expanduser(os.environ['CALIBRE_TEST_TRANSLATION'])) if lang: mpath = get_lc_messages_path(lang) if buf is None and mpath and os.access(mpath + '.po', os.R_OK): buf = load_po(mpath + '.po') if mpath is not None: from zipfile import ZipFile with ZipFile( P('localization/locales.zip', allow_user_override=False), 'r') as zf: if buf is None: buf = cStringIO.StringIO(zf.read(mpath + '/messages.mo')) if mpath == 'nds': mpath = 'de' isof = mpath + '/iso639.mo' try: iso639 = cStringIO.StringIO(zf.read(isof)) except: pass # No iso639 translations for this lang if buf is not None: try: lcdata = cPickle.loads( zf.read(mpath + '/lcdata.pickle')) except: pass # No lcdata if buf is not None: t = GNUTranslations(buf) if iso639 is not None: iso639 = _lang_trans = GNUTranslations(iso639) t.add_fallback(iso639) if t is None: t = NullTranslations() try: set_translators.lang = t.info().get('language') except Exception: pass t.install(unicode=True, names=('ngettext', )) # Now that we have installed a translator, we have to retranslate the help # for the global prefs object as it was instantiated in get_lang(), before # the translator was installed. from calibre.utils.config_base import prefs prefs.retranslate_help()
def set_translators(): global _lang_trans, lcdata # To test different translations invoke as # CALIBRE_OVERRIDE_LANG=de_DE.utf8 program lang = get_lang() t = None if lang: buf = iso639 = None mpath = get_lc_messages_path(lang) if mpath and os.access(mpath+'.po', os.R_OK): from calibre.translations.msgfmt import make buf = cStringIO.StringIO() try: make(mpath+'.po', buf) except: print (('Failed to compile translations file: %s,' ' ignoring')%(mpath+'.po')) buf = None else: buf = cStringIO.StringIO(buf.getvalue()) if mpath is not None: from zipfile import ZipFile with ZipFile(P('localization/locales.zip', allow_user_override=False), 'r') as zf: if buf is None: buf = cStringIO.StringIO(zf.read(mpath + '/messages.mo')) if mpath == 'nds': mpath = 'de' isof = mpath + '/iso639.mo' try: iso639 = cStringIO.StringIO(zf.read(isof)) except: pass # No iso639 translations for this lang if buf is not None: try: lcdata = cPickle.loads(zf.read(mpath + '/lcdata.pickle')) except: pass # No lcdata if buf is not None: t = GNUTranslations(buf) if iso639 is not None: iso639 = _lang_trans = GNUTranslations(iso639) t.add_fallback(iso639) if t is None: t = NullTranslations() t.install(unicode=True, names=('ngettext',)) # Now that we have installed a translator, we have to retranslate the help # for the global prefs object as it was instantiated in get_lang(), before # the translator was installed. from calibre.utils.config_base import prefs prefs.retranslate_help()
def require_current_locale_being(locale): current_locales.append(locale) try: translations = load_translations(locale=locale) translations.install(unicode=True) with require_current_translations_being(translations): yield finally: NullTranslations().install(unicode=True) current_locales.pop()
def get(self, langcode, fallback=NullTranslations()): try: fallback_langcodes = self.trans[langcode] except KeyError: return fallback else: return translation( self.domain, self.localedir, [langcode] + list(fallback_langcodes), fallback=self.fallback, codeset=self.codeset)
def set_locale(self, locales, trans_dir=None): if locales[0] is None or "en" in locales[0].lower(): self.trans = NullTranslations() return if "cn" in locales[0].lower(): locales = ["zh_Hans_CN"] try: if trans_dir is None: trans_dir = os.path.join( os.path.dirname(os.path.abspath(__file__, ), ), "translations") self.trans = translation( domain="messages", localedir=trans_dir, languages=locales, ) except Exception as e: system_log.debug(e) self.trans = NullTranslations()
def pylons_formencode_gettext(value): from pylons.i18n import ugettext as pylons_gettext from gettext import NullTranslations trans = pylons_gettext(value) # Translation failed, try formencode if trans == value: try: fetrans = pylons.c.formencode_translation except AttributeError, attrerror: # the translator was not set in the Pylons context # we are certainly in the test framework # let's make sure won't return something that is ok with the caller fetrans = NullTranslations() if not fetrans: fetrans = NullTranslations() trans = fetrans.ugettext(value)
def get_translator(bcp_47_code): parts = bcp_47_code.replace('-', '_').split('_')[:2] parts[0] = lang_as_iso639_1(parts[0].lower()) or 'en' if len(parts) > 1: parts[1] = parts[1].upper() lang = '_'.join(parts) lang = {'pt': 'pt_BR', 'zh': 'zh_CN'}.get(lang, lang) available = available_translations() found = True if lang == 'en' or lang.startswith('en_'): return found, lang, NullTranslations() if lang not in available: lang = {'pt': 'pt_BR', 'zh': 'zh_CN'}.get(parts[0], parts[0]) if lang not in available: lang = get_lang() if lang not in available: lang = 'en' found = False if lang == 'en': return True, lang, NullTranslations() return found, lang, get_single_translator(lang)
def set_locale(locales, trans_dir=translation_dir): global current_translation try: current_translation = translation( domain="messages", localedir=trans_dir, languages=locales, ) except Exception as e: system_log.debug(e) current_translation = NullTranslations()
def init_localization(language): """prepare l10n""" try: # Language message file filename = os.path.join(os.path.abspath(os.path.dirname(__file__)), "../res/%s.mo" % language) logger.info("Opening message file %s for locale %s", filename, language) translation = GNUTranslations(open(filename, "rb")) translation.install() except IOError: logger.warning("Locale not found. Using default messages") logger.debug("Backtrace: %s", traceback.format_exc()) default = NullTranslations() default.install() except Exception as e: logger.error("Locale not found. Exception: %s", str(e)) logger.debug("Backtrace: %s", traceback.format_exc()) default = NullTranslations() default.install() logger.info(_("Language is English (default)..."))
def set_lang(lang, pkgname, localedir): "Set language" if not lang: translator = NullTranslations() else: if not isinstance(lang, list): lang = [lang] translator = translation( pkgname, localedir, languages=lang ) return translator
def translation(domain, localedir=None, languages=None, _class=None, fallback=False, codeset=None): """Similar to gettext.translation() but also search inside ZIP archives if this module is loaded from one. """ if languages is None: languages = get_languages() archive = __archive__ if (localedir is None or archive is None or not startswith_token(localedir, archive, os.sep)): return _gettext.translation(domain, localedir, languages, _class, fallback, codeset) languages = tuple(unique(get_fallback_languages(languages))) translations = None if languages: assert startswith_token(localedir, archive, dirseps) localedir = strip(localedir, dirseps, start=len(archive) + len(os.sep)) locale_suffix = os.path.join('LC_MESSAGES', os.extsep.join((domain, 'mo'))) with ZipFile(archive) as archive: #archive.debug = 3 for lang in languages: lang_path = os.path.join(localedir, lang, locale_suffix) #print('Trying', lang_path, '...', file=sys.stderr) translation_file = archive.open(lang_path, follow_symlinks=True, fail_missing=False) if translation_file is not None: with translation_file: #print("Found language '{:s}' at '{:s}'.".format(lang, lang_path)) translations = ((_class or GNUTranslations)(translation_file)) break if translations is None: if not fallback: raise OSError("No translation in '{:s}:{:s}' for: {:s}".format( archive, localedir, ', '.join(languages))) translations = NullTranslations() if codeset is not None: translations.set_output_charset(codeset) return translations
def translator_for_lang(lang): t = buf = iso639 = lcdata = None if 'CALIBRE_TEST_TRANSLATION' in os.environ: buf = load_po( os.path.expanduser(os.environ['CALIBRE_TEST_TRANSLATION'])) mpath = get_lc_messages_path(lang) if buf is None and mpath and os.access(mpath + '.po', os.R_OK): buf = load_po(mpath + '.po') if mpath is not None: from zipfile import ZipFile with ZipFile(P('localization/locales.zip', allow_user_override=False), 'r') as zf: if buf is None: buf = io.BytesIO(zf.read(mpath + '/messages.mo')) if mpath == 'nds': mpath = 'de' isof = mpath + '/iso639.mo' try: iso639 = io.BytesIO(zf.read(isof)) except: pass # No iso639 translations for this lang if buf is not None: from calibre.utils.serialize import msgpack_loads try: lcdata = msgpack_loads( zf.read(mpath + '/lcdata.calibre_msgpack')) except: pass # No lcdata if buf is not None: try: t = GNUTranslations(buf) except Exception: import traceback traceback.print_exc() t = None if iso639 is not None: try: iso639 = GNUTranslations(iso639) except Exception: iso639 = None else: if t is not None: t.add_fallback(iso639) if t is None: t = NullTranslations() return {'translator': t, 'iso639_translator': iso639, 'lcdata': lcdata}
def load_translations(locale): """Return the translations for the locale.""" locale = Locale.parse(locale) key = str(locale) rv = _translations.get(key) if rv is None: catalog = find_catalog(locale) if catalog is None: rv = NullTranslations() else: with open(catalog, 'rb') as f: rv = Translations(fileobj=f, domain=LOCALE_DOMAIN) _translations[key] = rv return rv
def ActivateTranslation(session, config, language, localedir=None): global ACTIVE_TRANSLATION, RECENTLY_TRANSLATED if not language: language = os.getenv('LANG', None) if not localedir: import mailpile.config.paths localedir = mailpile.config.paths.DEFAULT_LOCALE_DIRECTORY() trans = None if (not language) or language[:5].lower() in ('en', 'en_us', 'c'): trans = NullTranslations() elif language: try: trans = translation("mailpile", localedir, [language], codeset="utf-8") except IOError: if session: session.ui.debug('Failed to load language %s' % language) if not trans: trans = translation("mailpile", localedir, codeset='utf-8', fallback=True) if session: session.ui.debug('Failed to configure i18n (%s). ' 'Using fallback.' % language) if trans: with RECENTLY_TRANSLATED_LOCK: RECENTLY_TRANSLATED = [] ACTIVE_TRANSLATION = trans trans.org_gettext = trans.gettext trans.org_ngettext = trans.ngettext trans.gettext = lambda t, g: gettext(g) trans.ngettext = lambda t, s1, s2, n: ngettext(s1, s2, n) trans.set_output_charset("utf-8") if hasattr(config, 'jinja_env'): config.jinja_env.install_gettext_translations(trans, newstyle=True) if session and language and not isinstance(trans, NullTranslations): session.ui.debug(gettext('Loaded language %s') % language) return trans
def _get_translator(lang, tgl=None, tg_config=None, **kwargs): """Utility method to get a valid translator object from a language name""" if tg_config: conf = tg_config else: if tgl: conf = tgl.config else: # pragma: no cover #backward compatibility with explicit calls without #specifying local context or config. conf = tg.config.current_conf() if not lang: return NullTranslations() try: localedir = conf['localedir'] except KeyError: # pragma: no cover localedir = os.path.join(conf['paths']['root'], 'i18n') app_domain = conf['package'].__name__ native_lang = conf.get( 'i18n.native') # Languages that requires no translation if not isinstance(lang, list): lang = [lang] mofiles = [] supported_languages = [] for l in lang: if native_lang and l in native_lang: mo = _TGI18NIdentityTranslator() else: mo = _gettext.find(app_domain, localedir=localedir, languages=[l], all=False) if mo is not None: mofiles.append(mo) supported_languages.append(l) try: translator = _translator_from_mofiles(app_domain, mofiles, **kwargs) except IOError as ioe: raise LanguageError('IOError: %s' % ioe) translator.tg_lang = lang translator.tg_supported_lang = supported_languages return translator
def Pluralizer(translations=None, policy=None): """ Return a pluralizer object based on the ``translations`` and ``policy`` provided. ``translations`` should be an object supporting *at least* the Python :class:`gettext.NullTranslations` API but ideally the :class:`babel.support.Translations` API, which has support for domain lookups like dugettext. ``policy`` should be a callable which accepts five arguments: ``translations``, ``singular`` and ``plural``, ``n`` and ``domain``. It must perform the actual pluralization lookup. If ``policy`` is ``None``, the :func:`translationstring.dungettext_policy` policy will be used. The object returned will be a callable which has the following signature:: def pluralizer(singular, plural, n, domain=None, mapping=None): ... The ``singular`` and ``plural`` objects passed may be translation strings or unicode strings. ``n`` represents the number of elements. ``domain`` is the translation domain to use to do the pluralization, and ``mapping`` is the interpolation mapping that should be used on the result. Note that if the objects passed are translation strings, their domains and mappings are ignored. The domain and mapping arguments must be used instead. If the ``domain`` is not supplied, a default domain is used (usually ``messages``). """ if policy is None: policy = dungettext_policy if translations is None: translations = NullTranslations() def pluralizer(singular, plural, n, domain=None, mapping=None, context=None): """ Pluralize this object """ translated = text_type( policy(translations, singular, plural, n, domain, context)) if translated and '$' in translated and mapping: return TranslationString(translated, mapping=mapping).interpolate() return translated return pluralizer
def __init__(self): self._name = 'I18nTool' self._point = 'before_handler' self.callable = self.add_language self._priority = 100 self.babel_envs = {'en': NullTranslations()} self.template_envs = {} self.add_template_env('en') for name in listdir(config.LOCALE_DIR): if os.path.isdir( os.path.join(config.LOCALE_DIR, name, 'LC_MESSAGES')): self.babel_envs[name] = None self.template_envs[name] = None
def pylons_formencode_gettext(value): global NullTranslations, tg_gettext if tg_gettext is None: from tg.i18n import ugettext as tg_gettext from gettext import NullTranslations trans = tg_gettext(value) # Translation failed, try formencode if trans == value: try: fetrans = tg.tmpl_context.formencode_translation except (AttributeError, TypeError): # the translator was not set in the Pylons context # we are certainly in the test framework # let's make sure won't return something that is ok with the caller fetrans = NullTranslations() if not fetrans: fetrans = NullTranslations() translator_gettext = getattr(fetrans, 'ugettext', fetrans.gettext) trans = translator_gettext(value) return trans
def set_translators(): # To test different translations invoke as # CALIBRE_OVERRIDE_LANG=de_DE.utf8 program lang = get_lang() t = None if lang: buf = iso639 = None mpath = get_lc_messages_path(lang) if mpath and os.access(mpath + '.po', os.R_OK): from calibre.translations.msgfmt import make buf = cStringIO.StringIO() try: make(mpath + '.po', buf) except: print(('Failed to compile translations file: %s,' ' ignoring') % (mpath + '.po')) buf = None else: buf = cStringIO.StringIO(buf.getvalue()) if mpath is not None: from zipfile import ZipFile with ZipFile( P('localization/locales.zip', allow_user_override=False), 'r') as zf: if buf is None: buf = cStringIO.StringIO(zf.read(mpath + '/messages.mo')) if mpath == 'nds': mpath = 'de' isof = mpath + '/iso639.mo' try: iso639 = cStringIO.StringIO(zf.read(isof)) except: pass # No iso639 translations for this lang if buf is not None: t = GNUTranslations(buf) if iso639 is not None: iso639 = GNUTranslations(iso639) t.add_fallback(iso639) if t is None: t = NullTranslations() t.install(unicode=True, names=('ngettext', ))
def _get_translator(lang, **kwargs): """Utility method to get a valid translator object from a language name""" if not lang: return NullTranslations() if 'pylons_config' in kwargs: conf = kwargs.pop('pylons_config') else: conf = pylons.config.current_conf() localedir = os.path.join(conf['pylons.paths']['root'], 'i18n') if not isinstance(lang, list): lang = [lang] try: translator = translation(conf['pylons.package'], localedir, languages=lang, **kwargs) except IOError, ioe: raise LanguageError('IOError: %s' % ioe)
def init(locale_dirs: List[Optional[str]], language: Optional[str], catalog: str = 'sphinx', namespace: str = 'general') -> Tuple[NullTranslations, bool]: """Look for message catalogs in `locale_dirs` and *ensure* that there is at least a NullTranslations catalog set in `translators`. If called multiple times or if several ``.mo`` files are found, their contents are merged together (thus making ``init`` reentrant). """ global translators translator = translators.get((namespace, catalog)) # ignore previously failed attempts to find message catalogs if translator.__class__ is NullTranslations: translator = None # the None entry is the system's default locale path has_translation = True if language and '_' in language: # for language having country code (like "de_AT") languages = [language, language.split('_')[0]] # type: Optional[List[str]] elif language: languages = [language] else: languages = None # loading for dir_ in locale_dirs: try: trans = gettext.translation(catalog, localedir=dir_, languages=languages) if translator is None: translator = trans else: translator.add_fallback(trans) except Exception: # Language couldn't be found in the specified path pass # guarantee translators[(namespace, catalog)] exists if translator is None: translator = NullTranslations() has_translation = False translators[(namespace, catalog)] = translator return translator, has_translation
def _formencode_gettext(value): trans = ugettext(value) # Translation failed, try formencode if trans == value: try: fetrans = tg.translator._formencode_translation except (AttributeError, TypeError): # the translator was not set in the TG context # we are certainly in the test framework # let's make sure won't return something that is ok with the caller fetrans = None if not fetrans: fetrans = NullTranslations() translator_gettext = getattr(fetrans, 'ugettext', fetrans.gettext) trans = translator_gettext(value) return trans
def set_locale(self, locales, trans_dir=None): try: if trans_dir is None: trans_dir = os.path.join( os.path.dirname( os.path.abspath( __file__, ), ), "translations" ) self.trans = translation( domain="messages", localedir=trans_dir, languages=locales, ) except Exception as e: system_log.debug(e) self.trans = NullTranslations()
def set_language(language): global translations try: with open( pkg_resources.resource_filename( "middlewared", f"locale/{language}/LC_MESSAGES/middlewared.mo"), "rb") as f: translations = GNUTranslations(f) return True except Exception as e: if language != "en": logger.warning("Failed to set language %r: %r", language, e) translations = NullTranslations() return False
def __init__(self, translate=NullTranslations(), ignore_tags=IGNORE_TAGS, include_attrs=INCLUDE_ATTRS, extract_text=True): """Initialize the translator. :param translate: the translation function, for example ``gettext`` or ``ugettext``. :param ignore_tags: a set of tag names that should not be localized :param include_attrs: a set of attribute names should be localized :param extract_text: whether the content of text nodes should be extracted, or only text in explicit ``gettext`` function calls :note: Changed in 0.6: the `translate` parameter can now be either a ``gettext``-style function, or an object compatible with the ``NullTransalations`` or ``GNUTranslations`` interface """ self.translate = translate self.ignore_tags = ignore_tags self.include_attrs = include_attrs self.extract_text = extract_text
def _load_domain(self, domain, fallback=True): """Load the given domain from one of the pre-configured locale dirs. Returns a :class:`gettext.NullTranslations` instance if no translations could be found for a non-critical domain. This allows untranslated plugins to be rendered in English instead of an error being raised. :param domain: A domain name. :param fallback: An optional flag that, when True, returns a :class:`gettext.NullTranslations` instance if no translations file could be found for the given language(s). :rtype: :class:`gettext.GNUTranslations` :returns: The native python translator instance for this domain. :raises DomainError: If no locale dir has been configured for this domain and the fallback is off. :raises LanguageError: If no translations could be found for this domain in this locale and the fallback is off. """ locale_dirs = self._locale_dirs.get(domain, None) if locale_dirs: if isinstance(locale_dirs, basestring): locale_dirs = (locale_dirs, ) translation_list = self._load_translations(domain, locale_dirs, fallback) if (not fallback) and len(translation_list) == 0: msg = 'No %r translations found for %r in %r.' raise LanguageError(msg % (domain, self._languages, locale_dirs)) translations = Translations(domain=domain) for translation in translation_list: translations.merge(translation) elif fallback: translations = NullTranslations() else: raise DomainError('No localedir specified for domain %r' % domain) self._domains[domain] = translations return translations
def get_translations(self): """Returns the correct gettext translations that should be used for this request. This will never fail and return a dummy translation object if used outside of the request or if a translation cannot be found. """ ctx = _request_ctx_stack.top if ctx is None: return NullTranslations() locale = get_locale() cache = self.get_translations_cache(ctx) translations = cache.get(str(locale)) if translations is None: dirname = self.get_translations_path(ctx) translations = support.Translations.load(dirname, locale, domain=self.domain) cache[str(locale)] = translations return translations
def _load_domain(self, domain, fallback=True): """Load the given domain from one of the pre-configured locale dirs. Returns a :class:`gettext.NullTranslations` instance if no translations could be found for a non-critical domain. This allows untranslated plugins to be rendered in English instead of an error being raised. :param domain: A domain name. :param fallback: An optional flag that, when True, returns a :class:`gettext.NullTranslations` instance if no translations file could be found for the given language(s). :rtype: :class:`gettext.GNUTranslations` :returns: The native python translator instance for this domain. :raises DomainError: If no locale dir has been configured for this domain and the fallback is off. :raises LanguageError: If no translations could be found for this domain in this locale and the fallback is off. """ localedir = self._locale_dirs.get(domain, None) if localedir: try: t = gettext_translation(domain, localedir, self._languages, fallback=fallback) except IOError: # This only occurs when fallback is false. msg = 'No %r translations found for %r at %r.' % \ (domain, self._languages, localedir) raise LanguageError(msg) elif fallback: t = NullTranslations() else: raise DomainError('No localedir specified for domain %r' % domain) self._domains[domain] = t return t
def _translator_from_mofiles(domain, mofiles, class_=None, fallback=False): """ Adapted from python translation function in gettext module to work with a provided list of mo files """ if class_ is None: class_ = GNUTranslations if not mofiles: if fallback: return NullTranslations() raise LanguageError('No translation file found for domain %s' % domain) result = None for mofile in mofiles: if hasattr(mofile, 'gettext'): # An instance of a translator was provided. # Use it instead of trying to load from disk. t = mofile else: key = (class_, os.path.abspath(mofile)) t = _TRANSLATORS_CACHE.get(key) if t is None: with open(mofile, 'rb') as fp: # Cache Translator to avoid reading it again t = _TRANSLATORS_CACHE.setdefault(key, class_(fp)) t = copy.copy(t) if result is None: # Copy the translation object to be able to append fallbacks # without affecting the cached object. result = t else: result.add_fallback(t) return result
def set_translators(): global _lang_trans, lcdata # To test different translations invoke as # CALIBRE_OVERRIDE_LANG=de_DE.utf8 program lang = get_lang() if lang: q = translator_for_lang(lang) t = q['translator'] _lang_trans = q['iso639_translator'] if q['lcdata']: lcdata = q['lcdata'] else: t = NullTranslations() try: set_translators.lang = t.info().get('language') except Exception: pass t.install(names=('ngettext', )) # Now that we have installed a translator, we have to retranslate the help # for the global prefs object as it was instantiated in get_lang(), before # the translator was installed. from calibre.utils.config_base import prefs prefs.retranslate_help()