def Install(language=None,pathRead=None,pathWrite=None): """Install translation for language. If language is not specified, installs a translation for the default language.""" if not language: language = locale.getlocale()[0].split('_',1)[0] pathRead = pathRead if pathRead else GPath('l10n') pathWrite = pathWrite if pathWrite else pathRead if language.lower() == 'german': language = 'de' txt = pathRead.join(language+'.txt') po = pathWrite.join(language+'.po') mo = pathWrite.join(language+'.mo') #--Test for no translation for the language if not txt.exists and not mo.exists: if language.lower() != 'english': print('No translation file for language:', language) trans = gettext.NullTranslations() else: try: # See if translation needs to be recompiled txtMtime = txt.mtime if not mo.exists or txtMtime != mo.mtime: txt.copyTo(po) args= ['m',po.s,'-o',mo.s] if hasattr(sys,'frozen'): # Same thing as for 'Dump' for frozen # apps. import msgfmt old_argv = sys.argv[:] sys.argv = args msgfmt.main() sys.argv = old_argv else: m = GPath(sys.prefix).join('Tools','i18n','msgfmt.py') args[0] = m.s subprocess.call(args,shell=True) po.remove() mo.mtime = txtMtime # Create GNU translations with mo.open('rb') as ins: trans = gettext.GNUTranslations(ins) except: print('Error loading translation file for', language) traceback.print_exc() trans = gettext.NullTranslations() # Install trans.install()
def setup_locale(cli_lang, _wx): """Sets up wx and Wrye Bash locales, ensuring they match or falling back to English if that is impossible. Also considers cli_lang as an override, installs the gettext translation and remembers the locale we end up with as bass.active_locale. bolt.deprint must be set up and ready to use (i.e. hooked up to the BashBugDump if debug mode is enabled) and the working directory must be correct (otherwise detection of translation files will not work and this method will always set locale to English). :param cli_lang: The language the user specified on the command line, or None. :param _wx: The wx instance to use. :return: The wx.Locale object we ended up using.""" # We need a throwaway wx.App so that the calls below work _temp_app = _wx.App(False) # Set the wx language - otherwise we will crash when loading any images if cli_lang and _wx.Locale.FindLanguageInfo(cli_lang): # The user specified a language that wx recognizes and WB supports target_language = _wx.Locale.FindLanguageInfo(cli_lang).Language else: # Fall back on the default language target_language = _wx.LANGUAGE_DEFAULT # We now have a language that wx supports, but we don't know if WB supports # it - so check that next target_locale = _wx.Locale(target_language) target_name = target_locale.GetSysName().split(u'_', 1)[0] # Ugly hack, carried forward from bolt.initTranslator if target_name.lower() == u'german': target_name = u'de' # English is the default, so it doesn't have a translation file # For all other languages, check if we have a translation trans_path = os.path.join(os.getcwdu(), u'bash', u'l10n') if target_name.lower() != u'english' and not os.path.exists( os.path.join(trans_path, target_name + u'.txt')): # WB does not support the default language, use English instead target_locale = _wx.Locale(_wx.LANGUAGE_ENGLISH) bolt.deprint(u"No translation file for language '%s', falling back to " u"English" % target_name) target_name = target_locale.GetSysName().split(u'_', 1)[0] bolt.deprint(u"Set wx locale to '%s' (%s)" % (target_name, target_locale.GetCanonicalName())) # Next, set the Wrye Bash locale based on the one we grabbed from wx txt, po, mo = (os.path.join(trans_path, target_name + ext) for ext in (u'.txt', u'.po', u'.mo')) if not os.path.exists(txt) and not os.path.exists(mo): # We're using English or don't have a translation file - either way, # prepare the English translation trans = gettext.NullTranslations() bolt.deprint(u"Set Wrye Bash locale to 'English'") else: try: # We have a translation file, check if it has to be compiled if not os.path.exists(mo) or (os.path.getmtime(txt) > os.path.getmtime(mo)): # Try compiling - have to do it differently if we're a # standalone build shutil.copy(txt, po) args = [u'm', u'-o', mo, po] if bass.is_standalone: # Delayed import, since it's only present on standalone import msgfmt old_argv = sys.argv[:] sys.argv = args msgfmt.main() sys.argv = old_argv else: # msgfmt is only in Tools, so call it explicitly m = os.path.join(sys.prefix, u'Tools', u'i18n', u'msgfmt.py') subprocess.call([sys.executable, m, u'-o', mo, po], shell=True) # Clean up the temp file we created for compilation os.remove(po) # We've succesfully compiled the translation, read it into memory with open(mo, u'rb') as trans_file: trans = gettext.GNUTranslations(trans_file) bolt.deprint(u"Set Wrye Bash locale to '%s'" % target_name) except (UnicodeError, OSError): bolt.deprint(u'Error loading translation file:') traceback.print_exc() trans = gettext.NullTranslations() # Everything has gone smoothly, install the translation and remember what # we ended up with as the final locale # PY3: drop the unicode=True, gone in py3 (this is always unicode now) trans.install(unicode=True) bass.active_locale = target_name del _temp_app return target_locale
import os, glob import msgfmt import sys script_dir = os.path.dirname(os.path.abspath(__file__)) locale_path = os.path.abspath(os.path.join(script_dir, '..', 'locale')) for name in glob.iglob(locale_path + '/**'): if not os.path.isfile(name): path = os.path.join(locale_path, name, 'LC_MESSAGES', 'lang') sys.argv[1:] = [path + '.po'] msgfmt.reset() msgfmt.main()
def setup_locale(cli_lang): """Sets up wx and Wrye Bash locales, ensuring they match or falling back to English if that is impossible. Also considers cli_lang as an override, installs the gettext translation and remembers the locale we end up with as bass.active_locale. bolt.deprint must be set up and ready to use (i.e. hooked up to the BashBugDump if debug mode is enabled) and the working directory must be correct (otherwise detection of translation files will not work and this method will always set locale to English). :param cli_lang: The language the user specified on the command line, or None. :return: The wx.Locale object we ended up using.""" # We need a throwaway wx.App so that the calls below work import wx as _wx _temp_app = _wx.App(False) # Set the wx language - otherwise we will crash when loading any images cli_target = cli_lang and _wx.Locale.FindLanguageInfo(cli_lang) if cli_target: # The user specified a language that wx recognizes target_language = cli_target.Language else: # Fall back on the default language target_language = _wx.LANGUAGE_DEFAULT # We now have a language that wx supports, but we don't know if WB supports # it - so check that next target_locale = _wx.Locale(target_language) target_name = target_locale.GetCanonicalName() trans_path = os.path.join(os.getcwdu(), u'bash', u'l10n') if not os.path.exists(trans_path): # HACK: the CI has to run tests from the top dir, which causes us to # have a non-Mopy working dir here. Real fix is ditching the fake # startup and adding a real headless mode to WB (see #568 and #554) trans_path = os.path.join(os.getcwdu(), u'Mopy', u'bash', u'l10n') supported_l10ns = [ l[:-3] for l in os.listdir(trans_path) if l[-3:] == u'.po' ] if target_name not in supported_l10ns: # We don't support this exact language. Check if we support any similar # languages (i.e. same prefix) wanted_prefix = target_name.split(u'_', 1)[0] for l in supported_l10ns: if l.split(u'_', 1)[0] == wanted_prefix: bolt.deprint(u"No translation file for language '%s', " u"using similar language with translation file " u"'%s' instead" % (target_name, l)) target_name = l # Try switching wx to this locale as well lang_info = _wx.Locale.FindLanguageInfo(target_name) if lang_info: target_locale = _wx.Locale(lang_info.Language) else: # Didn't work, try the prefix to get a similar language lang_info = _wx.Locale.FindLanguageInfo(wanted_prefix) if lang_info: target_locale = _wx.Locale(lang_info.Language) bolt.deprint( u"wxPython does not support language " u"'%s', using supported language '%s' " u"instead" % (target_name, target_locale.GetCanonicalName())) else: # If even that didn't work, all we can do is complain # about it and fall back to English bolt.deprint(u"wxPython does not support the language " u"family '%s', will fall back to " u"English" % wanted_prefix) break po, mo = (os.path.join(trans_path, target_name + ext) for ext in (u'.po', u'.mo')) # English is the default, so it doesn't have a translation file # For all other languages, check if we have a translation if not target_name.startswith(u'en_') and not os.path.isfile(po): # WB does not support the default language, use English instead target_locale = _wx.Locale(_wx.LANGUAGE_ENGLISH) fallback_name = target_locale.GetCanonicalName() bolt.deprint(u"No translation file for language '%s', falling back to " u"'%s'" % (target_name, fallback_name)) target_name = fallback_name bolt.deprint(u"Set wxPython language to '%s'" % target_locale.GetCanonicalName()) bolt.deprint(u"Set Wrye Bash language to '%s'" % target_name) # Next, set the Wrye Bash locale based on the one we grabbed from wx if not os.path.isfile(po) and not os.path.isfile(mo): # We're using English or don't have a translation file - either way, # prepare the English translation trans = gettext.NullTranslations() else: try: # We have a translation file, check if it has to be compiled if not os.path.isfile(mo) or (os.path.getmtime(po) > os.path.getmtime(mo)): # Try compiling - have to do it differently if we're a # standalone build args = [u'm', u'-o', mo, po] if bass.is_standalone: # Delayed import, since it's only present on standalone import msgfmt old_argv = sys.argv[:] sys.argv = args msgfmt.main() sys.argv = old_argv else: # msgfmt is only in Tools, so call it explicitly from .env import python_tools_dir m = os.path.join(python_tools_dir(), u'i18n', u'msgfmt.py') subprocess.call([sys.executable, m, u'-o', mo, po]) # We've successfully compiled the translation, read it into memory with open(mo, u'rb') as trans_file: trans = gettext.GNUTranslations(trans_file) except (UnicodeError, OSError): bolt.deprint(u'Error loading translation file:') traceback.print_exc() trans = gettext.NullTranslations() # Everything has gone smoothly, install the translation and remember what # we ended up with as the final locale # PY3: drop the unicode=True, gone in py3 (this is always unicode now) trans.install(unicode=True) bass.active_locale = target_name del _temp_app return target_locale