Fix translation stuff

* Make fallback stuff work
* Use helper.get_setting('language') instead of hardcoded 'en_US'
* Fix status and public pages lang variables
* Fix and add some translations for fi_FI
This commit is contained in:
luukas 2022-01-15 17:38:08 +02:00
parent b8e9efad76
commit a20f7c4acf
11 changed files with 96 additions and 60 deletions

View File

@ -1,73 +1,76 @@
from app.classes.shared.helpers import helper
from app.classes.shared.console import console
import os
import json
import logging
import os
import typing as t
from app.classes.shared.console import console
from app.classes.shared.helpers import helper
logger = logging.getLogger(__name__)
class Translation():
class Translation:
def __init__(self):
self.translations_path = os.path.join(helper.root_dir, 'app', 'translations')
self.cached_translation = None
self.cached_translation_lang = None
self.lang_file_exists = []
def translate(self, page, word, lang):
translated_word = None
fallback_lang = 'en_EN'
def get_language_file(self, language: str):
return os.path.join(self.translations_path, str(language) + '.json')
if lang not in self.lang_file_exists and \
helper.check_file_exists(os.path.join(self.translations_path, str(lang) + '.json')):
self.lang_file_exists.append(lang)
def translate(self, page, word, language):
fallback_language = 'en_EN'
translated_word = self.translate_inner(page, word, lang) \
if lang in self.lang_file_exists else self.translate_inner(page, word, fallback_lang)
translated_word = self.translate_inner(page, word, language)
if translated_word is None:
translated_word = self.translate_inner(page, word, fallback_language)
if translated_word:
if isinstance(translated_word, dict): return json.dumps(translated_word)
elif iter(translated_word) and not isinstance(translated_word, str): return '\n'.join(translated_word)
return translated_word
if isinstance(translated_word, dict):
# JSON objects
return json.dumps(translated_word)
elif isinstance(translated_word, str):
# Basic strings
return translated_word
elif hasattr(translated_word, '__iter__'):
# Multiline strings
return '\n'.join(translated_word)
return 'Error while getting translation'
def translate_inner(self, page, word, lang):
lang_file = os.path.join(
self.translations_path,
lang + '.json'
)
def translate_inner(self, page, word, language) -> t.Union[t.Any, None]:
language_file = self.get_language_file(language)
try:
if not self.cached_translation:
with open(lang_file, 'r', encoding='utf-8') as f:
with open(language_file, 'r', encoding='utf-8') as f:
data = json.load(f)
self.cached_translation = data
elif self.cached_translation_lang != lang:
with open(lang_file, 'r', encoding='utf-8') as f:
elif self.cached_translation_lang != language:
with open(language_file, 'r', encoding='utf-8') as f:
data = json.load(f)
self.cached_translation = data
self.cached_translation_lang = lang
self.cached_translation_lang = language
else:
data = self.cached_translation
try:
translated_page = data[page]
except KeyError:
logger.error('Translation File Error: page {} does not exist for lang {}'.format(page, lang))
console.error('Translation File Error: page {} does not exist for lang {}'.format(page, lang))
logger.error('Translation File Error: page {} does not exist for lang {}'.format(page, language))
console.error('Translation File Error: page {} does not exist for lang {}'.format(page, language))
return None
try:
translated_word = translated_page[word]
return translated_word
except KeyError:
logger.error('Translation File Error: word {} does not exist on page {} for lang {}'.format(word, page, lang))
console.error('Translation File Error: word {} does not exist on page {} for lang {}'.format(word, page, lang))
logger.error(f'Translation File Error: word {word} does not exist on page {page} for lang {language}')
console.error(f'Translation File Error: word {word} does not exist on page {page} for lang {language}')
return None
except Exception as e:
logger.critical('Translation File Error: Unable to read {} due to {}'.format(lang_file, e))
console.critical('Translation File Error: Unable to read {} due to {}'.format(lang_file, e))
logger.critical(f'Translation File Error: Unable to read {language_file} due to {e}')
console.critical(f'Translation File Error: Unable to read {language_file} due to {e}')
return None
translation = Translation()
translation = Translation()

View File

