Merge branch 'l10n-fr' into testing

This commit is contained in:
Valentin Lorentz 2010-11-17 21:40:36 +01:00
commit d5ae366ceb
12 changed files with 70 additions and 52 deletions

View File

@ -40,7 +40,7 @@ def pluralize(s):
lowered in ['bijou', 'caillou', 'chou', 'genou', 'hibou', 'joujou',
'pou']:
return s + 'x'
elif lowered.endwith('al') and \
elif lowered.endswith('al') and \
lowered not in ['bal', 'carnaval', 'chacal', 'festival', 'récital',
'régal', 'cal', 'étal', 'aval', 'caracal', 'val', 'choral',
'corral', 'galgal', 'gayal']:
@ -53,7 +53,7 @@ def pluralize(s):
return s + 'x'
elif lowered == 'pare-feu':
return s
elif lowered.endwith('eu') and \
elif lowered.endswith('eu') and \
lowered not in ['bleu', 'pneu', 'émeu', 'enfeu']:
# Note: when 'lieu' is a fish, it has a 's' ; else, it has a 'x'
return s + 'x'

View File

@ -61,7 +61,7 @@ conf.registerChannelValue(Factoids, 'replyWhenInvalidCommand',
commands by searching for a factoid; basically making the whatis
unnecessary when you want all factoids for a given key.""")))
conf.registerChannelValue(Factoids, 'format',
FactoidFormat('$key could be $value.', _("""Determines the format of
FactoidFormat(_('$key could be $value.'), _("""Determines the format of
the response given when a factoid's value is requested. All the standard
substitutes apply, in addition to "$key" for the factoid's key and "$value"
for the factoid's value.""")))

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Supybot-fr\n"
"POT-Creation-Date: 2010-10-17 10:59+CEST\n"
"POT-Creation-Date: 2010-11-11 12:37+CET\n"
"PO-Revision-Date: \n"
"Last-Translator: Valentin Lorentz <progval@gmail.com>\n"
"Language-Team: Supybot-fr <progval@gmail.com>\n"
@ -41,6 +41,10 @@ msgid ""
" unnecessary when you want all factoids for a given key."
msgstr "Détermine si le bot répondra aux commandes invalides lors de la recherche d'une factoid ; permet simplement de rendre la commande 'whatis' inutile lorsque vous voulez toutes les factoids d'un clef donnée."
#: config.py:64
msgid "$key could be $value."
msgstr "$key semble être $value."
#: config.py:64
msgid ""
"Determines the format of\n"

View File

@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2010-10-17 10:59+CEST\n"
"POT-Creation-Date: 2010-11-11 12:37+CET\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -44,6 +44,10 @@ msgid ""
" unnecessary when you want all factoids for a given key."
msgstr ""
#: config.py:64
msgid "$key could be $value."
msgstr ""
#: config.py:64
msgid ""
"Determines the format of\n"

View File

@ -104,5 +104,5 @@ msgstr "Il n'y a pas de note pour %r"
#: plugin.py:182
msgid "Sent %s: <%s> %s"
msgstr "Envoyé le %s : "
msgstr "Envoyé le %s : <%s> %s"

View File

@ -69,11 +69,11 @@ msgstr "plugin"
#: plugin.py:92
msgid "The %q command is available in the %L %s."
msgstr "La commande %q est disponibles dans le(s) plugin %v."
msgstr "La commande %q est disponibles dans le(s) plugin(s) %L%v."
#: plugin.py:95
msgid "There is no command %q."
msgstr "Il n'y a pas de commande q."
msgstr "Il n'y a pas de commande %q."
#: plugin.py:100
msgid ""

View File

