diff --git a/src/i18n.py b/src/i18n.py index 7f6f4d1d1..274df8f70 100644 --- a/src/i18n.py +++ b/src/i18n.py @@ -75,16 +75,29 @@ def getLocalePath(name, localeName, extension): directory = ansi.__file__[0:-len('ansi.pyc')] + 'locale' return '%s/%s.%s' % (directory, localeName, extension) +i18nSupybot = None i18nClasses = {} internationalizedCommands = {} +internationalizedFunctions = [] def reloadLocals(): for pluginName in i18nClasses: i18nClasses[pluginName].loadLocale() for commandHash in internationalizedCommands: internationalizeDocstring(internationalizedCommands[commandHash]) + for function in internationalizedFunctions: + function.loadLocale() + -class PluginInternationalization: +def PluginInternationalization(name='supybot'): + global i18nSupybot + if name != 'supybot': + return _PluginInternationalization(name) + elif i18nSupybot == None: + i18nSupybot = _PluginInternationalization('supybot') + return i18nSupybot + +class _PluginInternationalization: """Internationalization managment for a plugin.""" def __init__(self, name='supybot'): self.name = name @@ -101,6 +114,8 @@ class PluginInternationalization: elif localeName is None: localeName = 'en' self.currentLocaleName = localeName + + self._loadL10nCode() try: translationFile = open(getLocalePath(self.name, localeName, 'po'), @@ -158,7 +173,7 @@ class PluginInternationalization: self._parse(translated)}) def _parse(self, string): - return str.replace(string, '\\n', '\n') # Replace \\n by \n + return str.replace(string, '\\n', '\n') def __call__(self, untranslated, *args): if not 'conf' in globals(): @@ -181,32 +196,55 @@ class PluginInternationalization: except KeyError: return untranslated % args - def _getL10nCode(self): - return getLocalePath('supybot', self.currentLocaleName, 'py') - - def getPluralizers(self, pluralize, depluralize): - # This should be used only by src/utils/str.py + def _loadL10nCode(self): + if self.name != 'supybot': + return try: - execfile(self._getL10nCode()) - except IOError: + execfile(self._getL10nCodePath()) + except IOError: # File doesn't exist pass - return (pluralize, depluralize) + + functions = locals() + functions.pop('self') + self._l10nFunctions = functions + + def _getL10nCodePath(self): + if self.name != 'supybot': + return + return getLocalePath('supybot', self.currentLocaleName, 'py') + + def localizeFunction(self, name): + if self.name != 'supybot': + return + if hasattr(self, '_l10nFunctions') and self._l10nFunctions.has_key(name): + return self._l10nFunctions[name] + + def internationalizeFunction(self, name): + if self.name != 'supybot': + return + class FunctionInternationalizer: + def __init__(self, parent, name): + self._parent = parent + self._name = name + def __call__(self, obj): + obj = internationalizedFunction(self._parent, self._name, obj) + obj.loadLocale() + return obj + return FunctionInternationalizer(self, name) - def getOrdinal(self, ordinal): - # This should be used only by src/utils/str.py - try: - execfile(self._getL10nCode()) - except IOError: - pass - return ordinal - - def getBeAndHas(self, be, has): - # This should be used only by src/utils/str.py - try: - execfile(self._getL10nCode()) - except IOError: - pass - return (be, has) +class internationalizedFunction: + def __init__(self, internationalizer, name, function): + self._internationalizer = internationalizer + self._name = name + self.__call__ = function + self._origin = function + internationalizedFunctions.append(self) + def loadLocale(self): + self.__call__ = self._internationalizer.localizeFunction(self._name) + if self.__call__ == None: + self.restore() + def restore(self): + self.__call__ = self._origin def internationalizeDocstring(obj): if sys.modules[obj.__module__].__dict__.has_key('_'): diff --git a/src/utils/str.py b/src/utils/str.py index 91f71f3e6..32d24e418 100644 --- a/src/utils/str.py +++ b/src/utils/str.py @@ -43,7 +43,7 @@ from iter import all, any from structures import TwoWayDictionary from supybot.i18n import PluginInternationalization -_ = PluginInternationalization() +internationalizeFunction=PluginInternationalization().internationalizeFunction curry = new.instancemethod chars = string.maketrans('', '') @@ -256,6 +256,7 @@ def matchCase(s1, s2): L[i] = L[i].upper() return ''.join(L) +@internationalizeFunction('pluralize') def pluralize(s): """Returns the plural of s. Put any exceptions to the general English rule of appending 's' in the plurals dictionary. @@ -278,6 +279,7 @@ def pluralize(s): else: return matchCase(s, s+'s') +@internationalizeFunction('depluralize') def depluralize(s): """Returns the singular of s.""" _depluralizeRegex = re.compile('[%s]ies' % consonants) @@ -294,8 +296,6 @@ def depluralize(s): else: return s # Don't know what to do. -pluralize, depluralize = _.getPluralizers(pluralize, depluralize) - def nItems(n, item, between=None): """Works like this: @@ -332,6 +332,7 @@ def nItems(n, item, between=None): else: return format('%s %s %s', n, between, item) +@internationalizeFunction('ordinal') def ordinal(i): """Returns i + the ordinal indicator for the number. @@ -350,8 +351,7 @@ def ordinal(i): ord = 'rd' return '%s%s' % (i, ord) -ordinal = _.getOrdinal(ordinal) - +@internationalizeFunction('be') def be(i): """Returns the form of the verb 'to be' based on the number i.""" if i == 1: @@ -359,6 +359,7 @@ def be(i): else: return 'are' +@internationalizeFunction('has') def has(i): """Returns the form of the verb 'to have' based on the number i.""" if i == 1: @@ -366,8 +367,6 @@ def has(i): else: return 'have' -be, has = _.getBeAndHas(be, has) - def toBool(s): s = s.strip().lower() if s in ('true', 'on', 'enable', 'enabled', '1'):