feat(i18n): finish persisting data for i18n
This commit is contained in:
parent
5482429cba
commit
1f88499d44
9 changed files with 120 additions and 79 deletions
|
@ -5,7 +5,7 @@ from discord.ext import commands
|
||||||
|
|
||||||
from tuxbot.core import checks
|
from tuxbot.core import checks
|
||||||
from tuxbot.core.bot import Tux
|
from tuxbot.core.bot import Tux
|
||||||
from tuxbot.core.i18n import Translator, set_locale, _locale_key_value
|
from tuxbot.core.i18n import Translator, find_locale, get_locale_name, available_locales
|
||||||
from tuxbot.core.utils.functions.extra import group_extra, ContextPlus
|
from tuxbot.core.utils.functions.extra import group_extra, ContextPlus
|
||||||
|
|
||||||
log = logging.getLogger("tuxbot.cogs.admin")
|
log = logging.getLogger("tuxbot.cogs.admin")
|
||||||
|
@ -16,11 +16,10 @@ class Admin(commands.Cog, name="Admin"):
|
||||||
def __init__(self, bot: Tux):
|
def __init__(self, bot: Tux):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
@group_extra(
|
async def _save_lang(self, ctx: ContextPlus, lang: str):
|
||||||
name="lang",
|
await self.bot.config.update("core", f"guild.{ctx.guild.id}.locale", lang)
|
||||||
aliases=["locale", "langue"],
|
|
||||||
deletable=True
|
@group_extra(name="lang", aliases=["locale", "langue"], deletable=True)
|
||||||
)
|
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@checks.is_admin()
|
@checks.is_admin()
|
||||||
async def _lang(self, ctx: ContextPlus):
|
async def _lang(self, ctx: ContextPlus):
|
||||||
|
@ -29,20 +28,21 @@ class Admin(commands.Cog, name="Admin"):
|
||||||
@_lang.command(name="set", aliases=["define", "choice"])
|
@_lang.command(name="set", aliases=["define", "choice"])
|
||||||
async def _lang_set(self, ctx: ContextPlus, lang: str):
|
async def _lang_set(self, ctx: ContextPlus, lang: str):
|
||||||
try:
|
try:
|
||||||
set_locale(lang.lower())
|
await self._save_lang(ctx, find_locale(lang.lower()))
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
_("Locale changed to {lang} successfully")
|
_("Locale changed to {lang} successfully", ctx, self.bot.config).format(
|
||||||
.format(lang=f"`{lang}`")
|
lang=f"`{get_locale_name(lang).lower()}`"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
await ctx.send(_("This locale isn't available, execute `lang list` to view available locales"))
|
await self._lang_list(ctx)
|
||||||
|
|
||||||
@_lang.command(name="list", aliases=["liste", "all", "view"])
|
@_lang.command(name="list", aliases=["liste", "all", "view"])
|
||||||
async def _lang_list(self, ctx: ContextPlus):
|
async def _lang_list(self, ctx: ContextPlus):
|
||||||
e = discord.Embed(
|
e = discord.Embed(
|
||||||
title=_("List of available locales: "),
|
title=_("List of available locales: ", ctx, self.bot.config),
|
||||||
description='\n'.join([i[0] for i in _locale_key_value.values()]),
|
description="\n".join([i[0] for i in available_locales.values()]),
|
||||||
color=0x36393E
|
color=0x36393E,
|
||||||
)
|
)
|
||||||
|
|
||||||
await ctx.send(embed=e)
|
await ctx.send(embed=e)
|
||||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Tuxbot-bot\n"
|
"Project-Id-Version: Tuxbot-bot\n"
|
||||||
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
||||||
"POT-Creation-Date: 2020-06-11 00:59+0200\n"
|
"POT-Creation-Date: 2020-06-11 19:07+0200\n"
|
||||||
"PO-Revision-Date: 2020-06-10 00:38+0200\n"
|
"PO-Revision-Date: 2020-06-10 00:38+0200\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Automatically generated\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
|
@ -18,15 +18,10 @@ msgstr ""
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: tuxbot/cogs/admin/admin.py:33
|
#: tuxbot/cogs/admin/admin.py:33
|
||||||
#, fuzzy, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Locale changed to {lang} successfully"
|
msgid "Locale changed to {lang} successfully"
|
||||||
msgstr "Lang changed to {lang} successfully"
|
|
||||||
|
|
||||||
#: tuxbot/cogs/admin/admin.py:37
|
|
||||||
msgid ""
|
|
||||||
"This locale isn't available, execute `lang list` to view available locales"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tuxbot/cogs/admin/admin.py:42
|
#: tuxbot/cogs/admin/admin.py:43
|
||||||
msgid "List of available locales: "
|
msgid "List of available locales: "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Tuxbot-bot\n"
|
"Project-Id-Version: Tuxbot-bot\n"
|
||||||
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
||||||
"POT-Creation-Date: 2020-06-11 00:49+0200\n"
|
"POT-Creation-Date: 2020-06-11 18:24+0200\n"
|
||||||
"PO-Revision-Date: 2020-06-10 00:38+0200\n"
|
"PO-Revision-Date: 2020-06-10 00:38+0200\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Automatically generated\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
|
@ -17,12 +17,11 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: tuxbot/cogs/admin/admin.py:33
|
#: tuxbot/cogs/admin/admin.py:38
|
||||||
#, fuzzy, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Locale changed to {lang} successfully"
|
msgid "Locale changed to {lang} successfully"
|
||||||
msgstr "Lang changed to {lang} successfully"
|
msgstr ""
|
||||||
|
|
||||||
#: tuxbot/cogs/admin/admin.py:37
|
#: tuxbot/cogs/admin/admin.py:47
|
||||||
msgid ""
|
msgid "List of available locales: "
|
||||||
"This locale isn't available, execute `lang list` to view available locales"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Tuxbot-bot\n"
|
"Project-Id-Version: Tuxbot-bot\n"
|
||||||
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
||||||
"POT-Creation-Date: 2020-06-11 00:59+0200\n"
|
"POT-Creation-Date: 2020-06-11 19:07+0200\n"
|
||||||
"PO-Revision-Date: 2020-06-10 00:38+0200\n"
|
"PO-Revision-Date: 2020-06-10 00:38+0200\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Automatically generated\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
|
@ -23,13 +23,6 @@ msgstr ""
|
||||||
msgid "Locale changed to {lang} successfully"
|
msgid "Locale changed to {lang} successfully"
|
||||||
msgstr "Langue changée pour {lang} avec succès"
|
msgstr "Langue changée pour {lang} avec succès"
|
||||||
|
|
||||||
#: tuxbot/cogs/admin/admin.py:37
|
#: tuxbot/cogs/admin/admin.py:43
|
||||||
msgid ""
|
|
||||||
"This locale isn't available, execute `lang list` to view available locales"
|
|
||||||
msgstr ""
|
|
||||||
"Cette langue n'est pas disponible, exécutez `lang list` pour voir les "
|
|
||||||
"langues disponibles"
|
|
||||||
|
|
||||||
#: tuxbot/cogs/admin/admin.py:42
|
|
||||||
msgid "List of available locales: "
|
msgid "List of available locales: "
|
||||||
msgstr "Liste des langues disponibles : "
|
msgstr "Liste des langues disponibles : "
|
||||||
|
|
28
tuxbot/cogs/admin/locales/fr-FR.po~
Normal file
28
tuxbot/cogs/admin/locales/fr-FR.po~
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# French translations for Tuxbot-bot package
|
||||||
|
# Traductions françaises du paquet Tuxbot-bot.
|
||||||
|
# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the Tuxbot-bot package.
|
||||||
|
# Automatically generated, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Tuxbot-bot\n"
|
||||||
|
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
||||||
|
"POT-Creation-Date: 2020-06-11 18:24+0200\n"
|
||||||
|
"PO-Revision-Date: 2020-06-10 00:38+0200\n"
|
||||||
|
"Last-Translator: Automatically generated\n"
|
||||||
|
"Language-Team: none\n"
|
||||||
|
"Language: fr\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
|
#: tuxbot/cogs/admin/admin.py:38
|
||||||
|
#, fuzzy, python-brace-format
|
||||||
|
msgid "Locale changed to {lang} successfully"
|
||||||
|
msgstr "Langue changée pour {lang} avec succès"
|
||||||
|
|
||||||
|
#: tuxbot/cogs/admin/admin.py:47
|
||||||
|
msgid "List of available locales: "
|
||||||
|
msgstr "Liste des langues disponibles : "
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Tuxbot-bot\n"
|
"Project-Id-Version: Tuxbot-bot\n"
|
||||||
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
||||||
"POT-Creation-Date: 2020-06-11 00:59+0200\n"
|
"POT-Creation-Date: 2020-06-11 19:07+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -22,10 +22,6 @@ msgstr ""
|
||||||
msgid "Locale changed to {lang} successfully"
|
msgid "Locale changed to {lang} successfully"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tuxbot/cogs/admin/admin.py:37
|
#: tuxbot/cogs/admin/admin.py:43
|
||||||
msgid "This locale isn't available, execute `lang list` to view available locales"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tuxbot/cogs/admin/admin.py:42
|
|
||||||
msgid "List of available locales: "
|
msgid "List of available locales: "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -2,6 +2,7 @@ import asyncio
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from typing import List, Dict, Union, Any
|
from typing import List, Dict, Union, Any
|
||||||
|
from flatten_dict import flatten, unflatten
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
|
@ -124,7 +125,9 @@ class Config:
|
||||||
datas = self.__getitem__(cog_name)
|
datas = self.__getitem__(cog_name)
|
||||||
path = data_path(self._cog_instance)
|
path = data_path(self._cog_instance)
|
||||||
|
|
||||||
datas[item] = value
|
flat_datas = flatten(datas)
|
||||||
|
flat_datas[tuple(item.split("."))] = value
|
||||||
|
datas = unflatten(flat_datas)
|
||||||
|
|
||||||
self._datas = datas
|
self._datas = datas
|
||||||
|
|
||||||
|
@ -139,3 +142,30 @@ class Config:
|
||||||
await self.loop.run_in_executor(None, self._dump)
|
await self.loop.run_in_executor(None, self._dump)
|
||||||
|
|
||||||
return datas
|
return datas
|
||||||
|
|
||||||
|
def get_value(self, cog_name: str, key: str, default: Any = None) -> Any:
|
||||||
|
"""Get value by key.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
cog_name:str
|
||||||
|
Name of cog who's corresponding to the config file.
|
||||||
|
key:str
|
||||||
|
Key to fetch.
|
||||||
|
default:Any|Optional
|
||||||
|
Default value.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Any:
|
||||||
|
Recovered value.
|
||||||
|
|
||||||
|
"""
|
||||||
|
datas = self.__getitem__(cog_name)
|
||||||
|
|
||||||
|
flat_datas = flatten(datas)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return flat_datas[tuple(key.split("."))]
|
||||||
|
except KeyError:
|
||||||
|
return default
|
||||||
|
|
|
@ -83,4 +83,4 @@ def logs_data_path(instance_name: str) -> Path:
|
||||||
Path
|
Path
|
||||||
Generated path for logs files.
|
Generated path for logs files.
|
||||||
"""
|
"""
|
||||||
return data_path(instance_name) / "data" / instance_name / "logs"
|
return data_path(instance_name) / "logs"
|
||||||
|
|
|
@ -5,42 +5,34 @@ from typing import Callable, Union, Dict, List
|
||||||
|
|
||||||
from babel.messages.pofile import read_po
|
from babel.messages.pofile import read_po
|
||||||
|
|
||||||
|
from tuxbot.core import Config
|
||||||
|
from tuxbot.core.utils.functions.extra import ContextPlus
|
||||||
|
|
||||||
log = logging.getLogger("tuxbot.core.i18n")
|
log = logging.getLogger("tuxbot.core.i18n")
|
||||||
|
|
||||||
_translators = []
|
_translators = []
|
||||||
|
|
||||||
_current_locale = "en-US"
|
available_locales: Dict[str, List[str]] = {
|
||||||
_locale_key_value: Dict[str, List[str]] = {
|
"en-US": ["english", "anglais", "en", "us", "en-us"],
|
||||||
"en": ["english", "anglais", "en", "us"],
|
"fr-FR": ["français", "francais", "french", "fr", "be", "fr-fr"],
|
||||||
"fr": ["français", "francais", "french", "fr", "be"],
|
|
||||||
}
|
}
|
||||||
_available_locales: Dict[str, str] = {"en": "en-US", "fr": "fr-FR"}
|
|
||||||
|
|
||||||
|
|
||||||
def get_locale() -> str:
|
|
||||||
return _current_locale
|
|
||||||
|
|
||||||
|
|
||||||
def find_locale(locale: str) -> str:
|
def find_locale(locale: str) -> str:
|
||||||
"""We suppose `locale` is in `_locale_key_value.values()`"""
|
"""We suppose `locale` is in `_available_locales.values()`"""
|
||||||
|
|
||||||
for key, val in _locale_key_value.items():
|
for key, val in available_locales.items():
|
||||||
if locale in val:
|
if locale in val:
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
|
||||||
def set_locale(locale: str) -> None:
|
|
||||||
if not any(locale in values for values in _locale_key_value.values()):
|
|
||||||
raise NotImplementedError("This locale isn't implemented")
|
raise NotImplementedError("This locale isn't implemented")
|
||||||
else:
|
|
||||||
global _current_locale
|
|
||||||
_current_locale = _available_locales.get(find_locale(locale))
|
|
||||||
reload_locales()
|
|
||||||
|
|
||||||
|
|
||||||
def reload_locales() -> None:
|
def get_locale_name(locale: str) -> str:
|
||||||
for translator in _translators:
|
"""Return the name of this `locale`
|
||||||
translator.load_translations()
|
|
||||||
|
"""
|
||||||
|
return available_locales.get(find_locale(locale))[0]
|
||||||
|
|
||||||
|
|
||||||
class Translator(Callable[[str], str]):
|
class Translator(Callable[[str], str]):
|
||||||
|
@ -65,9 +57,14 @@ class Translator(Callable[[str], str]):
|
||||||
|
|
||||||
self.load_translations()
|
self.load_translations()
|
||||||
|
|
||||||
def __call__(self, untranslated: str) -> str:
|
def __call__(self, untranslated: str, ctx: ContextPlus, config: Config) -> str:
|
||||||
try:
|
try:
|
||||||
return self.translations[untranslated]
|
locale = config.get_value(
|
||||||
|
"core",
|
||||||
|
f"guild.{ctx.guild.id}.locale",
|
||||||
|
config.get_value("core", "locale"),
|
||||||
|
)
|
||||||
|
return self.translations[locale][untranslated]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return untranslated
|
return untranslated
|
||||||
|
|
||||||
|
@ -81,16 +78,19 @@ class Translator(Callable[[str], str]):
|
||||||
"""Loads the current translations.
|
"""Loads the current translations.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.translations = {}
|
for locale in available_locales.keys():
|
||||||
locale_path = self.cog_folder / "locales" / f"{get_locale()}.po"
|
locale_path = self.cog_folder / "locales" / f"{locale}.po"
|
||||||
|
|
||||||
with locale_path.open("r") as f:
|
with locale_path.open("r") as f:
|
||||||
catalog = read_po(f)
|
catalog = read_po(f)
|
||||||
|
|
||||||
for message in catalog:
|
for message in catalog:
|
||||||
if message.id:
|
if message.id:
|
||||||
self._add_translation(message.id, message.string)
|
self._add_translation(locale, message.id, message.string)
|
||||||
|
|
||||||
def _add_translation(self, untranslated, translated):
|
def _add_translation(self, locale: str, untranslated: str, translated: str):
|
||||||
if translated:
|
if translated:
|
||||||
self.translations[untranslated] = translated
|
if not self.translations.get(locale, False):
|
||||||
|
self.translations[locale] = {}
|
||||||
|
|
||||||
|
self.translations[locale][untranslated] = translated
|
||||||
|
|
Loading…
Reference in a new issue