@ -61,6 +61,7 @@ import textwrap
started = time.time()
import supybot
import supybot.i18n as i18n
import supybot.utils as utils
import supybot.registry as registry
import supybot.questions as questions
@ -178,6 +179,7 @@ if __name__ == '__main__':
docs/GETTING_STARTED and follow the instructions."""))
else:
registryFilename = args.pop()
i18n.getLocaleFromRegistryFilename(registryFilename)
try:
# The registry *MUST* be opened before importing log or conf.
registry.open(registryFilename)
@ -210,6 +212,7 @@ if __name__ == '__main__':
sys.exit(-1)
import supybot.conf as conf
import supybot.world as world
i18n.import_conf()
world.starting = True
def closeRegistry():

View File

@ -199,7 +199,7 @@ def getFloat(irc, msg, args, state, type=_('floating point number')):
def getPositiveInt(irc, msg, args, state, *L):
getInt(irc, msg, args, state,
p=lambda i: i>0, type=_('positive integer') *L)
p=lambda i: i>0, type=_('positive integer'), *L)
def getNonNegativeInt(irc, msg, args, state, *L):
getInt(irc, msg, args, state,

View File

@ -37,6 +37,7 @@ import re
import sys
import time
import threading
conf = None
# Don't import conf here ; because conf needs this module
WAITING_FOR_MSGID = 1
@ -47,16 +48,26 @@ IN_MSGSTR = 4
MSGID = 'msgid "'
MSGSTR = 'msgstr "'
currentLocale = 'en'
def getLocaleFromRegistryFilename(filename):
"""Called by the 'supybot' script. Gets the locale name before conf is
loaded."""
global currentLocale
for line in open(filename, 'r'):
if line.startswith('supybot.language: '):
currentLocale = line[len('supybot.language: '):]
def import_conf():
import supybot.conf as conf
globals().update({'conf': conf})
"""Imports the conf into this module"""
global conf
conf = __import__('supybot.conf').conf
conf.registerGlobalValue(conf.supybot, 'language',
conf.registry.String('en', """Determines the bot's default language.
Valid values are things like en, fr, de, etc."""))
for key in i18nClasses:
i18nClasses[key].loadLocale()
conf.registry.String(currentLocale, """Determines the bot's default
language. Valid values are things like en, fr, de, etc."""))
def getPluginDir(plugin_name):
"""Gets the directory of the given plugin"""
filename = None
try:
filename = sys.modules[plugin_name].__file__
@ -74,6 +85,8 @@ def getPluginDir(plugin_name):
return
def getLocalePath(name, localeName, extension):
"""Gets the path of the locale file of the given plugin ('supybot' stands
for the core)."""
if name != 'supybot':
directory = getPluginDir(name) + 'locale'
else:
@ -85,7 +98,15 @@ i18nClasses = {}
internationalizedCommands = {}
internationalizedFunctions = [] # No need to know there name
def reloadLocals():
def reloadLocalesIfRequired():
global currentLocale
if conf is None:
return
if currentLocale != conf.supybot.language():
currentLocale = conf.supybot.language()
reloadLocales()
def reloadLocales():
for pluginName in i18nClasses:
i18nClasses[pluginName].loadLocale()
for commandHash in internationalizedCommands:
@ -108,17 +129,12 @@ class _PluginInternationalization:
self.name = name
self.currentLocaleName = None
i18nClasses.update({name: self})
if name != 'supybot' and not 'conf' in globals():
# if conf is loadable but not loaded
import_conf()
self.loadLocale()
def loadLocale(self, localeName=None):
"""(Re)loads the locale used by this class."""
if localeName is None and 'conf' in globals():
localeName = conf.supybot.language()
elif localeName is None:
localeName = 'en'
if localeName is None:
localeName = currentLocale
self.currentLocaleName = localeName
self._loadL10nCode()
@ -179,14 +195,16 @@ class _PluginInternationalization:
self._addToDatabase(untranslated, translated)
def _addToDatabase(self, untranslated, translated):
untranslated = self._unescape(untranslated)
untranslated = self._unescape(untranslated, True)
translated = self._unescape(translated)
self.translations.update({untranslated: translated})
def _unescape(self, string):
def _unescape(self, string, removeNewline=False):
import supybot.utils as utils
string = str.replace(string, '\\n', '\n') # gettext escapes the \n
string = utils.str.normalizeWhitespace(string, removeNewline=False)
string = str.replace(string, '\\"', '"')
string = str.replace(string, "\'", "'")
string = utils.str.normalizeWhitespace(string, removeNewline)
return string
def __call__(self, untranslated):
@ -195,12 +213,8 @@ class _PluginInternationalization:
his is the function which is called when a plugin runs _()"""
if untranslated.__class__ == internationalizedString:
return untranslated._original
untranslated = self._unescape(untranslated)
if not 'conf' in globals():
return untranslated
if self.currentLocaleName != conf.supybot.language():
# If the locale has been changed
reloadLocals()
untranslated = self._unescape(untranslated, True)
reloadLocalesIfRequired()
try:
string = self._translate(untranslated)
return self._addTracker(string, untranslated)
@ -304,8 +318,14 @@ def internationalizeDocstring(obj):
"""Decorates functions and internationalize their docstring.
Only useful for commands (commands' docstring is displayed on IRC)"""
if obj.__doc__ == None:
return obj
if sys.modules[obj.__module__].__dict__.has_key('_'):
internationalizedCommands.update({hash(obj): obj})
try:
obj.__doc__=sys.modules[obj.__module__]._.__call__(obj.__doc__)
# We use _.__call__() instead of _() because of a pygettext warning.
except AttributeError:
# attribute '__doc__' of 'type' objects is not writable
pass
return obj

View File

@ -360,7 +360,6 @@ class PluginTestCase(SupyTestCase):
return
for cb in self.irc.callbacks:
name = cb.name()
print " --- " + name
if ((name in self._noTestDoc) and \
not name.lower() in self.__class__.__name__.lower()):
continue
@ -372,12 +371,6 @@ class PluginTestCase(SupyTestCase):
attr == callbacks.canonicalName(attr):
self.failUnless(getattr(cb, attr, None).__doc__,
'%s.%s has no help.' % (name, attr))
def testInternationalization(self):
name = self.__class__.__module__[0:-len('.test')]
if self.__class__.__module__.startswith('supybot'):
return
self.failIf(hasattr(sys.modules[name], '_') == False,
'%s has no internationalizer.' % name)

View File

@ -61,16 +61,10 @@ def rsplit(s, sep=None, maxsplit=-1):
def normalizeWhitespace(s, removeNewline=True):
"""Normalizes the whitespace in a string; \s+ becomes one space."""
beginning = s.startswith(' ')
ending = s.endswith(' ')
if removeNewline:
s = ' '.join(s.split())
else:
s = ' '.join(s.split(' '))
if beginning:
s = ' ' + s
if ending:
s = s + ' '
s = str.replace(s, '\n', '')
while ' ' in s:
s = str.replace(s, ' ', ' ')
return s
def distance(s, t):