Fix the internationalisation problem for the docstrings

This commit is contained in:
Valentin Lorentz 2010-10-10 14:45:25 +02:00
parent 842221801a
commit a750fe6a2e
4 changed files with 214 additions and 307 deletions

View File

@ -8,9 +8,9 @@ msgid ""
msgstr ""
"Project-Id-Version: supybot-i18n\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-10-06 16:16+0200\n"
"PO-Revision-Date: 2010-10-06 16:46+0100\n"
"Last-Translator: Valentin 'ProgVal' Lorentz <progval@gmail.com>\n"
"POT-Creation-Date: 2010-10-10 09:35+CEST\n"
"PO-Revision-Date: 2010-10-10 10:08+0100\n"
"Last-Translator: Valentin Lorentz <progval@gmail.com>\n"
"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
@ -18,59 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: plugin.py:252
msgid "I couldn't find you in my user database."
msgstr "Je ne peux vous trouver dans ma base de données."
#: plugin.py:265
msgid "%s has sent %n; a total of %n, %n, %n, and %n; %s of those messages %s. %s has joined %n, parted %n, quit %n, kicked someone %n, been kicked %n, changed the topic %n, and changed the mode %n."
msgstr "%s a envoyé %n ; un total de %n, %n, %n, et %n ; %s de ces messages %s. %s est arrivé %nfois, est parti %nfois, a quitté %nfois, a kické %nfois, a été kické %nfois, a changé le topic %nfois, et a changé les modes %nfois."
#: plugin.py:272
msgid "character"
msgstr "caractère"
#: plugin.py:273
#: plugin.py:355
msgid "word"
msgstr "mot"
#: plugin.py:274
#: plugin.py:356
msgid "smiley"
msgstr "smiley"
#: plugin.py:275
#: plugin.py:357
msgid "frown"
msgstr "sadley"
#: plugin.py:277
#: plugin.py:358
msgid "was an ACTION"
msgstr "était une action"
#: plugin.py:278
#: plugin.py:359
msgid "were ACTIONs"
msgstr "étaient des ACTIONs"
#: plugin.py:280
#: plugin.py:281
#: plugin.py:282
#: plugin.py:283
#: plugin.py:284
#: plugin.py:285
#: plugin.py:286
msgid "time"
msgstr " fois"
#: plugin.py:289
#, python-format
msgid "I have no stats for that %s in %s."
msgstr "Je n'ai pas de statistiques pour %s sur %s."
#: plugin.py:291
#: plugin.py:246
msgid ""
"[<channel>] [<name>]\n"
"\n"
@ -79,23 +27,62 @@ msgid ""
" isn't given, it defaults to the user sending the command.\n"
" "
msgstr ""
"[canal>] [nom]\n"
"[<canal>] [nom]\n"
"\n"
" Retourne les statistiques pour <nom> sur le <canal>. <canal> n'est nécessaire que si le message n'est pas envoyé sur le canal lui-même. Si <nom> n'est pas donné, il correspond par défaut à l'utilisateur envoyant la commande"
#: plugin.py:305
msgid "There's really no reason why you should have underscores or brackets in your mathematical expression. Please remove them."
msgstr "Il n'y a aucune raison pour que vous ayez des underscores ou des crochets dans vos expressions mathématiques. Veuillez les supprimer."
#: plugin.py:259
msgid "I couldn't find you in my user database."
msgstr "Je ne peux vous trouver dans ma base de données."
#: plugin.py:309
msgid "You can't use lambda in this command."
msgstr "Vous ne pouvez utiliser lambda dans cette commande."
#: plugin.py:272
msgid "%s has sent %n; a total of %n, %n, %n, and %n; %s of those messages %s. %s has joined %n, parted %n, quit %n, kicked someone %n, been kicked %n, changed the topic %n, and changed the mode %n."
msgstr "%s a envoyé %n ; un total de %n, %n, %n, et %n ; %s de ces messages %s. %s est arrivé %nfois, est parti %nfois, a quitté %nfois, a kické %nfois, a été kické %nfois, a changé le topic %nfois, et a changé les modes %nfois."
#: plugin.py:323
msgid "stat variable"
msgstr "Variable statistique"
#: plugin.py:279
msgid "character"
msgstr "caractère"
#: plugin.py:335
#: plugin.py:280
#: plugin.py:363
msgid "word"
msgstr "mot"
#: plugin.py:281
#: plugin.py:364
msgid "smiley"
msgstr "smiley"
#: plugin.py:282
#: plugin.py:365
msgid "frown"
msgstr "sadley"
#: plugin.py:284
#: plugin.py:366
msgid "was an ACTION"
msgstr "était une action"
#: plugin.py:285
#: plugin.py:367
msgid "were ACTIONs"
msgstr "étaient des ACTIONs"
#: plugin.py:287
#: plugin.py:288
#: plugin.py:289
#: plugin.py:290
#: plugin.py:291
#: plugin.py:292
#: plugin.py:293
msgid "time"
msgstr " fois"
#: plugin.py:296
msgid "I have no stats for that %s in %s."
msgstr "Je n'ai pas de statistiques pour %s sur %s."
#: plugin.py:304
msgid ""
"[<channel>] <stat expression>\n"
"\n"
@ -110,50 +97,19 @@ msgstr ""
"\n"
"Retourne le rang des utilisateurs en fonction de l'expression de statistiques données. Les variables valides dans l'expression de statistiques sont : 'msgs', 'chars', 'words', 'smileys', 'frowns', 'actions', 'joins', 'parts', 'quits', 'kicks', 'kicked', 'topics', et 'modes'. Toute expression mathématiques simple utilisant ces variables est autorisée."
#: plugin.py:315
msgid "There's really no reason why you should have underscores or brackets in your mathematical expression. Please remove them."
msgstr "Il n'y a aucune raison pour que vous ayez des underscores ou des crochets dans vos expressions mathématiques. Veuillez les supprimer."
#: plugin.py:319
msgid "You can't use lambda in this command."
msgstr "Vous ne pouvez utiliser lambda dans cette commande."
#: plugin.py:333
msgid "stat variable"
msgstr "Variable statistique"
#: plugin.py:349
msgid "On %s there %h been %i messages, containing %i characters, %n, %n, and %n; %i of those messages %s. There have been %n, %n, %n, %n, %n, and %n. There %b currently %n and the channel has peaked at %n."
msgstr "Sur %s il y a eu%v %i messages, contenant %i caractères, %n, %n, et %n ; %i de ces messages %s. Il y a eu %n, %n, %n, %n, %n, et %n. Il y a%v actuellement %n et le record du canal est de %n."
#: plugin.py:360
msgid "join"
msgstr "arrivée"
#: plugin.py:361
msgid "part"
msgstr "départ"
#: plugin.py:362
msgid "quit"
msgstr "quit"
#: plugin.py:363
msgid "kick"
msgstr "kick"
#: plugin.py:364
msgid "mode"
msgstr "mode"
#: plugin.py:364
#: plugin.py:365
msgid "change"
msgstr "changement"
#: plugin.py:365
msgid "topic"
msgstr "topic"
#: plugin.py:367
#: plugin.py:368
msgid "user"
msgstr "utilisateur"
#: plugin.py:371
#, python-format
msgid "I've never been on %s."
msgstr "Je n'ai jamais été sur %s."
#: plugin.py:372
msgid ""
"[<channel>]\n"
"\n"
@ -165,3 +121,45 @@ msgstr ""
"\n"
"Retourne les statistiques pour le <canal>. <canal> n'est nécessaire que si le message n'est pas envoyé sur le canal lui-même."
#: plugin.py:357
msgid "On %s there %h been %i messages, containing %i characters, %n, %n, and %n; %i of those messages %s. There have been %n, %n, %n, %n, %n, and %n. There %b currently %n and the channel has peaked at %n."
msgstr "Sur %s il y a eu%v %i messages, contenant %i caractères, %n, %n, et %n ; %i de ces messages %s. Il y a eu %n, %n, %n, %n, %n, et %n. Il y a%v actuellement %n et le record du canal est de %n."
#: plugin.py:368
msgid "join"
msgstr "arrivée"
#: plugin.py:369
msgid "part"
msgstr "départ"
#: plugin.py:370
msgid "quit"
msgstr "quit"
#: plugin.py:371
msgid "kick"
msgstr "kick"
#: plugin.py:372
msgid "mode"
msgstr "mode"
#: plugin.py:372
#: plugin.py:373
msgid "change"
msgstr "changement"
#: plugin.py:373
msgid "topic"
msgstr "topic"
#: plugin.py:375
#: plugin.py:376
msgid "user"
msgstr "utilisateur"
#: plugin.py:379
msgid "I've never been on %s."
msgstr "Je n'ai jamais été sur %s."

