implement plurals, update de_DE translation to use plurals
This commit is contained in:
175
internationalization.py
Normal file
175
internationalization.py
Normal file
@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Telegram bot to play UNO in group chats
|
||||
# Copyright (c) 2016 Jannes Höke <uno@jhoeke.de>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import gettext
|
||||
from functools import wraps
|
||||
import logging
|
||||
|
||||
from locales import available_locales
|
||||
from database import db_session
|
||||
from user_setting import UserSetting
|
||||
from shared_vars import gm
|
||||
|
||||
GETTEXT_DOMAIN = 'unobot'
|
||||
GETTEXT_DIR = 'locales'
|
||||
|
||||
|
||||
class _Underscore(object):
|
||||
"""Class to emulate flufl.i18n behaviour, but with plural support"""
|
||||
def __init__(self):
|
||||
self.translators = {
|
||||
locale: gettext.GNUTranslations(
|
||||
open(gettext.find(
|
||||
GETTEXT_DOMAIN, GETTEXT_DIR, languages=[locale]
|
||||
), 'rb')
|
||||
)
|
||||
for locale
|
||||
in available_locales.keys()
|
||||
if locale != 'en_US' # No translation file for en_US
|
||||
}
|
||||
self.locale_stack = list()
|
||||
|
||||
def push(self, locale):
|
||||
self.locale_stack.append(locale)
|
||||
|
||||
def pop(self):
|
||||
if self.locale_stack:
|
||||
return self.locale_stack.pop()
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def code(self):
|
||||
if self.locale_stack:
|
||||
return self.locale_stack[-1]
|
||||
else:
|
||||
return None
|
||||
|
||||
def __call__(self, singular, plural=None, n=1, locale=None):
|
||||
if not locale:
|
||||
locale = self.locale_stack[-1]
|
||||
|
||||
if locale not in self.translators.keys():
|
||||
if n is 1:
|
||||
return singular
|
||||
else:
|
||||
return plural
|
||||
|
||||
translator = self.translators[locale]
|
||||
|
||||
if plural is None:
|
||||
return translator.gettext(singular)
|
||||
else:
|
||||
return translator.ngettext(singular, plural, n)
|
||||
|
||||
_ = _Underscore()
|
||||
|
||||
|
||||
def __(singular, plural=None, n=1, multi=False):
|
||||
"""Translates text into all locales on the stack"""
|
||||
translations = list()
|
||||
|
||||
if not multi:
|
||||
_.push('en_US')
|
||||
translations.append(_(singular))
|
||||
_.pop()
|
||||
|
||||
else:
|
||||
for locale in _.locale_stack:
|
||||
translation = _(singular, plural, n, locale)
|
||||
logging.info(translation)
|
||||
|
||||
if translation not in translations:
|
||||
translations.append(translation)
|
||||
|
||||
return '\n'.join(translations)
|
||||
|
||||
|
||||
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=user.id)
|
||||
|
||||
if us:
|
||||
_.push(us.lang)
|
||||
else:
|
||||
_.push('en_US')
|
||||
|
||||
result = func(bot, update, *pargs, **kwargs)
|
||||
_.pop()
|
||||
return result
|
||||
return wrapped
|
||||
|
||||
|
||||
def game_locales(func):
|
||||
@wraps(func)
|
||||
@db_session
|
||||
def wrapped(bot, update, *pargs, **kwargs):
|
||||
user, chat = _user_chat_from_update(update)
|
||||
player = gm.player_for_user_in_chat(user, chat)
|
||||
locales = list()
|
||||
|
||||
if player:
|
||||
for player in player.game.players:
|
||||
us = UserSetting.get(id=player.user.id)
|
||||
|
||||
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)
|
||||
|
||||
while _.code:
|
||||
_.pop()
|
||||
|
||||
return result
|
||||
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
|
Reference in New Issue
Block a user