mirror of https://github.com/Mikaela/Limnoria.git
Merge branch 'i18n' into l10n-fr
This commit is contained in:
commit
e8e5aa2d7a
63
src/i18n.py
63
src/i18n.py
|
@ -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__)
|
||||||
|
|
Loading…
Reference in New Issue