View File

@ -1,107 +1,27 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-10-09 17:55+0200\n"
"POT-Creation-Date: 2010-10-10 09:35+CEST\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"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
#: plugin.py:48
msgid "ChannelStats"
msgstr ""
#: plugin.py:51
msgid "actions"
msgstr ""
#: plugin.py:51
msgid "chars"
msgstr ""
#: plugin.py:51 plugin.py:83
msgid "frowns"
msgstr ""
#: plugin.py:51
msgid "joins"
msgstr ""
#: plugin.py:51
msgid "kicks"
msgstr ""
#: plugin.py:51
msgid "modes"
msgstr ""
#: plugin.py:52
msgid "msgs"
msgstr ""
#: plugin.py:52
msgid "parts"
msgstr ""
#: plugin.py:52
msgid "quits"
msgstr ""
#: plugin.py:52 plugin.py:84
msgid "smileys"
msgstr ""
#: plugin.py:52
msgid "topics"
msgstr ""
#: plugin.py:52
msgid "words"
msgstr ""
#: plugin.py:52
msgid "users"
msgstr ""
#: plugin.py:121
msgid "kicked"
msgstr ""
#: plugin.py:139 plugin.py:147 plugin.py:148 plugin.py:149 plugin.py:160
#: plugin.py:206 plugin.py:207 plugin.py:208 plugin.py:210 plugin.py:225
#: plugin.py:226 plugin.py:227
msgid "channelStats"
msgstr ""
#: plugin.py:165
msgid "ChannelStats.db"
msgstr ""
#: plugin.py:195
msgid "PRIVMSG"
msgstr ""
#: plugin.py:197
msgid "selfStats"
msgstr ""
#: plugin.py:246
#, docstring
msgid ""
"[<channel>] [<name>]\n"
"\n"
" Returns the statistics for <name> on <channel>. <channel> is only\n"
" necessary if the message isn't sent on the channel itself. If "
"<name>\n"
" necessary if the message isn't sent on the channel itself. If <name>\n"
" isn't given, it defaults to the user sending the command.\n"
" "
msgstr ""
@ -111,37 +31,30 @@ msgid "I couldn't find you in my user database."
msgstr ""
#: plugin.py:272
msgid ""
"%s has sent %n; a total of %n, %n, %n, and %n; %s of those messages %s. %s "
"has joined %n, parted %n, quit %n, kicked someone %n, been kicked %n, "
"changed the topic %n, and changed the mode %n."
msgstr ""
#: plugin.py:278
msgid "message"
msgid "%s has sent %n; a total of %n, %n, %n, and %n; %s of those messages %s. %s has joined %n, parted %n, quit %n, kicked someone %n, been kicked %n, changed the topic %n, and changed the mode %n."
msgstr ""
#: plugin.py:279
msgid "character"
msgstr ""
#: plugin.py:280 plugin.py:365
#: plugin.py:280 plugin.py:363
msgid "word"
msgstr ""
#: plugin.py:281 plugin.py:366
#: plugin.py:281 plugin.py:364
msgid "smiley"
msgstr ""
#: plugin.py:282 plugin.py:367
#: plugin.py:282 plugin.py:365
msgid "frown"
msgstr ""
#: plugin.py:284 plugin.py:368
#: plugin.py:284 plugin.py:366
msgid "was an ACTION"
msgstr ""
#: plugin.py:285 plugin.py:369
#: plugin.py:285 plugin.py:367
msgid "were ACTIONs"
msgstr ""
@ -151,28 +64,15 @@ msgid "time"
msgstr ""
#: plugin.py:296
#, python-format
msgid "I have no stats for that %s in %s."
msgstr ""
#: plugin.py:298 plugin.py:346 plugin.py:382
msgid "channeldb"
msgstr ""
#: plugin.py:298
msgid "something"
msgstr ""
#: plugin.py:300
msgid "__builtins__"
msgstr ""
#: plugin.py:305
#: plugin.py:304
#, docstring
msgid ""
"[<channel>] <stat expression>\n"
"\n"
" Returns the ranking of users according to the given stat "
"expression.\n"
" Returns the ranking of users according to the given stat expression.\n"
" Valid variables in the stat expression include 'msgs', 'chars',\n"
" 'words', 'smileys', 'frowns', 'actions', 'joins', 'parts', 'quits',\n"
" 'kicks', 'kicked', 'topics', and 'modes'. Any simple mathematical\n"
@ -181,90 +81,64 @@ msgid ""
msgstr ""
#: plugin.py:315
msgid "_[]"
msgstr ""
#: plugin.py:316
msgid ""
"There's really no reason why you should have underscores or brackets in your "
"mathematical expression. Please remove them."
msgid "There's really no reason why you should have underscores or brackets in your mathematical expression. Please remove them."
msgstr ""
#: plugin.py:319
msgid "lambda"
msgstr ""
#: plugin.py:320
msgid "You can't use lambda in this command."
msgstr ""
#: plugin.py:332
msgid "inf"
msgstr ""
#: plugin.py:334
#: plugin.py:333
msgid "stat variable"
msgstr ""
#: plugin.py:343
#, python-format
msgid "#%s %s (%.3g)"
msgstr ""
#: plugin.py:346
msgid "text"
msgstr ""
#: plugin.py:351
#: plugin.py:349
#, docstring
msgid ""
"[<channel>]\n"
"\n"
" Returns the statistics for <channel>. <channel> is only necessary "
"if\n"
" Returns the statistics for <channel>. <channel> is only necessary if\n"
" the message isn't sent on the channel itself.\n"
" "
msgstr ""
#: plugin.py:359
msgid ""
"On %s there %h been %i messages, containing %i characters, %n, %n, and %n; "
"%i of those messages %s. There have been %n, %n, %n, %n, %n, and %n. There "
"%b currently %n and the channel has peaked at %n."
#: plugin.py:357
msgid "On %s there %h been %i messages, containing %i characters, %n, %n, and %n; %i of those messages %s. There have been %n, %n, %n, %n, %n, and %n. There %b currently %n and the channel has peaked at %n."
msgstr ""
#: plugin.py:370
#: plugin.py:368
msgid "join"
msgstr ""
#: plugin.py:371
#: plugin.py:369
msgid "part"
msgstr ""
#: plugin.py:372
#: plugin.py:370
msgid "quit"
msgstr ""
#: plugin.py:373
#: plugin.py:371
msgid "kick"
msgstr ""
#: plugin.py:374
#: plugin.py:372
msgid "mode"
msgstr ""
#: plugin.py:374 plugin.py:375
#: plugin.py:372 plugin.py:373
msgid "change"
msgstr ""
#: plugin.py:375
#: plugin.py:373
msgid "topic"
msgstr ""
#: plugin.py:377 plugin.py:378
#: plugin.py:375 plugin.py:376
msgid "user"
msgstr ""
#: plugin.py:381
#, python-format
#: plugin.py:379
msgid "I've never been on %s."
msgstr ""

