# # 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 string import locale import gettext from simpleconfig import SimpleConfigFile import system_config_keyboard.keyboard as keyboard import logging log = logging.getLogger("anaconda") # Converts a single language into a "language search path". For example, # fr_FR.utf8@euro would become "fr_FR.utf8@eueo fr_FR.utf8 fr_FR fr" def expandLangs(astring): langs = [astring] charset = None base = None # remove charset ... if '.' in astring: langs.append(string.split(astring, '.')[0]) if '@' in astring: charset = string.split(astring, '@')[1] if '_' in astring: base = string.split(astring, '_')[0] if charset: langs.append("%s@%s" % (base, charset)) langs.append(base) else: langs.append(astring[:2]) return langs 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/font/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. We need to default to en_US.UTF-8 for now. if self.displayMode == 't': for (lang, info) in self.localeInfo.iteritems(): # If there's no font, it's not a supported language. if lang == self._instLang and info[2] == "none": 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. Unfortunately, it also means anaconda will be # running with the wrong font and keyboard in these cases. 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/font/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 = "en_US.UTF-8" self.displayMode = display_mode self.info = {} self.localeInfo = {} 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 # nick -> (name, short name, font, keyboard, timezone) mapping search = ('lang-table', '/tmp/updates/lang-table', '/etc/lang-table', '/usr/share/anaconda/lang-table') for path in search: if os.access(path, os.R_OK): f = open(path, "r") for line in f.readlines(): string.strip(line) l = string.split(line, '\t') # throw out invalid lines if len(l) < 6: continue self.localeInfo[l[3]] = (l[0], l[1], l[2], l[4], string.strip(l[5])) f.close() break # Hard code this to prevent errors in the build environment. self.localeInfo['C'] = self.localeInfo[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 expandLangs(key): return key raise ValueError def available(self): return self.nativeLangNames.keys() def dracutSetupString(self): args="" for (key, val) in self.info.iteritems(): if val != None: args += " %s=%s" % (key, val) return args def getCurrentLangSearchList(self): return expandLangs(self.systemLang) + ['C'] def getDefaultKeyboard(self, instPath): try: return self.localeInfo[self.systemLang][3] except KeyError: try: kbd = keyboard.Keyboard() kbd.read(instPath) return kbd.get() except: return self.localeInfo[self._default][3] def getDefaultTimeZone(self, instPath): 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(instPath + "/etc/sysconfig/clock"): cfg = SimpleConfigFile() cfg.read(instPath + "/etc/sysconfig/clock") try: return cfg.get("ZONE") except: return self.localeInfo[self._default][4] else: return self.localeInfo[self._default][4] def getFontFile(self, lang): # Note: in /etc/fonts.cgz fonts are named by the map # name as that's unique, font names are not 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, instPath): f = open(instPath + "/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'])