# # language.py: install data component that stores information about both # installer runtime language choice and installed system # language support. # # Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009 Red Hat, Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import os import re import string import locale import gettext from pyanaconda.constants import ROOT_PATH, DEFAULT_LANG import localeinfo from simpleconfig import SimpleConfigFile import system_config_keyboard.keyboard as keyboard import logging log = logging.getLogger("anaconda") def langComponents(astring): pattern = re.compile("(?P[A-Za-z]+)(_(?P[A-Za-z]+))?(\.(?P[-\w]+))?(@(?P[-\w]+))?") m = pattern.match(astring) return m.groupdict() class Language(object): def _setInstLang(self, value): # Always store in its full form so we know what we're comparing with. try: self._instLang = self._canonLang(value) except ValueError: # If the language isn't listed in lang-table, we won't know what # keyboard/etc. to use. However, we can still set the $LANG # to that and make sure it works in the installed system. self._instLang = value # If we're running in text mode, value may not be a supported language # to display. Fall back to the default for now. if self.displayMode == 't': for (lang, info) in self.localeInfo.iteritems(): if lang == self._instLang and info[2] == "False": self._instLang = self._default break # Now set some things to make sure the language setting takes effect # right now. os.environ["LANG"] = self._instLang os.environ["LC_NUMERIC"] = "C" try: locale.setlocale(locale.LC_ALL, "") except locale.Error: pass # XXX: oh ick. this is the sort of thing which you should never do... # but we switch languages at runtime and thus need to invalidate # the set of languages/mofiles which gettext knows about gettext._translations = {} def _getInstLang(self): # If we were given a language that's not in lang-table, lie and say # we're using the default. This prevents us from having to check all # over the place. if self._instLang in self.localeInfo.keys(): return self._instLang else: return self._default # The language being displayed while anaconda is running. instLang = property(lambda s: s._getInstLang(), lambda s, v: s._setInstLang(v)) def _setSystemLang(self, value): # Always store in its full form so we know what we're comparing with. try: self._systemLang = self._canonLang(value) except ValueError: # If the language isn't listed in lang-table, we won't know what # keyboard/etc. to use. However, we can still set the $LANG # to that and make sure it works in the installed system. self._systemLang = value # Now set a bunch of other things that'll get written to # /etc/sysconfig/i18n on the installed system. self.info["LANG"] = self._systemLang if not self.localeInfo.has_key(self._systemLang): return if self.localeInfo[self._systemLang][2] == "none": self.info["SYSFONT"] = None else: self.info["SYSFONT"] = self.localeInfo[self._systemLang][2] # XXX hack - because of exceptional cases on the var - zh_CN.GB2312 if self._systemLang == "zh_CN.GB18030": self.info["LANGUAGE"] = "zh_CN.GB18030:zh_CN.GB2312:zh_CN" # The language to use on the installed system. This can differ from the # language being used during anaconda. For instance, text installs cannot # display all languages (CJK, Indic, etc.). systemLang = property(lambda s: s._systemLang, lambda s, v: s._setSystemLang(v)) def __init__ (self, display_mode = 'g'): self._default = DEFAULT_LANG self.displayMode = display_mode self.info = {} self.nativeLangNames = {} # English name -> native name mapping search = ('lang-names', '/usr/share/anaconda/lang-names') for path in search: if os.access(path, os.R_OK): f = open(path, 'r') for line in f.readlines(): lang, native = string.split(line, '\t') native = native.strip() self.nativeLangNames[lang] = native f.close() break self.localeInfo = localeinfo.get(self._default) # instLang must be set after localeInfo is populated, in case the # current setting is unsupported by anaconda.. self.instLang = os.environ.get("LANG", self._default) self.systemLang = os.environ.get("LANG", self._default) def _canonLang(self, lang): """Convert the shortened form of a language name into the full version. If it's not found, raise ValueError. Example: fr -> fr_FR.UTF-8 fr_FR -> fr_FR.UTF-8 fr_CA -> ValueError """ for key in self.localeInfo.keys(): if lang in localeinfo.expandLangs(key): return key raise ValueError def available(self): return self.nativeLangNames.keys() def buildLocale(self): import iutil c = langComponents(self._instLang) locale_p = c["language"] if c["territory"]: locale_p += "_" + c["territory"] if c["modifier"]: locale_p += "@" + c["modifier"] iutil.execWithRedirect("localedef", ["-i", locale_p, "-f", c["codeset"] or "UTF-8", self._instLang]) def dracutSetupArgs(self): args=set() for (key, val) in self.info.iteritems(): if val != None: args.add("%s=%s" % (key, val)) return args def getCurrentLangSearchList(self): return localeinfo.expandLangs(self.systemLang) + ['C'] def getDefaultKeyboard(self): try: return self.localeInfo[self.systemLang][3] except KeyError: try: kbd = keyboard.Keyboard() kbd.read(ROOT_PATH) return kbd.get() except: return self.localeInfo[self._default][3] def getDefaultTimeZone(self): try: return self.localeInfo[self.systemLang][4] except KeyError: # If doing an upgrade and the system language is something not # recognized by anaconda, we should try to see if we can figure # it out from the running system. if os.path.exists(ROOT_PATH + "/etc/sysconfig/clock"): cfg = SimpleConfigFile() cfg.read(ROOT_PATH + "/etc/sysconfig/clock") try: return cfg.get("ZONE") except: return self.localeInfo[self._default][4] else: return self.localeInfo[self._default][4] def textSupported(self, lang): try: l = self._canonLang(lang) except ValueError: l = self._default return self.localeInfo[l][2] def getLangName(self, lang): try: l = self._canonLang(lang) except ValueError: l = self._default return self.localeInfo[l][0] def getLangByName(self, name): for (key, val) in self.localeInfo.iteritems(): if val[0] == name: return key def getNativeLangName(self, lang): return self.nativeLangNames[lang] def write(self): f = open(ROOT_PATH + "/etc/sysconfig/i18n", "w") for (key, val) in self.info.iteritems(): if val != None: f.write("%s=\"%s\"\n" % (key, val)) f.close() def writeKS(self, f): f.write("lang %s\n" % self.info['LANG'])