View File

@ -34,7 +34,7 @@ import types
import supybot.log as log
import supybot.conf as conf
import supybot.i18n as i18n
from supybot.i18n import PluginInternationalization, internationalizeDocstring
import supybot.utils as utils
import supybot.world as world
import supybot.ircdb as ircdb
@ -45,7 +45,7 @@ import supybot.plugins as plugins
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
_ = i18n.PluginInternationalization('ChannelStats')
_ = PluginInternationalization('ChannelStats')
class ChannelStat(irclib.IrcCommandDispatcher):
_values = ['actions', 'chars', 'frowns', 'joins', 'kicks','modes',
@ -241,7 +241,14 @@ class ChannelStats(callbacks.Plugin):
self.db[channel, id] = UserStat()
self.db.channels[channel][id].kicked += 1
@internationalizeDocstring
def stats(self, irc, msg, args, channel, name):
"""[<channel>] [<name>]
Returns the statistics for <name> on <channel>. <channel> is only
necessary if the message isn't sent on the channel itself. If <name>
isn't given, it defaults to the user sending the command.
"""
if name and ircutils.strEqual(name, irc.nick):
id = 0
elif not name:
@ -288,17 +295,20 @@ class ChannelStats(callbacks.Plugin):
except KeyError:
irc.error(format(_('I have no stats for that %s in %s.'),
name, channel))
stats.__doc__ = _("""[<channel>] [<name>]
Returns the statistics for <name> on <channel>. <channel> is only
necessary if the message isn't sent on the channel itself. If <name>
isn't given, it defaults to the user sending the command.
""")
stats = wrap(stats, ['channeldb', additional('something')])
_env = {'__builtins__': types.ModuleType('__builtins__')}
_env.update(math.__dict__)
@internationalizeDocstring
def rank(self, irc, msg, args, channel, expr):
"""[<channel>] <stat expression>
Returns the ranking of users according to the given stat expression.
Valid variables in the stat expression include 'msgs', 'chars',
'words', 'smileys', 'frowns', 'actions', 'joins', 'parts', 'quits',
'kicks', 'kicked', 'topics', and 'modes'. Any simple mathematical
expression involving those variables is permitted.
"""
# XXX I could do this the right way, and abstract out a safe eval,
# or I could just copy/paste from the Math plugin.
if expr != expr.translate(utils.str.chars, '_[]'):
@ -332,17 +342,15 @@ class ChannelStats(callbacks.Plugin):
s = utils.str.commaAndify(['#%s %s (%.3g)' % (i+1, u, v)
for (i, (v, u)) in enumerate(users)])
irc.reply(s)
rank.__doc__ = _("""[<channel>] <stat expression>
Returns the ranking of users according to the given stat expression.
Valid variables in the stat expression include 'msgs', 'chars',
'words', 'smileys', 'frowns', 'actions', 'joins', 'parts', 'quits',
'kicks', 'kicked', 'topics', and 'modes'. Any simple mathematical
expression involving those variables is permitted.
""")
rank = wrap(rank, ['channeldb', 'text'])
@internationalizeDocstring
def channelstats(self, irc, msg, args, channel):
"""[<channel>]
Returns the statistics for <channel>. <channel> is only necessary if
the message isn't sent on the channel itself.
"""
try:
stats = self.db.getChannelStats(channel)
curUsers = len(irc.state.channels[channel].users)
@ -369,11 +377,6 @@ class ChannelStats(callbacks.Plugin):
irc.reply(s)
except KeyError:
irc.error(format(_('I\'ve never been on %s.'), channel))
channelstats.__doc__ = _("""[<channel>]
Returns the statistics for <channel>. <channel> is only necessary if
the message isn't sent on the channel itself.
""")
channelstats = wrap(channelstats, ['channeldb'])

View File

@ -33,6 +33,7 @@ Supybot internationalisation and localisation managment.
__all__ = ['PluginInternationalization']
import re
import sys
import supybot.conf as conf
@ -44,38 +45,50 @@ IN_MSGSTR = 4
MSGID = 'msgid "'
MSGSTR = 'msgstr "'
#registerGlobalValue(supybot, 'language',
# ValidNick('supybot', """Determines the bot's default language.
# Valid values are things like en, fr, de, etc."""))
conf.registerGlobalValue(conf.supybot, 'language',
conf.registry.String('en', """Determines the bot's default language.
Valid values are things like en, fr, de, etc."""))
def get_plugin_dir(plugin_name):
filename = sys.modules[plugin_name].__file__
if filename.endswith("plugin.pyc"):
return filename[0:-len("plugin.pyc")]
elif filename.endswith("plugin.py"):
return filename[0:-len("plugin.py")]
else:
return
if filename.endswith(".pyc"):
filename = filename[0:-1]
allowed_files = ['__init__.py', 'config.py', 'plugin.py', 'test.py']
for allowed_file in allowed_files:
if filename.endswith(allowed_file):
return filename[0:-len(allowed_file)]
return
i18nClasses = {}
internationalizedCommands = {}
def reloadLocals():
for pluginName in i18nClasses:
i18nClasses[pluginName].loadLocale()
for commandHash in internationalizedCommands:
internationalizeDocstring(internationalizedCommands[commandHash])
class PluginInternationalization:
"""Internationalization managment for a plugin."""
def __init__(self, name='supybot'):
self.name = name
self.load_locale('toto')
self.loadLocale()
i18nClasses.update({name: self})
def load_locale(self, locale_name):
directory = get_plugin_dir(self.name) + 'locale/'
def loadLocale(self, localeName=None):
if localeName is None:
localeName = conf.supybot.language()
self.currentLocaleName = localeName
directory = get_plugin_dir(self.name) + 'locale'
try:
translation_file = open('%s%s.po' % (directory, locale_name), 'ru')
translationFile = open('%s/%s.po' % (directory, localeName), 'ru')
except IOError: # The translation is unavailable
self.translations = {}
return
step = WAITING_FOR_MSGID
self.translations = {}
for line in translation_file:
for line in translationFile:
line = line[0:-1] # Remove the ending \n
if line.startswith(MSGID):
@ -102,22 +115,33 @@ class PluginInternationalization:
if step is WAITING_FOR_MSGSTR and line.startswith(MSGSTR):
data = line[len(MSGSTR):-1]
if len(data) == 0: # Multiline mode
step = IN_MSGID
step = IN_MSGSTR
else:
self.translations.update({untranslated: data})
self._translate(untranslated, data)
step = WAITING_FOR_MSGID
elif step is IN_MSGSTR and line.startswith('"') and \
line.endswith('"'):
untranslated += line[1:-1]
translated += line[1:-1]
elif step is IN_MSGSTR: # the MSGSTR is finished
step = WAITING_FOR_MSGID
if translated == '':
translated = untranslated
self.translations.update({untranslated: translated})
self._translate(untranslated, translated)
def _translate(self, untranslated, translated):
print repr({self._parse(untranslated): self._parse(translated)})
self.translations.update({self._parse(untranslated):
self._parse(translated)})
def _parse(self, string):
return str.replace(string, '\\n', '\n') # Replace \\n by \n
def __call__(self, untranslated, *args):
if self.currentLocaleName != conf.supybot.language():
# If the locale has been changed
reloadLocals()
if len(args) == 0:
try:
return self.translations[untranslated]
@ -127,3 +151,11 @@ class PluginInternationalization:
translation = self(untranslated)
return translation % args
def internationalizeDocstring(obj):
# FIXME: check if the plugin has an _ object
internationalizedCommands.update({hash(obj): obj})
print "----doc : " + repr(obj.__doc__)
print "----strings : " + repr(sys.modules[obj.__module__]._.translations.keys())
obj.__doc__=sys.modules[obj.__module__]._(obj.__doc__)
return obj