Локализация таблицы (ru/en): колонка О→Оч/Pts, детект языка клиента Telegram
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 5s

This commit is contained in:
vrubel 2026-06-19 16:30:55 +00:00
parent 22a0e27763
commit cfd410d5fe

View file

@ -32,6 +32,35 @@ START_MSG = (
'Работает для швейцарских турниров\. Движок: FIDE Dutch System \(bbpPairings\)\.' 'Работает для швейцарских турниров\. Движок: FIDE Dutch System \(bbpPairings\)\.'
) )
LOCALE = {
'ru': {
'player': 'Игрок',
'rating': 'Рейт',
'points': 'Оч',
'tb1': 'Доп1',
'title': '📋 *Тур {rnd}* — пары',
'bye': '— BYE —',
'footer_bbp': '\n_FIDE 2025 \(bbpPairings\)_',
'footer_fallback': '\n_Упрощённый Swiss \(bbpPairings недоступен\)_',
},
'en': {
'player': 'Player',
'rating': 'Rat',
'points': 'Pts',
'tb1': 'TB1',
'title': '📋 *Round {rnd}* — pairings',
'bye': '— BYE —',
'footer_bbp': '\n_FIDE 2025 \(bbpPairings\)_',
'footer_fallback': '\n_Simplified Swiss \(bbpPairings unavailable\)_',
},
}
def _get_locale(lang_code: str) -> dict:
if lang_code and lang_code.startswith('ru'):
return LOCALE['ru']
return LOCALE['en']
def _md_escape(text: str) -> str: def _md_escape(text: str) -> str:
escape_chars = r'_*[]()~`>#+-=|{}.!' escape_chars = r'_*[]()~`>#+-=|{}.!'
@ -74,32 +103,34 @@ def _pad_col(s: str, width: int) -> str:
return s + ' ' * (width - cur) return s + ' ' * (width - cur)
def format_pairings(pairings_data: dict, tournament_name: str) -> str: def format_pairings(pairings_data: dict, tournament_name: str, lang: str = '') -> str:
locale = _get_locale(lang)
pairings = pairings_data['pairings'] pairings = pairings_data['pairings']
rnd = pairings_data['round'] rnd = pairings_data['round']
w_board, w_name, w_rating, w_pts, w_tb1 = 2, 17, 4, 4, 5 w_board, w_name, w_rating, w_pts, w_tb1 = 2, 17, 4, 4, 5
border = '+'.join('-' * w for w in [w_board, w_name, w_rating, w_pts, w_tb1]) border = '+'.join('-' * w for w in [w_board, w_name, w_rating, w_pts, w_tb1])
header = (f'{_pad_col("#", w_board)}|{_pad_col("Игрок", w_name)}|' header = (f'{_pad_col("#", w_board)}|{_pad_col(locale["player"], w_name)}|'
f'{_pad_col("Рейт", w_rating)}|{_pad_col("О", w_pts)}|' f'{_pad_col(locale["rating"], w_rating)}|{_pad_col(locale["points"], w_pts)}|'
f'{_pad_col("Доп1", w_tb1)}') f'{_pad_col(locale["tb1"], w_tb1)}')
table_header = f'```\n{header}\n{border}\n' table_header = f'```\n{header}\n{border}\n'
source = pairings_data.get('source', 'algorithm') source = pairings_data.get('source', 'algorithm')
footer = '\n_FIDE 2025 \(bbpPairings\)_' if source == 'bbp_pairings_fide_2025' else \ footer = locale['footer_bbp'] if source == 'bbp_pairings_fide_2025' else \
'\n_Упрощённый Swiss \(bbpPairings недоступен\)_' if source == 'swiss_algorithm_simplified' else '' locale['footer_fallback'] if source == 'swiss_algorithm_simplified' else ''
return { return {
'title': f'📋 *Тур {rnd}* — пары', 'title': locale['title'].format(rnd=rnd),
'rows': _build_table_rows(pairings, w_board, w_name, w_rating, w_pts, w_tb1, border), 'rows': _build_table_rows(pairings, w_board, w_name, w_rating, w_pts, w_tb1, border,
locale['bye']),
'table_header': table_header, 'table_header': table_header,
'footer': footer, 'footer': footer,
} }
def _build_table_rows(pairings: list, w_board: int, w_name: int, w_rating: int, def _build_table_rows(pairings: list, w_board: int, w_name: int, w_rating: int,
w_pts: int, w_tb1: int, border: str) -> list: w_pts: int, w_tb1: int, border: str, bye_label: str = '— BYE —') -> list:
def _rating_str(p): def _rating_str(p):
return str(p.rating) if p.rating else '' return str(p.rating) if p.rating else ''
@ -123,7 +154,7 @@ def _build_table_rows(pairings: list, w_board: int, w_name: int, w_rating: int,
) )
rows.append( rows.append(
f'{_pad_col("", w_board)}|' f'{_pad_col("", w_board)}|'
f'{_pad_col("— BYE —", w_name)}|' f'{_pad_col(bye_label, w_name)}|'
f'{_pad_col("", w_rating)}|' f'{_pad_col("", w_rating)}|'
f'{_pad_col("", w_pts)}|' f'{_pad_col("", w_pts)}|'
f'{_pad_col("", w_tb1)}' f'{_pad_col("", w_tb1)}'
@ -365,7 +396,8 @@ async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE):
record_request(user.id, url, tournament.get('name', ''), False, str(e)) record_request(user.id, url, tournament.get('name', ''), False, str(e))
return return
fmt = format_pairings(result, tournament['name']) lang_code = user.language_code or ''
fmt = format_pairings(result, tournament['name'], lang_code)
chunks = _render_chunks(fmt) chunks = _render_chunks(fmt)
try: try: