diff --git a/app/classes/shared/translation.py b/app/classes/shared/translation.py index 837a5a1c..1683aedc 100644 --- a/app/classes/shared/translation.py +++ b/app/classes/shared/translation.py @@ -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() \ No newline at end of file + +translation = Translation() diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 475c17a2..166ced27 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -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, diff --git a/app/classes/web/public_handler.py b/app/classes/web/public_handler.py index 6b8cb2de..df3f26af 100644 --- a/app/classes/web/public_handler.py +++ b/app/classes/web/public_handler.py @@ -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" diff --git a/app/classes/web/server_handler.py b/app/classes/web/server_handler.py index f027ae04..0e58ded4 100644 --- a/app/classes/web/server_handler.py +++ b/app/classes/web/server_handler.py @@ -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": diff --git a/app/classes/web/status_handler.py b/app/classes/web/status_handler.py index be0e3d05..0ee493f1 100644 --- a/app/classes/web/status_handler.py +++ b/app/classes/web/status_handler.py @@ -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) diff --git a/app/classes/web/tornado.py b/app/classes/web/tornado.py index edf58172..2cf232aa 100644 --- a/app/classes/web/tornado.py +++ b/app/classes/web/tornado.py @@ -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} diff --git a/app/frontend/templates/notify.html b/app/frontend/templates/notify.html index f33cbdbe..696e6b71 100644 --- a/app/frontend/templates/notify.html +++ b/app/frontend/templates/notify.html @@ -27,7 +27,7 @@ {% for r in data['user_role'] %}

{{ r }}

{% end %} - {% if data['api_key'] %} + {% if data.get('api_key') %}

Logged in as API key "{{ data['api_key']['name'] }}"

{% end %}

Email: {{ data['user_data']['email'] }}

diff --git a/app/frontend/templates/panel/panel_config.html b/app/frontend/templates/panel/panel_config.html index cb3aed0c..115d83eb 100644 --- a/app/frontend/templates/panel/panel_config.html +++ b/app/frontend/templates/panel/panel_config.html @@ -14,6 +14,7 @@
@@ -33,12 +34,14 @@

Users

+
  Add New User
+ @@ -99,6 +102,7 @@
User Enabled
+ diff --git a/app/frontend/templates/public/status.html b/app/frontend/templates/public/status.html index 911085ed..8f1f2363 100644 --- a/app/frontend/templates/public/status.html +++ b/app/frontend/templates/public/status.html @@ -49,6 +49,7 @@ {% else %} {% end %} diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index 17375651..29898b84 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -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": { diff --git a/app/translations/fi_FI.json b/app/translations/fi_FI.json index a0aff5ee..1a9d85ef 100644 --- a/app/translations/fi_FI.json +++ b/app/translations/fi_FI.json @@ -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.
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?

Tämä sisältää palvelimen varmuuskopiot. ", - "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": {
Role Allowed Servers + Crafty can't get infos from this Server