@ -497,7 +497,7 @@ class PanelHandler(BaseHandler):
user.api_token = "********"
if superuser:
for user in self.controller.users.get_all_users():
if user.superuser == 1:
if user.superuser:
super_auth_servers = ["Super User Access To All Servers"]
page_data['users'] = self.controller.users.get_all_users()
page_data['roles'] = self.controller.roles.get_all_roles()
@ -1252,7 +1252,7 @@ class PanelHandler(BaseHandler):
password1 = bleach.clean(self.get_argument('password1', None))
email = bleach.clean(self.get_argument('email', "default@example.com"))
enabled = int(float(self.get_argument('enabled', '0')))
lang = bleach.clean(self.get_argument('language'), 'en_EN')
lang = bleach.clean(self.get_argument('language'), helper.get_setting('language'))
if superuser:
#Checks if user is trying to change super user status of self. We don't want that. Automatically make them stay super user since we know they are.
@ -1389,7 +1389,7 @@ class PanelHandler(BaseHandler):
password1 = bleach.clean(self.get_argument('password1', None))
email = bleach.clean(self.get_argument('email', "default@example.com"))
enabled = int(float(self.get_argument('enabled', '0'))),
lang = bleach.clean(self.get_argument('lang', 'en_EN'))
lang = bleach.clean(self.get_argument('lang', helper.get_setting('language')))
if superuser:
superuser = bleach.clean(self.get_argument('superuser', '0'))
else:
@ -1507,7 +1507,7 @@ class PanelHandler(BaseHandler):
else:
self.set_status(404)
page_data = {'lang': locale.get("en_EN")}
page_data = {'lang': helper.get_setting('language')}
self.render(
"public/404.html",
translate=self.translator.translate,

View File

@ -46,7 +46,7 @@ class PublicHandler(BaseHandler):
error = bleach.clean(self.get_argument('error', "Invalid Login!"))
error_msg = bleach.clean(self.get_argument('error_msg', ''))
page_data = {'version': helper.get_version_string(), 'error': error, 'lang': tornado.locale.get("en_EN")}
page_data = {'version': helper.get_version_string(), 'error': error, 'lang': helper.get_setting('language')}
# sensible defaults
template = "public/404.html"

View File

@ -71,9 +71,17 @@ class ServerHandler(BaseHandler):
'hosts_data': self.controller.management.get_latest_hosts_stats(),
'menu_servers': defined_servers,
'show_contribute': helper.get_setting("show_contribute_link", True),
'lang': self.controller.users.get_user_lang_by_id(exec_user["user_id"])
'lang': self.controller.users.get_user_lang_by_id(exec_user["user_id"]),
'api_key': {
'name': api_key.name,
'created': api_key.created,
'server_permissions': api_key.server_permissions,
'crafty_permissions': api_key.crafty_permissions,
'superuser': api_key.superuser
} if api_key is not None else None,
'superuser': superuser
}
if superuser == 1:
if superuser:
page_data['roles'] = list_roles
if page == "step1":

View File

@ -25,7 +25,7 @@ except ModuleNotFoundError as e:
class StatusHandler(BaseHandler):
def get(self):
page_data = {}
page_data['lang'] = tornado.locale.get("en_EN")
page_data['lang'] = helper.get_setting('language')
page_data['servers'] = self.controller.servers.get_all_servers_stats()
for srv in page_data['servers']:
server_data = srv.get('server_data', False)

View File

@ -116,6 +116,7 @@ class Webserver:
tornado.template.Loader('.')
# TODO: Remove because we don't and won't use
tornado.locale.set_default_locale('en_EN')
handler_args = {"controller": self.controller, "tasks_manager": self.tasks_manager, "translator": translation}

View File

@ -27,7 +27,7 @@
{% for r in data['user_role'] %}
<p class="font-weight-light text-muted mb-0">{{ r }}</p>
{% end %}
{% if data['api_key'] %}
{% if data.get('api_key') %}
<p class="mt-3">Logged in as API key "{{ data['api_key']['name'] }}"</p>
{% end %}
<p class="font-weight-light text-muted mb-0">Email: {{ data['user_data']['email'] }}</p>

View File

