diff --git a/bot.py b/bot.py
index e1bdefa..d3b1ea2 100644
--- a/bot.py
+++ b/bot.py
@@ -41,6 +41,7 @@ from utils import _, __, send_async, answer_async, user_locale, game_locales, \
from shared_vars import botan, gm, updater, dispatcher
import simple_commands, settings
+from simple_commands import help
logging.basicConfig(
@@ -134,11 +135,11 @@ def leave_game(bot, update):
except NotEnoughPlayersError:
gm.end_game(chat, user)
- send_async(bot, chat.id, text=__("Game ended!"))
+ send_async(bot, chat.id, text=__("Game ended!", game.translate))
else:
send_async(bot, chat.id,
- text=__("Okay. Next Player: {name}").format(
+ text=__("Okay. Next Player: {name}", game.translate).format(
name=display_name(game.current_player.user)),
reply_to_message_id=update.message.message_id)
@@ -185,20 +186,20 @@ def status_update(bot, update):
chat = update.message.chat
if update.message.left_chat_member:
- try:
- user = update.message.left_chat_member
- except KeyError:
- return
+ user = update.message.left_chat_member
try:
gm.leave_game(user, chat)
+ game = gm.player_for_user_in_chat(user, chat).game
+
except NoGameInChatError:
pass
except NotEnoughPlayersError:
gm.end_game(chat, user)
- send_async(bot, chat.id, text=__("Game ended!"))
+ send_async(bot, chat.id, text=__("Game ended!", game.translate))
else:
- send_async(bot, chat.id, text=__("Removing {name} from the game")
+ send_async(bot, chat.id, text=__("Removing {name} from the game",
+ game.translate)
.format(name=display_name(user)))
@@ -230,6 +231,13 @@ def start_game(bot, update, args):
game.play_card(game.last_card)
game.started = True
+ first_message = (
+ __("First player: {name}\n"
+ "Use /close to stop people from joining the game.\n"
+ "Enable multi-translations with /enable_translations",
+ game.translate)
+ .format(name=display_name(game.current_player.user)))
+
@run_async
def send_first():
"""Send the first card and player"""
@@ -239,12 +247,7 @@ def start_game(bot, update, args):
timeout=TIMEOUT)
bot.sendMessage(chat.id,
- text=__("First player: {name}\n"
- "Use /close to stop people from "
- "joining the game.")
- .format(
- name=display_name(game.current_player.user)
- ),
+ text=first_message,
timeout=TIMEOUT)
send_first()
@@ -327,6 +330,63 @@ def open_game(bot, update):
return
+@user_locale
+def enable_translations(bot, update):
+ """Handler for the /enable_translations command"""
+ chat = update.message.chat
+ user = update.message.from_user
+ games = gm.chatid_games.get(chat.id)
+
+ if not games:
+ send_async(bot, chat.id,
+ text=_("There is no running game in this chat."))
+ return
+
+ game = games[-1]
+
+ if game.owner.id == user.id:
+ game.translate = True
+ send_async(bot, chat.id, text=_("Enabled multi-translations. "
+ "Disable with /disable_translations"))
+ return
+
+ else:
+ send_async(bot, chat.id,
+ text=_("Only the game creator ({name}) can do that")
+ .format(name=game.owner.first_name),
+ reply_to_message_id=update.message.message_id)
+ return
+
+
+@user_locale
+def disable_translations(bot, update):
+ """Handler for the /disable_translations command"""
+ chat = update.message.chat
+ user = update.message.from_user
+ games = gm.chatid_games.get(chat.id)
+
+ if not games:
+ send_async(bot, chat.id,
+ text=_("There is no running game in this chat."))
+ return
+
+ game = games[-1]
+
+ if game.owner.id == user.id:
+ game.translate = False
+ send_async(bot, chat.id, text=_("Disabled multi-translations. "
+ "Enable them again with "
+ "/enable_translations"))
+ return
+
+ else:
+ send_async(bot, chat.id,
+ text=_("Only the game creator ({name}) can do that")
+ .format(name=game.owner.first_name),
+ reply_to_message_id=update.message.message_id)
+ return
+
+
@game_locales
@user_locale
def skip_player(bot, update):
@@ -365,7 +425,7 @@ def skip_player(bot, update):
send_async(bot, chat.id,
text=__("Waiting time to skip this player has "
"been reduced to {time} seconds.\n"
- "Next player: {name}")
+ "Next player: {name}", game.translate)
.format(time=skipped_player.waiting_time,
name=display_name(next_player.user)))
game.turn()
@@ -376,7 +436,7 @@ def skip_player(bot, update):
send_async(bot, chat.id,
text=__("{name1} was skipped four times in a row "
"and has been removed from the game.\n"
- "Next player: {name2}")
+ "Next player: {name2}", game.translate)
.format(name1=display_name(skipped_player.user),
name2=display_name(next_player.user)))
@@ -384,11 +444,12 @@ def skip_player(bot, update):
send_async(bot, chat.id,
text=__("{name} was skipped four times in a row "
"and has been removed from the game.\n"
- "The game ended.")
+ "The game ended.", game.translate)
.format(name=display_name(skipped_player.user)))
gm.end_game(chat.id, skipped_player.user)
+
@game_locales
@user_locale
def reply_to_query(bot, update):
@@ -420,10 +481,10 @@ def reply_to_query(bot, update):
add_draw(player, results)
else:
- add_pass(results)
+ add_pass(results, game)
if game.last_card.special == c.DRAW_FOUR and game.draw_counter:
- add_call_bluff(results)
+ add_call_bluff(results, game)
playable = player.playable_cards()
added_ids = list() # Duplicates are not allowed
@@ -479,7 +540,7 @@ def process_result(bot, update):
return
elif int(anti_cheat) != last_anti_cheat:
send_async(bot, chat.id,
- text=__("Cheat attempt by {name}")
+ text=__("Cheat attempt by {name}", game.translate)
.format(name=display_name(player.user)))
return
elif result_id == 'call_bluff':
@@ -498,7 +559,7 @@ def process_result(bot, update):
if game in gm.chatid_games.get(chat.id, list()):
send_async(bot, chat.id,
- text=__("Next player: {name}")
+ text=__("Next player: {name}", game.translate)
.format(name=display_name(game.current_player.user)))
@@ -510,7 +571,8 @@ def reset_waiting_time(bot, player):
player.waiting_time = 90
send_async(bot, chat.id,
text=__("Waiting time for {name} has been reset to 90 "
- "seconds").format(name=display_name(player.user)))
+ "seconds", player.game.translate)
+ .format(name=display_name(player.user)))
def do_play_card(bot, player, result_id):
@@ -529,11 +591,12 @@ def do_play_card(bot, player, result_id):
if len(player.cards) == 0:
send_async(bot, chat.id,
- text=__("{name} won!").format(name=user.first_name))
+ text=__("{name} won!", game.translate)
+ .format(name=user.first_name))
try:
gm.leave_game(user, chat)
except NotEnoughPlayersError:
- send_async(bot, chat.id, text=__("Game ended!"))
+ send_async(bot, chat.id, text=__("Game ended!", game.translate))
gm.end_game(chat, user)
if botan:
@@ -551,7 +614,8 @@ def do_draw(bot, player):
player.draw()
except DeckEmptyError:
send_async(bot, player.game.chat.id,
- text=__("There are no more cards in the deck."))
+ text=__("There are no more cards in the deck.",
+ game.translate))
if (game.last_card.value == c.DRAW_TWO or
game.last_card.special == c.DRAW_FOUR) and \
@@ -566,26 +630,30 @@ def do_call_bluff(bot, player):
if player.prev.bluffing:
send_async(bot, chat.id,
- text=__("Bluff called! Giving 4 cards to {name}")
+ text=__("Bluff called! Giving 4 cards to {name}",
+ game.translate)
.format(name=player.prev.user.first_name))
try:
player.prev.draw()
except DeckEmptyError:
send_async(bot, player.game.chat.id,
- text=__("There are no more cards in the deck."))
+ text=__("There are no more cards in the deck.",
+ game.translate))
else:
game.draw_counter += 2
send_async(bot, chat.id,
- text=__("{name1} didn't bluff! Giving 6 cards to {name2}")
+ text=__("{name1} didn't bluff! Giving 6 cards to {name2}",
+ game.translate)
.format(name1=player.prev.user.first_name,
name2=player.user.first_name))
try:
player.draw()
except DeckEmptyError:
send_async(bot, player.game.chat.id,
- text=__("There are no more cards in the deck."))
+ text=__("There are no more cards in the deck.",
+ game.translate))
game.turn()
@@ -600,6 +668,10 @@ dispatcher.add_handler(CommandHandler('join', join_game))
dispatcher.add_handler(CommandHandler('leave', leave_game))
dispatcher.add_handler(CommandHandler('open', open_game))
dispatcher.add_handler(CommandHandler('close', close_game))
+dispatcher.add_handler(CommandHandler('enable_translations',
+ enable_translations))
+dispatcher.add_handler(CommandHandler('disable_translations',
+ disable_translations))
dispatcher.add_handler(CommandHandler('skip', skip_player))
dispatcher.add_handler(MessageHandler([Filters.status_update], status_update))
dispatcher.add_error_handler(error)
diff --git a/game.py b/game.py
index cbfc575..f25726a 100644
--- a/game.py
+++ b/game.py
@@ -34,6 +34,7 @@ class Game(object):
started = False
owner = None
open = True
+ translate = False
def __init__(self, chat):
self.chat = chat
diff --git a/game_manager.py b/game_manager.py
index a505ade..0013cba 100644
--- a/game_manager.py
+++ b/game_manager.py
@@ -77,6 +77,8 @@ class GameManager(object):
self.leave_game(user, chat)
except NoGameInChatError:
pass
+ except NotEnoughPlayersError:
+ self.end_game(chat, user)
player = Player(game, user)
diff --git a/locales/de_DE/LC_MESSAGES/unobot.po b/locales/de_DE/LC_MESSAGES/unobot.po
index 89a0232..9ce018d 100644
--- a/locales/de_DE/LC_MESSAGES/unobot.po
+++ b/locales/de_DE/LC_MESSAGES/unobot.po
@@ -18,7 +18,7 @@
#: bot.py:224
msgid ""
msgstr ""
-"Project-Id-Version: mau_mau_bot 0.1\n"
+"Project-Id-Version: uno_bot 0.1\n"
"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
"POT-Creation-Date: 2016-05-19 22:38+0200\n"
"PO-Revision-Date: 2016-05-21 21:16+0200\n"
@@ -32,8 +32,7 @@ msgstr ""
"X-Generator: Gtranslator 2.91.6\n"
#: bot.py:60
-msgid ""
-"Follow these steps:\n"
+msgid "Follow these steps:\n"
"\n"
"1. Add this bot to a group\n"
"2. In the group, start a new game with /new or join an already running game "
@@ -49,9 +48,13 @@ msgid ""
"player takes more than 90 seconds to play, you can use /skip to skip that "
"player.\n"
"\n"
+"Language and other settings: /settings\n"
"Other commands (only game creator):\n"
"/close - Close lobby\n"
"/open - Open lobby\n"
+"/enable_translations - Translate relevant texts into all "
+"languages spoken in a game\n"
+"/disable_translations - Use English for those texts\n"
"\n"
"Experimental: Play in multiple groups at the same time. Press the "
"Current game: ...
button and select the group you want to play "
@@ -78,9 +81,13 @@ msgstr ""
"benutze /leave. Wenn ein Spieler länger als 90 Sekunden braucht, kannst du "
"ihn mit /skip überspringen.\n"
"\n"
+"Sprache und andere Einstellungen: /settings\n"
"Weitere Kommandos (nur Spiel-Ersteller):\n"
"/close - Lobby schließen\n"
"/open - Lobby öffnen\n"
+"/enable_translations - Übersetze relevante Texte in alle im Spiel gesprochenen"
+" Sprachen\n"
+"/disable_translations - Verwende Englisch für diese Texte\n"
"\n"
"Experimentell: Spiele in mehreren Gruppen gleichzeitig. Um die "
"Gruppe, in der du deine Karte spielen willst, auszuwählen, tippe auf den "
@@ -170,15 +177,14 @@ msgstr "Das Spiel hat bereits begonnen"
#: bot.py:281
msgid "At least two players must /join the game before you can start it"
-msgstr ""
-"Es müssen mindestens zwei Spieler dem Spiel beitreten, bevor du es starten "
-"kannst"
+msgstr "Es müssen mindestens zwei Spieler dem Spiel beitreten, bevor du es "
+"starten kannst"
#: bot.py:297
-#, python-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game."
+#, python-format, fuzzy
+msgid "First player: {name}\n"
+"Use /close to stop people from joining the game.\n"
+"Enable multi-translations with /enable_translations"
msgstr ""
"Erster Spieler: {name}\n"
"Benutze /close, um zu verhindern, dass weitere Spieler beitreten."
@@ -201,6 +207,17 @@ msgstr ""
msgid "Only the game creator ({name}) can do that."
msgstr "Dies kann nur der Ersteller des Spiels ({name}) tun."
+#: bot.py:349
+#, python-format
+msgid "Enabled multi-translations. Disable with /disable_translations"
+msgstr "Multi-Übersetzungen aktiviert. Deaktivieren mit /disable_translations"
+
+#: bot.py:377
+#, python-format
+msgid "Disabled multi-translations. Enable them again with /enable_translations"
+msgstr "Multi-Übersetzungen deaktiviert. Aktiviere sie wieder mit "
+"/enable_translations"
+
#: bot.py:368
msgid "Opened the lobby. New players may /join the game."
msgstr "Lobby geöffnet. Neue Spieler können nun beitreten."
@@ -259,7 +276,7 @@ msgid "Cheat attempt by %s"
msgstr "{name} hat versucht zu schummeln!"
#: bot.py:562
-msgid "Next player: "
+msgid "Next player: {name}"
msgstr "Nächster Spieler: {name}"
#: bot.py:572
diff --git a/locales/unobot.pot b/locales/unobot.pot
index 2742045..0005894 100644
--- a/locales/unobot.pot
+++ b/locales/unobot.pot
@@ -19,7 +19,7 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: mau_mau_bot 0.1\n"
+"Project-Id-Version: uno_bot 0.1\n"
"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
"POT-Creation-Date: 2016-05-19 22:38+0200\n"
"PO-Revision-Date: 2016-05-19 22:38+0200\n"
@@ -32,6 +32,7 @@ msgstr ""
#: bot.py:60
+#, fuzzy
msgid "Follow these steps:\n"
"\n"
"1. Add this bot to a group\n"
@@ -48,10 +49,13 @@ msgid "Follow these steps:\n"
"player takes more than 90 seconds to play, you can use /skip to skip that "
"player.\n"
"\n"
+"Language and other settings: /settings\n"
"Other commands (only game creator):\n"
"/close - Close lobby\n"
"/open - Open lobby\n"
-"\n"
+"/enable_translations - Translate relevant texts into all "
+"languages spoken in a game\n"
+"/disable_translations - Use English for those texts\n\n"
"Experimental: Play in multiple groups at the same time. Press the "
"Current game: ...
button and select the group you want to play "
"a card in.\n"
@@ -136,9 +140,10 @@ msgstr ""
#: bot.py:297
-#, python-format
+#, python-format, fuzzy
msgid "First player: {name}\n"
-"Use /close to stop people from joining the game."
+"Use /close to stop people from joining the game.\n"
+"Enable multi-translations with /enable_translations"
msgstr ""
#: bot.py:321
@@ -159,6 +164,16 @@ msgstr ""
msgid "Only the game creator ({name}) can do that."
msgstr ""
+#: bot.py:349
+#, python-format
+msgid "Enabled multi-translations. Disable with /disable_translations"
+msgstr ""
+
+#: bot.py:377
+#, python-format
+msgid "Disabled multi-translations. Enable them again with /enable_translations"
+msgstr ""
+
#: bot.py:368
msgid "Opened the lobby. New players may /join the game."
msgstr ""
diff --git a/results.py b/results.py
index 47fa31b..722656d 100644
--- a/results.py
+++ b/results.py
@@ -100,9 +100,10 @@ def add_draw(player, results):
Sticker(
"draw", sticker_file_id=c.STICKERS['option_draw'],
input_message_content=
- InputTextMessageContent(__('Drawing 1 card')
+ InputTextMessageContent(__('Drawing 1 card', player.game.translate)
if n == 1 else
- __('Drawing {number} cards')
+ __('Drawing {number} cards',
+ player.game.translate)
.format(number=n))
)
)
@@ -120,24 +121,26 @@ def add_gameinfo(game, results):
)
-def add_pass(results):
+def add_pass(results, game):
"""Add option to pass"""
results.append(
Sticker(
"pass", sticker_file_id=c.STICKERS['option_pass'],
- input_message_content=InputTextMessageContent(__('Pass'))
+ input_message_content=InputTextMessageContent(__('Pass',
+ game.translate))
)
)
-def add_call_bluff(results):
+def add_call_bluff(results, game):
"""Add option to call a bluff"""
results.append(
Sticker(
"call_bluff",
sticker_file_id=c.STICKERS['option_bluff'],
input_message_content=
- InputTextMessageContent(__("I'm calling your bluff!"))
+ InputTextMessageContent(__("I'm calling your bluff!",
+ game.translate))
)
)
diff --git a/simple_commands.py b/simple_commands.py
index 5fb9d13..51c0770 100644
--- a/simple_commands.py
+++ b/simple_commands.py
@@ -39,9 +39,13 @@ help_text = ("Follow these steps:\n\n"
"Players can join the game at any time. To leave a game, "
"use /leave. If a player takes more than 90 seconds to play, "
"you can use /skip to skip that player.\n\n"
+ "Language and other settings: /settings\n"
"Other commands (only game creator):\n"
"/close - Close lobby\n"
- "/open - Open lobby\n\n"
+ "/open - Open lobby\n"
+ "/enable_translations - Translate relevant texts into all "
+ "languages spoken in a game\n"
+ "/disable_translations - Use English for those texts\n\n"
"Experimental: Play in multiple groups at the same time. "
"Press the Current game: ...
button and select the "
"group you want to play a card in.\n"
diff --git a/utils.py b/utils.py
index 1d0676f..9d93152 100644
--- a/utils.py
+++ b/utils.py
@@ -29,6 +29,7 @@ from telegram.ext.dispatcher import run_async
import locales
from database import db_session
from user_setting import UserSetting
+from shared_vars import gm
strategy = PackageStrategy('unobot', locales)
application = registry.register(strategy)
@@ -38,27 +39,28 @@ logger = logging.getLogger(__name__)
TIMEOUT = 2.5
-def __(string):
+def __(string, multi_translate):
"""Translates text into all locales on the stack"""
translations = list()
locales = list()
- while True:
- translation = _(string)
-
- if translation not in translations:
- translations.append(translation)
-
- l = _.code
+ if not multi_translate:
+ _.push('en_US')
+ translations.append(_(string))
_.pop()
- if l is None:
- break
- else:
- locales.append(l)
+ else:
+ while _.code:
+ translation = _(string)
- for l in reversed(locales):
- _.push(l)
+ if translation not in translations:
+ translations.append(translation)
+
+ locales.append(_.code)
+ _.pop()
+
+ for l in reversed(locales):
+ _.push(l)
return '\n'.join(translations) # TODO
@@ -126,12 +128,16 @@ def user_locale(func):
@wraps(func)
@db_session
def wrapped(bot, update, *pargs, **kwargs):
+ user, chat = _user_chat_from_update(update)
+
with db_session:
- us = UserSetting.get(id=update.message.from_user.id)
+ us = UserSetting.get(id=user.id)
+
if us:
_.push(us.lang)
else:
_.push('en_US')
+
result = func(bot, update, *pargs, **kwargs)
_.pop()
return result
@@ -141,15 +147,50 @@ def user_locale(func):
def game_locales(func):
@wraps(func)
@db_session
- def wrapped(*pargs, **kwargs):
- num_locales = 0
- for loc in ('en_US', 'de_DE'): # TODO: Get user locales from Database
- _.push(loc)
- num_locales += 1
+ def wrapped(bot, update, *pargs, **kwargs):
+ user, chat = _user_chat_from_update(update)
+ player = gm.player_for_user_in_chat(user, chat)
+ locales = list()
- result = func(*pargs, **kwargs)
+ if player:
+ for player in player.game.players:
+ us = UserSetting.get(id=player.user.id)
- for i in range(num_locales):
+ if us:
+ loc = us.lang
+ else:
+ loc = 'en_US'
+
+ if loc in locales:
+ continue
+
+ _.push(loc)
+ locales.append(loc)
+
+ result = func(bot, update, *pargs, **kwargs)
+
+ for i in locales:
_.pop()
return result
- return wrapped
\ No newline at end of file
+ return wrapped
+
+
+def _user_chat_from_update(update):
+
+ try:
+ user = update.message.from_user
+ chat = update.message.chat
+ except (NameError, AttributeError):
+ try:
+ user = update.inline_query.from_user
+ chat = gm.userid_current[user.id].game.chat
+ except KeyError:
+ chat = None
+ except (NameError, AttributeError):
+ try:
+ user = update.chosen_inline_result.from_user
+ chat = gm.userid_current[user.id].game.chat
+ except (NameError, AttributeError):
+ chat = None
+
+ return user, chat