add __ function to translate complete stack, add dummy decorators to pull locales from db

This commit is contained in:
Jannes Höke 2016-05-22 03:13:05 +02:00
parent 5ece46527a
commit cddf13dc5d
4 changed files with 97 additions and 53 deletions

96
bot.py
View file

@ -20,6 +20,7 @@
import logging import logging
from datetime import datetime from datetime import datetime
from functools import wraps
from random import randint from random import randint
from telegram import ParseMode, Message, Chat, InlineKeyboardMarkup, \ from telegram import ParseMode, Message, Chat, InlineKeyboardMarkup, \
@ -40,8 +41,7 @@ from utils import display_name
import card as c import card as c
from errors import (NoGameInChatError, LobbyClosedError, AlreadyJoinedError, from errors import (NoGameInChatError, LobbyClosedError, AlreadyJoinedError,
NotEnoughPlayersError, DeckEmptyError) NotEnoughPlayersError, DeckEmptyError)
from database import db_session, user_locale from utils import _, __
from utils import _
TIMEOUT = 2.5 TIMEOUT = 2.5
@ -92,6 +92,32 @@ source_text = ("This bot is Free Software and licensed under the AGPL. "
"https://github.com/jh0ker/mau_mau_bot") "https://github.com/jh0ker/mau_mau_bot")
def user_locale(func):
@wraps(func)
def wrapped(*pargs, **kwargs):
_.push('de_DE') # TODO: Get user locale from Database
result = func(*pargs, **kwargs)
_.pop()
return result
return wrapped
def game_locales(func):
@wraps(func)
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
result = func(*pargs, **kwargs)
for i in range(num_locales):
_.pop()
return result
return wrapped
@run_async @run_async
def send_async(bot, *args, **kwargs): def send_async(bot, *args, **kwargs):
"""Send a message asynchronously""" """Send a message asynchronously"""
@ -169,8 +195,8 @@ def join_game(bot, update):
except DeckEmptyError: except DeckEmptyError:
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("There are not enough cards left in the deck for new " text=_("There are not enough cards left in the deck for "
"players to join."), "new players to join."),
reply_to_message_id=update.message.message_id) reply_to_message_id=update.message.message_id)
else: else:
@ -206,11 +232,11 @@ def leave_game(bot, update):
except NotEnoughPlayersError: except NotEnoughPlayersError:
gm.end_game(chat, user) gm.end_game(chat, user)
send_async(bot, chat.id, text=_("Game ended!")) send_async(bot, chat.id, text=__("Game ended!"))
else: else:
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("Okay. Next Player: {name}").format( text=__("Okay. Next Player: {name}").format(
name=display_name(game.current_player.user)), name=display_name(game.current_player.user)),
reply_to_message_id=update.message.message_id) reply_to_message_id=update.message.message_id)
@ -251,7 +277,7 @@ def select_game(bot, update):
timeout=TIMEOUT) timeout=TIMEOUT)
@user_locale @game_locales
def status_update(bot, update): def status_update(bot, update):
"""Remove player from game if user leaves the group""" """Remove player from game if user leaves the group"""
chat = update.message.chat chat = update.message.chat
@ -268,12 +294,13 @@ def status_update(bot, update):
pass pass
except NotEnoughPlayersError: except NotEnoughPlayersError:
gm.end_game(chat, user) gm.end_game(chat, user)
send_async(bot, chat.id, text=_("Game ended!")) send_async(bot, chat.id, text=__("Game ended!"))
else: else:
send_async(bot, chat.id, text=_("Removing {name} from the game") send_async(bot, chat.id, text=__("Removing {name} from the game")
.format(name=display_name(user))) .format(name=display_name(user)))
@game_locales
@user_locale @user_locale
def start_game(bot, update, args): def start_game(bot, update, args):
"""Handler for the /start command""" """Handler for the /start command"""
@ -310,9 +337,9 @@ def start_game(bot, update, args):
timeout=TIMEOUT) timeout=TIMEOUT)
bot.sendMessage(chat.id, bot.sendMessage(chat.id,
text=_("First player: {name}\n" text=__("First player: {name}\n"
"Use /close to stop people from " "Use /close to stop people from "
"joining the game.") "joining the game.")
.format( .format(
name=display_name(game.current_player.user) name=display_name(game.current_player.user)
), ),
@ -398,6 +425,7 @@ def open_game(bot, update):
return return
@game_locales
@user_locale @user_locale
def skip_player(bot, update): def skip_player(bot, update):
"""Handler for the /skip command""" """Handler for the /skip command"""
@ -433,9 +461,9 @@ def skip_player(bot, update):
pass pass
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("Waiting time to skip this player has " text=__("Waiting time to skip this player has "
"been reduced to {time} seconds.\n" "been reduced to {time} seconds.\n"
"Next player: {name}") "Next player: {name}")
.format(time=skipped_player.waiting_time, .format(time=skipped_player.waiting_time,
name=display_name(next_player.user))) name=display_name(next_player.user)))
game.turn() game.turn()
@ -444,17 +472,17 @@ def skip_player(bot, update):
try: try:
gm.leave_game(skipped_player.user, chat) gm.leave_game(skipped_player.user, chat)
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("{name1} was skipped four times in a row " text=__("{name1} was skipped four times in a row "
"and has been removed from the game.\n" "and has been removed from the game.\n"
"Next player: {name2}") "Next player: {name2}")
.format(name1=display_name(skipped_player.user), .format(name1=display_name(skipped_player.user),
name2=display_name(next_player.user))) name2=display_name(next_player.user)))
except NotEnoughPlayersError: except NotEnoughPlayersError:
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("{name} was skipped four times in a row " text=__("{name} was skipped four times in a row "
"and has been removed from the game.\n" "and has been removed from the game.\n"
"The game ended.") "The game ended.")
.format(name=display_name(skipped_player.user))) .format(name=display_name(skipped_player.user)))
gm.end_game(chat.id, skipped_player.user) gm.end_game(chat.id, skipped_player.user)
@ -482,6 +510,7 @@ def news(bot, update):
disable_web_page_preview=True) disable_web_page_preview=True)
@game_locales
@user_locale @user_locale
def reply_to_query(bot, update): def reply_to_query(bot, update):
""" """
@ -543,6 +572,7 @@ def reply_to_query(bot, update):
switch_pm_text=switch, switch_pm_parameter='select') switch_pm_text=switch, switch_pm_parameter='select')
@game_locales
@user_locale @user_locale
def process_result(bot, update): def process_result(bot, update):
""" """
@ -570,7 +600,7 @@ def process_result(bot, update):
return return
elif int(anti_cheat) != last_anti_cheat: elif int(anti_cheat) != last_anti_cheat:
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("Cheat attempt by {name}") text=__("Cheat attempt by {name}")
.format(name=display_name(player.user))) .format(name=display_name(player.user)))
return return
elif result_id == 'call_bluff': elif result_id == 'call_bluff':
@ -589,7 +619,7 @@ def process_result(bot, update):
if game in gm.chatid_games.get(chat.id, list()): if game in gm.chatid_games.get(chat.id, list()):
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("Next player: {name}") text=__("Next player: {name}")
.format(name=display_name(game.current_player.user))) .format(name=display_name(game.current_player.user)))
@ -600,8 +630,8 @@ def reset_waiting_time(bot, player):
if player.waiting_time < 90: if player.waiting_time < 90:
player.waiting_time = 90 player.waiting_time = 90
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("Waiting time for {name} has been reset to 90 " text=__("Waiting time for {name} has been reset to 90 "
"seconds").format(name=display_name(player.user))) "seconds").format(name=display_name(player.user)))
def do_play_card(bot, player, result_id): def do_play_card(bot, player, result_id):
@ -616,15 +646,15 @@ def do_play_card(bot, player, result_id):
send_async(bot, chat.id, text=_("Please choose a color")) send_async(bot, chat.id, text=_("Please choose a color"))
if len(player.cards) == 1: if len(player.cards) == 1:
send_async(bot, chat.id, text=_("UNO!")) send_async(bot, chat.id, text="UNO!")
if len(player.cards) == 0: if len(player.cards) == 0:
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("{name} won!").format(name=user.first_name)) text=__("{name} won!").format(name=user.first_name))
try: try:
gm.leave_game(user, chat) gm.leave_game(user, chat)
except NotEnoughPlayersError: except NotEnoughPlayersError:
send_async(bot, chat.id, text=_("Game ended!")) send_async(bot, chat.id, text=__("Game ended!"))
gm.end_game(chat, user) gm.end_game(chat, user)
if botan: if botan:
@ -642,7 +672,7 @@ def do_draw(bot, player):
player.draw() player.draw()
except DeckEmptyError: except DeckEmptyError:
send_async(bot, player.game.chat.id, 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."))
if (game.last_card.value == c.DRAW_TWO or if (game.last_card.value == c.DRAW_TWO or
game.last_card.special == c.DRAW_FOUR) and \ game.last_card.special == c.DRAW_FOUR) and \
@ -657,26 +687,26 @@ def do_call_bluff(bot, player):
if player.prev.bluffing: if player.prev.bluffing:
send_async(bot, chat.id, send_async(bot, chat.id,
text=_("Bluff called! Giving 4 cards to {name}") text=__("Bluff called! Giving 4 cards to {name}")
.format(name=player.prev.user.first_name)) .format(name=player.prev.user.first_name))
try: try:
player.prev.draw() player.prev.draw()
except DeckEmptyError: except DeckEmptyError:
send_async(bot, player.game.chat.id, 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."))
else: else:
game.draw_counter += 2 game.draw_counter += 2
send_async(bot, chat.id, 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}")
.format(name1=player.prev.user.first_name, .format(name1=player.prev.user.first_name,
name2=player.user.first_name)) name2=player.user.first_name))
try: try:
player.draw() player.draw()
except DeckEmptyError: except DeckEmptyError:
send_async(bot, player.game.chat.id, 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.turn() game.turn()

View file

@ -18,21 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from functools import wraps
from pony.orm import Database, db_session, Optional, Required, Set, PrimaryKey from pony.orm import Database, db_session, Optional, Required, Set, PrimaryKey
from utils import _
# Database singleton # Database singleton
db = Database() db = Database()
def user_locale(func):
@wraps(func)
def wrapped(*pargs, **kwargs):
_.push('de_DE') # TODO: Get user locale from Database
result = func(*pargs, **kwargs)
_.pop()
return result
return wrapped

View file

@ -26,7 +26,7 @@ from telegram import InlineQueryResultArticle, InputTextMessageContent, \
InlineQueryResultCachedSticker as Sticker InlineQueryResultCachedSticker as Sticker
import card as c import card as c
from utils import display_color, display_name, list_subtract, _ from utils import display_color, display_name, list_subtract, _, __
def add_choose_color(results): def add_choose_color(results):
@ -61,7 +61,7 @@ def add_other_cards(playable, player, results, game):
def player_list(game): def player_list(game):
"""Generate list of player strings""" """Generate list of player strings"""
return ["{name} ({number} cards)" return [_("{name} ({number} cards)")
.format(name=player.user.first_name, number=len(player.cards)) .format(name=player.user.first_name, number=len(player.cards))
for player in game.players] for player in game.players]
@ -100,9 +100,9 @@ def add_draw(player, results):
Sticker( Sticker(
"draw", sticker_file_id=c.STICKERS['option_draw'], "draw", sticker_file_id=c.STICKERS['option_draw'],
input_message_content= input_message_content=
InputTextMessageContent(_('Drawing 1 card') InputTextMessageContent(__('Drawing 1 card')
if n == 1 else if n == 1 else
_('Drawing {number} cards') __('Drawing {number} cards')
.format(number=n)) .format(number=n))
) )
) )
@ -125,7 +125,7 @@ def add_pass(results):
results.append( results.append(
Sticker( Sticker(
"pass", sticker_file_id=c.STICKERS['option_pass'], "pass", sticker_file_id=c.STICKERS['option_pass'],
input_message_content=InputTextMessageContent(_('Pass')) input_message_content=InputTextMessageContent(__('Pass'))
) )
) )
@ -137,7 +137,7 @@ def add_call_bluff(results):
"call_bluff", "call_bluff",
sticker_file_id=c.STICKERS['option_bluff'], sticker_file_id=c.STICKERS['option_bluff'],
input_message_content= input_message_content=
InputTextMessageContent(_("I'm calling your bluff!")) InputTextMessageContent(__("I'm calling your bluff!"))
) )
) )

View file

@ -18,6 +18,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
from flufl.i18n import registry from flufl.i18n import registry
from flufl.i18n import PackageStrategy from flufl.i18n import PackageStrategy
@ -27,6 +29,32 @@ import locales
strategy = PackageStrategy('unobot', locales) strategy = PackageStrategy('unobot', locales)
application = registry.register(strategy) application = registry.register(strategy)
_ = application._ _ = application._
logger = logging.getLogger(__name__)
def __(string):
"""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
_.pop()
if l is None:
break
else:
locales.append(l)
for l in reversed(locales):
_.push(l)
return '\n'.join(translations) # TODO
def list_subtract(list1, list2): def list_subtract(list1, list2):