-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathl10n.py
148 lines (124 loc) · 5.68 KB
/
l10n.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import os
import json
import discord
from discord.ext import commands
LOCALES = [lang[:-5] for lang in os.listdir("lang") if lang.endswith(".json")]
class MissingTranslation(Exception):
pass
class TranslateHandler:
def __init__(self, bot, supported_locales=LOCALES):
self.bot = bot
self.supported_locales = supported_locales
self._translation_cache = {}
self._lang_cache = {}
def get_string_for(self, lang, key, placeholder=""):
if lang not in self.supported_locales:
return placeholder
if self._translation_cache and lang in self._translation_cache and key in self._translation_cache[lang]:
return self._translation_cache[lang][key]
try:
with open(f"lang/{lang}.json", "r", encoding="utf-8") as f:
dic = json.load(f)
self.cache_with_same_key(lang, key, dic)
value = dic.get(key, None)
if value:
return value
raise MissingTranslation
except (FileNotFoundError, MissingTranslation):
if lang == "ja":
return placeholder
else:
return self.get_string_for("ja", key, placeholder)
def cache_with_same_key(self, lang, key, f):
if lang not in self._translation_cache:
self._translation_cache[lang] = {}
key_name = key.split("-")[0]
keys = [file_key for file_key in f.keys(
) if file_key.startswith(key_name)]
for cache_key in keys:
self._translation_cache[cache_key] = f[cache_key]
def clean_cache(self):
self._translation_cache = {}
self._lang_cache = {}
async def update_language_cache(self, target, to=None):
if to is None:
if isinstance(target, discord.Guild):
to = await self.get_lang_by_guild(target, cache=False)
else:
to = await self.get_lang_by_user(target, cache=False)
return # get function caches
if to not in self.supported_locales:
return
self._lang_cache[target.id] = to
async def get_lang_by_guild(self, guild, cache=True):
if cache and guild.id in self._lang_cache:
return self._lang_cache[guild.id]
guild_db = await self.bot.cursor.fetchone("SELECT lang FROM guilds WHERE id=%s", (guild.id,))
#guild_db = await self.bot.cursor.fetchone()
lang = None
if not guild_db:
lang = guild.preferred_locale
elif not guild_db["lang"]:
lang = guild.preferred_locale
else:
lang = guild_db["lang"]
if lang in self.supported_locales:
self._lang_cache[guild.id] = lang
return lang
if lang in self.supported_locales:
return lang
return None
async def get_lang_by_user(self, user, cache=True):
if cache and user.id in self._lang_cache:
return self._lang_cache[user.id]
user_db = await self.bot.cursor.fetchone(
"SELECT lang FROM users WHERE id = %s", (user.id,))
#user_db = await self.bot.cursor.fetchone()
if user_db and user_db["lang"] and user_db["lang"] in self.supported_locales:
self._lang_cache[user.id] = user_db["lang"]
return user_db["lang"]
return None
async def get_lang(self, user):
lang = await self.get_lang_by_user(user)
if lang:
return lang
if isinstance(user, discord.Member):
lang = await self.get_lang_by_guild(user.guild)
if lang:
return lang
return "ja"
async def get_translation_for(self, user, key, *args, **kwargs):
return self.get_raw_translation(await self.get_lang(user), key, *args, **kwargs)
async def get_guild_translation_for(self, guild, key, *args, **kwargs):
lang = await self.get_lang_by_guild(guild)
if not lang:
lang = "ja"
return self.get_raw_translation(lang, key, *args, **kwargs)
def get_raw_translation(self, lang, key, *args, **kwargs):
word = self.get_string_for(lang, key)
if isinstance(word, list):
return word
return word.format(*args, **kwargs)
async def get_any_translation(self, target, key, *args, **kwargs):
if isinstance(target, discord.abc.User):
return await self.get_translation_for(target, key, *args, **kwargs)
elif isinstance(target, discord.Guild):
return await self.get_guild_translation_for(target, key, *args, **kwargs)
return self.get_raw_translation(target, key, *args, **kwargs)
class LocalizedContext(commands.Context):
async def say(self, key, *args, **kwargs):
return await self.send(await self._(key, *args, **kwargs))
async def _(self, key, *args, **kwargs):
return await self.bot.translate_handler.get_translation_for(self.author, key, *args, **kwargs)
async def l10n(self, user, key, *args, **kwargs):
return await self.bot.translate_handler.get_translation_for(user, key, *args, **kwargs)
async def l10n_guild(self, guild, key, *args, **kwargs):
return await self.bot.translate_handler.get_guild_translation_for(guild, key, *args, **kwargs)
async def l10n_any(self, target, key, *args, **kwargs):
return await self.bot.translate_handler.get_any_translation(target, key, *args, **kwargs)
def l10n_raw(self, lang, key, *args, **kwargs):
return self.bot.translate_handler.get_raw_translation(lang, key, *args, **kwargs)
async def user_lang(self, user=None):
if user is None:
user = self.author
return await self.bot.translate_handler.get_lang_by_user(user)