Merge branch 'i18n' into l10n-fr

This commit is contained in:
Valentin Lorentz 2010-10-30 21:41:35 +02:00
commit e8e5aa2d7a
1 changed files with 40 additions and 23 deletions

View File

@ -31,7 +31,7 @@
Supybot internationalisation and localisation managment. Supybot internationalisation and localisation managment.
""" """
__all__ = ['PluginInternationalization'] __all__ = ['PluginInternationalization', 'internationalizeDocstring']
import re import re
import sys import sys
@ -75,10 +75,9 @@ def getLocalePath(name, localeName, extension):
directory = ansi.__file__[0:-len('ansi.pyc')] + 'locale' directory = ansi.__file__[0:-len('ansi.pyc')] + 'locale'
return '%s/%s.%s' % (directory, localeName, extension) return '%s/%s.%s' % (directory, localeName, extension)
i18nSupybot = None
i18nClasses = {} i18nClasses = {}
internationalizedCommands = {} internationalizedCommands = {}
internationalizedFunctions = [] internationalizedFunctions = [] # No need to know there name
def reloadLocals(): def reloadLocals():
for pluginName in i18nClasses: for pluginName in i18nClasses:
@ -89,7 +88,10 @@ def reloadLocals():
function.loadLocale() function.loadLocale()
i18nSupybot = None
def PluginInternationalization(name='supybot'): def PluginInternationalization(name='supybot'):
# This is a proxy, that prevent Supybot against having more than one
# internationalizer
global i18nSupybot global i18nSupybot
if name != 'supybot': if name != 'supybot':
return _PluginInternationalization(name) return _PluginInternationalization(name)
@ -109,6 +111,7 @@ class _PluginInternationalization:
self.loadLocale() self.loadLocale()
def loadLocale(self, localeName=None): def loadLocale(self, localeName=None):
"""(Re)loads the locale used by this class."""
if localeName is None and 'conf' in globals(): if localeName is None and 'conf' in globals():
localeName = conf.supybot.language() localeName = conf.supybot.language()
elif localeName is None: elif localeName is None:
@ -121,9 +124,15 @@ class _PluginInternationalization:
translationFile = open(getLocalePath(self.name, localeName, 'po'), translationFile = open(getLocalePath(self.name, localeName, 'po'),
'ru') # ru is the mode, not the beginning 'ru') # ru is the mode, not the beginning
# of 'russian' ;) # of 'russian' ;)
self._parse(translationFile)
except IOError: # The translation is unavailable except IOError: # The translation is unavailable
self.translations = {} self.translations = {}
return return
def _parse(self, translationFile):
"""A .po files parser.
Give it a file object."""
step = WAITING_FOR_MSGID step = WAITING_FOR_MSGID
self.translations = {} self.translations = {}
for line in translationFile: for line in translationFile:
@ -169,32 +178,22 @@ class _PluginInternationalization:
self._translate(untranslated, translated) self._translate(untranslated, translated)
def _translate(self, untranslated, translated): def _translate(self, untranslated, translated):
self.translations.update({self._parse(untranslated): self.translations.update({self._unescape(untranslated):
self._parse(translated)}) self._unescape(translated)})
def _parse(self, string): def _unescape(self, string):
return str.replace(string, '\\n', '\n') return str.replace(string, '\\n', '\n')
def __call__(self, untranslated, *args): def __call__(self, untranslated):
if not 'conf' in globals(): if not 'conf' in globals():
if len(args) == 0: return untranslated
return untranslated
else:
translation = self(untranslated)
return translation % args
if self.currentLocaleName != conf.supybot.language(): if self.currentLocaleName != conf.supybot.language():
# If the locale has been changed # If the locale has been changed
reloadLocals() reloadLocals()
if len(args) == 0: try:
try: return self.translations[untranslated]
return self.translations[untranslated] except KeyError:
except KeyError: return untranslated
return untranslated
else:
try:
return self.translations[untranslated] % args
except KeyError:
return untranslated % args
def _loadL10nCode(self): def _loadL10nCode(self):
if self.name != 'supybot': if self.name != 'supybot':
@ -207,19 +206,31 @@ class _PluginInternationalization:
functions = locals() functions = locals()
functions.pop('self') functions.pop('self')
self._l10nFunctions = functions self._l10nFunctions = functions
# Remove old functions and come back to the native language
def _getL10nCodePath(self): def _getL10nCodePath(self):
"""Returns the path to the code localization file.
It contains functions that needs to by fully (code + strings)
localized"""
if self.name != 'supybot': if self.name != 'supybot':
return return
return getLocalePath('supybot', self.currentLocaleName, 'py') return getLocalePath('supybot', self.currentLocaleName, 'py')
def localizeFunction(self, name): def localizeFunction(self, name):
"""Returns the localized version of the function.
Should be used only by the internationalizedFunction class"""
if self.name != 'supybot': if self.name != 'supybot':
return return
if hasattr(self, '_l10nFunctions') and self._l10nFunctions.has_key(name): if hasattr(self, '_l10nFunctions') and \
self._l10nFunctions.has_key(name):
return self._l10nFunctions[name] return self._l10nFunctions[name]
def internationalizeFunction(self, name): def internationalizeFunction(self, name):
"""Decorates functions and internationalize their code.
Only useful for Supybot core functions"""
if self.name != 'supybot': if self.name != 'supybot':
return return
class FunctionInternationalizer: class FunctionInternationalizer:
@ -233,6 +244,9 @@ class _PluginInternationalization:
return FunctionInternationalizer(self, name) return FunctionInternationalizer(self, name)
class internationalizedFunction: class internationalizedFunction:
"""Proxy for functions that need to be fully localized.
The localization code is in locale/LOCALE.py"""
def __init__(self, internationalizer, name, function): def __init__(self, internationalizer, name, function):
self._internationalizer = internationalizer self._internationalizer = internationalizer
self._name = name self._name = name
@ -247,6 +261,9 @@ class internationalizedFunction:
self.__call__ = self._origin self.__call__ = self._origin
def internationalizeDocstring(obj): def internationalizeDocstring(obj):
"""Decorates functions and internationalize their docstring.
Only useful for commands (commands' docstring is displayed on IRC)"""
if sys.modules[obj.__module__].__dict__.has_key('_'): if sys.modules[obj.__module__].__dict__.has_key('_'):
internationalizedCommands.update({hash(obj): obj}) internationalizedCommands.update({hash(obj): obj})
obj.__doc__=sys.modules[obj.__module__]._.__call__(obj.__doc__) obj.__doc__=sys.modules[obj.__module__]._.__call__(obj.__doc__)