def _setLocale(self, primaryLocale, ignoreError=False): if wxIsAvailable(): # Strip the country code for wxLocales # since any invalid values raise an # uncapturable error in the wx Widgets layer. # With the exception of Chinese, all # wx localizations use the lang # code exclusively. # XXX [grant] Also, pt_BR is common. This just seems # bogus. try: setWxLocale(stripCountryCode(primaryLocale), self) except I18nException: if not ignoreError: raise setPyICULocale(primaryLocale) setEnvironmentLocale(primaryLocale) from application import Utility if Utility.getPlatformID() == "osx-ppc" and \ Utility.getOSName() in ('10.3-Panther', '10.4-Tiger'): # On OS X PPC the LC_NUMERIC values will # localize unless the Python locale is # set to 'C'. Localized numeric values ie. # 1234,23 for a float in the 'FR' locale # create data exchange issues and needs to # be avoided at all costs. setPythonLocale('C') else: setPythonLocale(primaryLocale)
def setWxLocale(locale, i18nMan): """ Sets the c{wx.Locale} to the value passed in c{str} locale argument. If the locale passed is not a valid wx locale and and that locale consists of a lang and country code, the country code is stripped and the lang code is set as the c{wx.Locale}. This logic is employed in the cases such as "es_UY" where wxPython does not have a translation for 'es_UY' but does have one for 'es'. If the locale is still not valid after attempting to use just the lang code a c{I18nException} is raised. @param locale: a c{str} locale @type locale: ASCII c{str} """ # Need to unload wx.Locale object otherwise it will # hold a dangling reference and not use the new Locale global _WX_LOCALE _WX_LOCALE = None # findWxLocale can return None when the locale # is not supported on the host OS lc = findWxLocale(locale, i18nMan) if lc is not None and not lc.IsOk() and hasCountryCode(locale): # Need to unload wx.Locale object otherwise it will # hold a dangling reference and not use the # Stripped Locale lc = None # Strip the country code and just use the language # For example wx does not have a translation for # 'es_UY' but does have one for 'es' lc = findWxLocale(stripCountryCode(locale), i18nMan) if lc is None or not lc.IsOk(): raise I18nException, "Invalid wxPython Locale: '%s'" % locale # Keep a Global reference to the Wx Locale # To ensure it does not get unloaded during the # application life cycle. There can be only one # wx locale per Python instance _WX_LOCALE = lc
def setLocaleSet(self, localeSet=None, fallback=True): """ Resets the c{I18nManager locale set c{List}. Resetting the locale set includes unloading all gettext .mo translations, loading the the gettext .mo translations for the current locale set, and setting the gettext locale fallback order if the fallback parameter is set to True. Note the initial locale set for the c{I18nManager} must be set in the C{I18nManager.initialize} method. Note, setting the c{I18nManager} locale set also adds the language code as a fallback for language / county code locale definitions when fallback is set to True. If the locale set contains 'fr_CA' this method will also add to the locale set 'fr' as a fallback for 'fr_CA'. If no localeSet is passed the discoverLocaleSet method will be called to retrieve the locale set of the Operating System. A locale of 'test' can be passed to this method. In testing mode all values returned by the c{I18nManager.getText} and c{i18nManager.wxTranslate} methods insert a (\u00FC): at the start of the string. This method sets the following: 1. The PyICU Locale 2. The wxPython Locale 3. The Python Locale 4. The Operating System Enviroment Locale The setLocaleSet method can raise the following exceptions: 1. c{UnicodeEncodeError} 2. c{NameError} 3. c{I18nException} @param localeSet: A c{unicode} or c{str} or c{List} containing locale country and language codes. The value(s) must be able to be converted to ASCII. If None is passed the setLocaleSet method will call the discoverLocaleSet method to retrieve the Operating System locale set. @type localeSet: None or ASCII c{str} or c{unicode} or c{List} containing ASCII c{str} or c{unicode} values @param fallback: Indicates whether locale set fallback should take place. If set to True, the c{I18nManager} will search all locales in the locale set till a resource or gettext mo translation file is found. If set to False the c{I18nManager} will only try to locate a resource or gettext mo translation file for the current locale which is the first locale in the locale set. @type fallback: c{boolean} """ self._testing = False discover = localeSet is None if discover: try: localeSet = self.discoverLocaleSet() except: # Just in case an error is raised in the # discovering of the localeSet, capture # it here and keep the localeSet variable # as None. This will result in the # locale being set to "en_US" later in the # code. In the discovery case Chandler # should do everything possible to # still load the application even # if an error was raised. pass else: assert (type(localeSet) == ListType or type(localeSet) == UnicodeType or type(localeSet) == StringType) if 'test' in localeSet: localeSet = ['en_US'] self._testing = True # If the localeSet is Unicode or a String # then wrap the value in a list if type(localeSet) != ListType: if localeSet is None or len(localeSet.strip()) == 0: # The locale is empty so do not include it # in the localeSet list. This will default # the locale to 'en' later in the code. localeSet = [] else: localeSet = [localeSet] # Check if the "en" locale or one of # its country sub-sets such as "en_US" or # "en_GB" is in the localeSet. If there # is not a match then add "en" as the last # locale in the the localeSet for fallback # purposes. This ensures that the English # localization of Chandler which contains # string changes added after a localization # code freeze are leveraged in the Chandler # UI. #The locale set appending of "en" # must be done before the call to the # parent classes setLocaleSet method # as that method loads and initalizes the # the gettext .mo files for each locale in # the locale set. if not any(loc.lower().startswith("en") for loc in localeSet): localeSet.append("en_US") #XXX This can raise an Exception if an invalid locale is # passed. Could make a more user friendly error message # here by capturing and re-raising the exception. # A bogus locale would be related to a user manually # entering the locale on the command line. super(I18nManager, self).setLocaleSet(localeSet, fallback) # If there is not an .mo translation file loaded for any # of the locales in the locale set then default to # United States English to prevent wxPython and PyICU # from localizing while Chandler is displaying English text. primaryLocale = "en_US" if fallback: # Find the first locale in the locale set that either: # # 1. Has a translation egg installed. # # 2. Has a translation egg installed for its language code only. # This preserves any country specific date / time formatting. # For example, if the locale is fr_CA and there is no fr_CA egg # but there is an fr egg then set the locale to fr_CA. for lc in self._localeSet: if (self.hasTranslation(self._DEFAULT_PROJECT, self._DEFAULT_CATALOG, lc) or (hasCountryCode(lc) and self.hasTranslation( self._DEFAULT_PROJECT, self._DEFAULT_CATALOG, stripCountryCode(lc)))): primaryLocale = lc if primaryLocale == "en_US": # This is a bit of a hack but # not sure of a cleaner way to # implement this logic. # If the primaryLocale is "en_US" # then it means that all of the # locales in the locale set that # preceeded "en" do not have a # translation. self._localeSet = ['en_US', 'en'] break else: lc = self._localeSet[0] if (lc.startswith("en") or self.hasTranslation( self._DEFAULT_PROJECT, self._DEFAULT_CATALOG, lc)): primaryLocale = lc try: self._setLocale(primaryLocale) except I18nException: if discover: self._setLocale("en_US", ignoreError=True) else: # If the locale was passed in (ie. not # discovered from the OS) then raise # the error. The most common case is # someone typing an invalid locale # on the command line. In this case # we do want to raise the error and # not just default to "en_US". raise # Reset the resource lookup cache self._lookupCache = None self._lookupCache = {}
def setLocaleSet(self, localeSet=None, fallback=True): """ Resets the c{I18nManager locale set c{List}. Resetting the locale set includes unloading all gettext .mo translations, loading the the gettext .mo translations for the current locale set, and setting the gettext locale fallback order if the fallback parameter is set to True. Note the initial locale set for the c{I18nManager} must be set in the C{I18nManager.initialize} method. Note, setting the c{I18nManager} locale set also adds the language code as a fallback for language / county code locale definitions when fallback is set to True. If the locale set contains 'fr_CA' this method will also add to the locale set 'fr' as a fallback for 'fr_CA'. If no localeSet is passed the discoverLocaleSet method will be called to retrieve the locale set of the Operating System. A locale of 'test' can be passed to this method. In testing mode all values returned by the c{I18nManager.getText} and c{i18nManager.wxTranslate} methods insert a (\u00FC): at the start of the string. This method sets the following: 1. The PyICU Locale 2. The wxPython Locale 3. The Python Locale 4. The Operating System Enviroment Locale The setLocaleSet method can raise the following exceptions: 1. c{UnicodeEncodeError} 2. c{NameError} 3. c{I18nException} @param localeSet: A c{unicode} or c{str} or c{List} containing locale country and language codes. The value(s) must be able to be converted to ASCII. If None is passed the setLocaleSet method will call the discoverLocaleSet method to retrieve the Operating System locale set. @type localeSet: None or ASCII c{str} or c{unicode} or c{List} containing ASCII c{str} or c{unicode} values @param fallback: Indicates whether locale set fallback should take place. If set to True, the c{I18nManager} will search all locales in the locale set till a resource or gettext mo translation file is found. If set to False the c{I18nManager} will only try to locate a resource or gettext mo translation file for the current locale which is the first locale in the locale set. @type fallback: c{boolean} """ self._testing = False discover = localeSet is None if discover: try: localeSet = self.discoverLocaleSet() except: # Just in case an error is raised in the # discovering of the localeSet, capture # it here and keep the localeSet variable # as None. This will result in the # locale being set to "en_US" later in the # code. In the discovery case Chandler # should do everything possible to # still load the application even # if an error was raised. pass else: assert(type(localeSet) == ListType or type(localeSet) == UnicodeType or type(localeSet) == StringType) if 'test' in localeSet: localeSet = ['en_US'] self._testing = True # If the localeSet is Unicode or a String # then wrap the value in a list if type(localeSet) != ListType: if localeSet is None or len(localeSet.strip()) == 0: # The locale is empty so do not include it # in the localeSet list. This will default # the locale to 'en' later in the code. localeSet = [] else: localeSet = [localeSet] # Check if the "en" locale or one of # its country sub-sets such as "en_US" or # "en_GB" is in the localeSet. If there # is not a match then add "en" as the last # locale in the the localeSet for fallback # purposes. This ensures that the English # localization of Chandler which contains # string changes added after a localization # code freeze are leveraged in the Chandler # UI. #The locale set appending of "en" # must be done before the call to the # parent classes setLocaleSet method # as that method loads and initalizes the # the gettext .mo files for each locale in # the locale set. if not any(loc.lower().startswith("en") for loc in localeSet): localeSet.append("en_US") #XXX This can raise an Exception if an invalid locale is # passed. Could make a more user friendly error message # here by capturing and re-raising the exception. # A bogus locale would be related to a user manually # entering the locale on the command line. super(I18nManager, self).setLocaleSet(localeSet, fallback) # If there is not an .mo translation file loaded for any # of the locales in the locale set then default to # United States English to prevent wxPython and PyICU # from localizing while Chandler is displaying English text. primaryLocale = "en_US" if fallback: # Find the first locale in the locale set that either: # # 1. Has a translation egg installed. # # 2. Has a translation egg installed for its language code only. # This preserves any country specific date / time formatting. # For example, if the locale is fr_CA and there is no fr_CA egg # but there is an fr egg then set the locale to fr_CA. for lc in self._localeSet: if (self.hasTranslation(self._DEFAULT_PROJECT, self._DEFAULT_CATALOG, lc) or (hasCountryCode(lc) and self.hasTranslation(self._DEFAULT_PROJECT, self._DEFAULT_CATALOG, stripCountryCode(lc)))): primaryLocale = lc if primaryLocale == "en_US": # This is a bit of a hack but # not sure of a cleaner way to # implement this logic. # If the primaryLocale is "en_US" # then it means that all of the # locales in the locale set that # preceeded "en" do not have a # translation. self._localeSet = ['en_US', 'en'] break else: lc = self._localeSet[0] if (lc.startswith("en") or self.hasTranslation(self._DEFAULT_PROJECT, self._DEFAULT_CATALOG, lc)): primaryLocale = lc try: self._setLocale(primaryLocale) except I18nException: if discover: self._setLocale("en_US", ignoreError=True) else: # If the locale was passed in (ie. not # discovered from the OS) then raise # the error. The most common case is # someone typing an invalid locale # on the command line. In this case # we do want to raise the error and # not just default to "en_US". raise # Reset the resource lookup cache self._lookupCache = None self._lookupCache = {}
def __init__(self): super(LocalePickerDialog, self).__init__(wx.GetApp().mainFrame, -1, u"", style=wx.DEFAULT_DIALOG_STYLE) self._locales = {} localeCodes = getAvailableChandlerLocales() icuLocales = Locale.getAvailableLocales() icuLocaleCodes = icuLocales.keys() langCodeAdded = {} linux = sys.platform.startswith("linux") for localeCode in localeCodes: langCode = stripCountryCode(localeCode) if linux and not hasWxLocale(langCode): # Not all WxPython translations are # installed by default on English # versions of Linux. Thus even # though there is a translation # egg available for Chandler, wx # will raise an error on Chandler # start up continue if hasCountryCode(localeCode) and not langCode in localeCodes: # There is no translation egg available for # the langCode (fallback). In this case, country variations # can not be made available to the user. This will # be rare if ever happen that say a "fr_CA" egg is # registered with Chandler but not an "fr" egg. self._locales[Locale(localeCode).getDisplayName()] = localeCode continue if not langCodeAdded.has_key(langCode): added = False for icuLocale in icuLocaleCodes: if icuLocale.startswith(langCode): self._locales[icuLocales[icuLocale].getDisplayName()] = icuLocale added = True if added: langCodeAdded[langCode] = True currentLocale = getLocale() currentLocaleName = Locale(currentLocale).getDisplayName() if currentLocale not in localeCodes: # Add the current locale to the locale selection list. # This case occurs when a user manual specifies a locale # on the command line or via prefs that does not have # a translation egg installed. self._locales[currentLocaleName] = currentLocale choices = self._locales.keys() choices.sort() # Now continue with the normal construction of the dialog # contents sizer = wx.BoxSizer(wx.VERTICAL) label = wx.StaticText(self, -1, _(u"Please select a language:"), size=(DIALOG_WIDTH, -1)) label.Wrap(DIALOG_WIDTH) sizer.Add(label, 0, wx.ALIGN_CENTER | wx.ALL, 10) self._localeChoices = wx.Choice(self, -1, choices=choices, size=(DIALOG_WIDTH - 70, -1)) sizer.Add(self._localeChoices, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 10) pos = self._localeChoices.FindString(currentLocaleName) if pos != wx.NOT_FOUND: self._localeChoices.SetSelection(pos) sizer.AddSpacer(10, 0) bsizer = wx.BoxSizer(wx.HORIZONTAL) # Load the wx.ICON_EXCLAMATION icon bmp = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_MESSAGE_BOX, (32, 32)) icon = wx.StaticBitmap(self, -1, bmp) bsizer.Add(icon, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5) note = wx.StaticText(self, -1, _(u"Switching languages will cause Chandler to automatically restart.")) note.Wrap(DIALOG_WIDTH) bsizer.Add(note, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5) sizer.Add(bsizer) sizer.AddSpacer(5, 0) box = wx.BoxSizer(wx.HORIZONTAL) btn = wx.Button(self, wx.ID_OK) btn.SetDefault() box.Add(btn, 0, wx.ALIGN_RIGHT | wx.ALL, 5) btn = wx.Button(self, wx.ID_CANCEL) box.Add(btn, 0, wx.ALIGN_RIGHT | wx.ALL, 5) sizer.Add(box, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10) self.SetSizer(sizer) self.SetAutoLayout(True) sizer.Fit(self)