@ -14,6 +14,7 @@
<div class="row page-title-header">
<div class="col-12">
<div class="page-header">
<!-- TODO: Translate the following -->
<h4 class="page-title">Panel Config</h4>
</div>
</div>
@ -33,12 +34,14 @@
<h4 class="card-title"><i class="fas fa-users"></i> Users</h4>
<span class="too_small" title="{{ translate('dashboard', 'cannotSee', data['lang']) }}", data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}", data-placement="top"></span>
<!-- TODO: Translate the following -->
<div><a class="nav-link" href="/panel/add_user"><i class="fas fa-plus-circle"></i> &nbsp; Add New User</a></div>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<!-- TODO: Translate the following -->
<tr class="rounded">
<th>User</th>
<th>Enabled</th>
@ -99,6 +102,7 @@
<div class="table-responsive">
<table class="table table-hover">
<thead>
<!-- TODO: Translate the following -->
<tr class="rounded">
<th>Role</th>
<th>Allowed Servers</th>

View File

@ -49,6 +49,7 @@
</td>
{% else %}
<td colspan="3">
<!-- TODO: translate the following text -->
<span class="text-warning"><i class="fas fa-exclamation-triangle"></i> Crafty can't get infos from this Server </span>
</td>
{% end %}

View File

@ -173,14 +173,13 @@
"loadingBannedPlayers": "Loading Banned Players"
},
"serverSchedules":{
"areYouSure": "Deleted Scheduled Task?",
"areYouSure": "Delete Scheduled Task?",
"confirmDelete": "Do you want to delete this scheduled task? This cannot be undone.",
"cancel": "Cancel",
"confirm": "Confirm",
"cannotSee": "Not seeing everything?",
"cannotSeeOnMobile": "Try clicking on a scheduled task for full details."
},
"serverBackups": {
"backupNow": "Backup Now!",
"backupAtMidnight": "Auto-backup at midnight?",
@ -300,9 +299,8 @@
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"superConfirmTitle": "Enable Super User? Are you sure?",
"superConfirm": "Proceed only if you want this user to have access to EVERYTHING (all user accounts, servers, panel configs, etc). They can even remove your super user access."
"superConfirmTitle": "Enable superuser? Are you sure?",
"superConfirm": "Proceed only if you want this user to have access to EVERYTHING (all user accounts, servers, panel settings, etc.). They can even revoke your superuser rights."
},
"datatables": {
"i18n": {

View File

@ -12,7 +12,7 @@
"embarassing": "No, tämähän on noloa.",
"error": "Virhe!",
"start-error": "Palvelin {} ei käynnistynyt virhekoodilla: {}",
"closedPort": "Olemme havainneet, että portti {} ei ehkä ole auki isäntäverkossa tai palomuuri estää sen. Etäasiakkaan yhteydet palvelimeen voivat olla rajallisia.",
"portReminder": "Olemme havainneet, että tämä on ensimmäinen kerta, kun {} on käynnistetty. Varmista, että välität porttia {} reitittimesi/palomuurisi kautta, jotta se on käytössä internetistä.",
"internet": "Olemme havainneet, että Crafty -koneella ei ole Internet -yhteyttä. Asiakasyhteydet palvelimelle voivat olla rajalliset.",
"eulaTitle": "Hyväksy EULA",
"eulaMsg": "Sinun on hyväksyttävä EULA. Kopio Mojang EULA:sta on linkitetty tämän viestin alla.",
@ -68,8 +68,17 @@
"downloading": "Lataamme palvelinta...",
"addRole": "Lisää Palvelin Olemassa Oleviin Rooleihin",
"autoCreate": "Jos ketään ei valita, Crafty tekee sellaisen!",
"selectRole": "Valitse roolit"
"selectRole": "Valitse roolit",
"selectZipDir": "Valitse arkistosta hakemisto, josta haluat meidän purkavan tiedostot",
"close": "Sulje",
"save": "Tallenna",
"selectRoot": "Valitse arkiston päähakemisto",
"clickRoot": "Napsauta tästä valitaksesi juurihakemiston",
"explainRoot": "Napsauta alla olevaa painiketta valitaksesi palvelimesi juurihakemiston arkistosta"
},
"usersConfig":{
"deleteUser": "Poista käyttäjä: ",
"confirmDelete": "Oletko varma, että haluat poistaa tämän käyttäjän? Tätä ei voi peruuttaa."
},
"dashboard": {
"dashboard": "Kojelauta",
@ -134,7 +143,8 @@
"description": "Kuvaus",
"errorCalculatingUptime": "Virhe laskettaessa käyttöaikaa",
"serverTime": "UTC aikaa",
"unableToConnect": "Yhteyden muodostaminen epäonnistui"
"unableToConnect": "Yhteyden muodostaminen epäonnistui",
"serverTimeZone": "Palvelimen aikavyöhyke"
},
"serverDetails": {
"serverDetails": "Palvelimen tiedot",
@ -162,6 +172,14 @@
"bannedPlayers": "Kielletyt pelaajat",
"loadingBannedPlayers": "Ladataan kiellettyjen pelaajien listaa"
},
"serverSchedules":{
"areYouSure": "Poista ajoitettu tehtävä?",
"confirmDelete": "Haluatko poistaa tämän ajoitetun tehtävän? Tätä ei voi peruuttaa.",
"cancel": "Peruuta",
"confirm": "Vahvista",
"cannotSee": "Etkö näe kaikkea?",
"cannotSeeOnMobile": "Napsauta ajoitettua tehtävää saadaksesi täydet tiedot."
},
"serverBackups": {
"backupNow": "Varmuuskopioi nyt!",
"backupAtMidnight": "Automaattisesti varmuuskopioi keskiyöllä?",
@ -206,14 +224,15 @@
"unsupportedLanguage": "Varoitus: Tätä tiedostotyyppiä ei tueta",
"keybindings": "Pikanäppäimet",
"fileReadError": "Tiedoston lukuvirhe",
"upload": "Lataa",
"upload": "Lähetä",
"unzip": "Pura",
"clickUpload": "Valitse tiedostosi napsauttamalla tätä",
"uploadTitle": "Lähetä tiedostot: ",
"waitUpload": "Odota, kunnes lataamme tiedostosi ... Tämä voi kestää hetken.",
"stayHere": "ÄLÄ JÄTÄ SIVUTA!",
"close": "Kiinni",
"download": "Ladata"
"waitUpload": "Odota, kun lähetämme tiedostojasi... Tämä voi kestää hetken.",
"stayHere": "ÄLÄ POISTU SIVULTA!",
"close": "Sulje",
"download": "Lataa",
"loadingRecords": "Ladataan tiedostoja..."
},
"serverConfig": {
"serverName": "Palvelimen nimi",
@ -248,12 +267,12 @@
"bePatientUpdate": "Ole kärsivällinen, kun päivitämme palvelinta. Latausajat voivat vaihdella Internet-nopeutesi mukaan.<br /> Tämä näyttö päivittyy hetkessä",
"sendingRequest": "Pyyntöäsi lähetetään...",
"deleteServerQuestion": "Poistetaanko palvelin?",
"deleteServerQuestionMessage": "Haluatko varmasti poistaa tämän palvelimen? Tämän jälkeen ei ole paluuta...",
"deleteServerQuestionMessage": "Haluatko varmasti poistaa tämän palvelimen? Tätä ei voi peruuttaa...",
"yesDelete": "Kyllä, poista",
"noDelete": "Ei, mene takaisin",
"deleteFilesQuestion": "Poistetaanko palvelintiedostot koneelta?",
"deleteFilesQuestionMessage": "Haluatko Craftyn poistavan kaikki palvelintiedostot isäntäkoneelta? <br><br><strong> Tämä sisältää palvelimen varmuuskopiot. <strong>",
"yesDeleteFiles": "Kyllä, poista tiedostoja",
"yesDeleteFiles": "Kyllä, poista tiedostot",
"noDeleteFiles": "Ei, poista vain paneelista",
"sendingDelete": "Poistetaan palvelinta",
"bePatientDelete": "Ole kärsivällinen, kun poistamme palvelimesi Crafty-paneelista. Tämä näyttö sulkeutuu hetken kuluttua.",
@ -279,7 +298,9 @@
"panelConfig": {
"save": "Tallenna",
"cancel": "Peruuta",
"delete": "Poista"
"delete": "Poista",
"superConfirmTitle": "Otetaanko järjestelmänvalvojan oikeudet käyttöön? Oletko varma?",
"superConfirm": "Jatka vain, jos haluat, että tällä käyttäjällä on pääsy KAIKKEEN (kaikki käyttäjätilit, palvelimet, paneelin asetukset jne.). Hän voi jopa poistaa sinun järjestelmänvalvojan oikeutesi."
},
"datatables": {
"i18n": {