From fa371e25bfc8356f78823a08d4f6ded1b64bfdb1 Mon Sep 17 00:00:00 2001 From: djmaze Date: Mon, 12 Apr 2021 12:57:35 +0200 Subject: [PATCH] Revamp language system for #82 --- dev/Common/Translator.js | 15 +- snappymail/v/0.0.0/app/handle.php | 10 - .../0.0.0/app/libraries/RainLoop/Actions.php | 110 +-- .../libraries/RainLoop/Plugins/Manager.php | 24 +- .../app/libraries/RainLoop/ServiceActions.php | 48 +- .../v/0.0.0/app/libraries/RainLoop/Utils.php | 46 - .../v/0.0.0/app/libraries/snappymail/l10n.php | 47 + snappymail/v/0.0.0/app/libraries/spyc/COPYING | 21 - .../v/0.0.0/app/libraries/spyc/README.md | 30 - .../v/0.0.0/app/libraries/spyc/Spyc.php | 884 ------------------ .../v/0.0.0/app/libraries/spyc/composer.json | 30 - snappymail/v/0.0.0/app/localization/README | 23 +- .../v/0.0.0/app/localization/admin/README | 1 - .../app/localization/admin/_source.en.yml | 225 ----- .../v/0.0.0/app/localization/admin/de_DE.yml | 236 ----- .../v/0.0.0/app/localization/admin/en_US.yml | 233 ----- .../v/0.0.0/app/localization/admin/es_ES.yml | 233 ----- .../v/0.0.0/app/localization/admin/fr_FR.yml | 237 ----- .../v/0.0.0/app/localization/admin/hu_HU.yml | 233 ----- .../v/0.0.0/app/localization/admin/nl_NL.yml | 233 ----- .../v/0.0.0/app/localization/admin/sv_SE.yml | 232 ----- .../v/0.0.0/app/localization/admin/zh_CN.yml | 226 ----- .../v/0.0.0/app/localization/de-DE/admin.json | 217 +++++ .../de.js => de-DE/relativetimeformat.js} | 0 .../0.0.0/app/localization/de-DE/static.json | 9 + .../v/0.0.0/app/localization/de-DE/user.json | 583 ++++++++++++ .../v/0.0.0/app/localization/en/admin.json | 217 +++++ .../en.js => en/relativetimeformat.js} | 0 .../v/0.0.0/app/localization/en/static.json | 9 + .../v/0.0.0/app/localization/en/user.json | 583 ++++++++++++ .../v/0.0.0/app/localization/es-ES/admin.json | 217 +++++ .../es.js => es-ES/relativetimeformat.js} | 0 .../0.0.0/app/localization/es-ES/static.json | 9 + .../v/0.0.0/app/localization/es-ES/user.json | 583 ++++++++++++ .../v/0.0.0/app/localization/fr-FR/admin.json | 217 +++++ .../fr.js => fr-FR/relativetimeformat.js} | 0 .../0.0.0/app/localization/fr-FR/static.json | 9 + .../v/0.0.0/app/localization/fr-FR/user.json | 583 ++++++++++++ .../v/0.0.0/app/localization/hu-HU/admin.json | 217 +++++ .../hu.js => hu-HU/relativetimeformat.js} | 0 .../0.0.0/app/localization/hu-HU/static.json | 9 + .../v/0.0.0/app/localization/hu-HU/user.json | 583 ++++++++++++ .../v/0.0.0/app/localization/langs.json | 88 ++ snappymail/v/0.0.0/app/localization/langs.yml | 91 -- .../v/0.0.0/app/localization/nl-NL/admin.json | 217 +++++ .../nl.js => nl-NL/relativetimeformat.js} | 0 .../0.0.0/app/localization/nl-NL/static.json | 9 + .../v/0.0.0/app/localization/nl-NL/user.json | 583 ++++++++++++ .../localization/relativetimeformat/en-GB.js | 75 -- .../v/0.0.0/app/localization/sv-SE/admin.json | 217 +++++ .../se.js => sv-SE/relativetimeformat.js} | 0 .../0.0.0/app/localization/sv-SE/static.json | 9 + .../v/0.0.0/app/localization/sv-SE/user.json | 583 ++++++++++++ .../v/0.0.0/app/localization/webmail/README | 1 - .../app/localization/webmail/_source.en.yml | 567 ----------- .../0.0.0/app/localization/webmail/de_DE.yml | 587 ------------ .../0.0.0/app/localization/webmail/en_GB.yml | 574 ------------ .../0.0.0/app/localization/webmail/en_US.yml | 574 ------------ .../0.0.0/app/localization/webmail/es_ES.yml | 582 ------------ .../0.0.0/app/localization/webmail/fr_FR.yml | 587 ------------ .../0.0.0/app/localization/webmail/hu_HU.yml | 578 ------------ .../0.0.0/app/localization/webmail/nl_NL.yml | 577 ------------ .../0.0.0/app/localization/webmail/sv_SE.yml | 573 ------------ .../0.0.0/app/localization/webmail/zh_CN.yml | 565 ----------- .../v/0.0.0/app/localization/zh-CN/admin.json | 217 +++++ .../cn.js => zh-CN/relativetimeformat.js} | 0 .../0.0.0/app/localization/zh-CN/static.json | 9 + .../v/0.0.0/app/localization/zh-CN/user.json | 583 ++++++++++++ 68 files changed, 6705 insertions(+), 9163 deletions(-) create mode 100644 snappymail/v/0.0.0/app/libraries/snappymail/l10n.php delete mode 100644 snappymail/v/0.0.0/app/libraries/spyc/COPYING delete mode 100644 snappymail/v/0.0.0/app/libraries/spyc/README.md delete mode 100644 snappymail/v/0.0.0/app/libraries/spyc/Spyc.php delete mode 100644 snappymail/v/0.0.0/app/libraries/spyc/composer.json delete mode 100644 snappymail/v/0.0.0/app/localization/admin/README delete mode 100644 snappymail/v/0.0.0/app/localization/admin/_source.en.yml delete mode 100644 snappymail/v/0.0.0/app/localization/admin/de_DE.yml delete mode 100644 snappymail/v/0.0.0/app/localization/admin/en_US.yml delete mode 100644 snappymail/v/0.0.0/app/localization/admin/es_ES.yml delete mode 100644 snappymail/v/0.0.0/app/localization/admin/fr_FR.yml delete mode 100644 snappymail/v/0.0.0/app/localization/admin/hu_HU.yml delete mode 100644 snappymail/v/0.0.0/app/localization/admin/nl_NL.yml delete mode 100644 snappymail/v/0.0.0/app/localization/admin/sv_SE.yml delete mode 100644 snappymail/v/0.0.0/app/localization/admin/zh_CN.yml create mode 100644 snappymail/v/0.0.0/app/localization/de-DE/admin.json rename snappymail/v/0.0.0/app/localization/{relativetimeformat/de.js => de-DE/relativetimeformat.js} (100%) create mode 100644 snappymail/v/0.0.0/app/localization/de-DE/static.json create mode 100644 snappymail/v/0.0.0/app/localization/de-DE/user.json create mode 100644 snappymail/v/0.0.0/app/localization/en/admin.json rename snappymail/v/0.0.0/app/localization/{relativetimeformat/en.js => en/relativetimeformat.js} (100%) create mode 100644 snappymail/v/0.0.0/app/localization/en/static.json create mode 100644 snappymail/v/0.0.0/app/localization/en/user.json create mode 100644 snappymail/v/0.0.0/app/localization/es-ES/admin.json rename snappymail/v/0.0.0/app/localization/{relativetimeformat/es.js => es-ES/relativetimeformat.js} (100%) create mode 100644 snappymail/v/0.0.0/app/localization/es-ES/static.json create mode 100644 snappymail/v/0.0.0/app/localization/es-ES/user.json create mode 100644 snappymail/v/0.0.0/app/localization/fr-FR/admin.json rename snappymail/v/0.0.0/app/localization/{relativetimeformat/fr.js => fr-FR/relativetimeformat.js} (100%) create mode 100644 snappymail/v/0.0.0/app/localization/fr-FR/static.json create mode 100644 snappymail/v/0.0.0/app/localization/fr-FR/user.json create mode 100644 snappymail/v/0.0.0/app/localization/hu-HU/admin.json rename snappymail/v/0.0.0/app/localization/{relativetimeformat/hu.js => hu-HU/relativetimeformat.js} (100%) create mode 100644 snappymail/v/0.0.0/app/localization/hu-HU/static.json create mode 100644 snappymail/v/0.0.0/app/localization/hu-HU/user.json create mode 100644 snappymail/v/0.0.0/app/localization/langs.json delete mode 100644 snappymail/v/0.0.0/app/localization/langs.yml create mode 100644 snappymail/v/0.0.0/app/localization/nl-NL/admin.json rename snappymail/v/0.0.0/app/localization/{relativetimeformat/nl.js => nl-NL/relativetimeformat.js} (100%) create mode 100644 snappymail/v/0.0.0/app/localization/nl-NL/static.json create mode 100644 snappymail/v/0.0.0/app/localization/nl-NL/user.json delete mode 100644 snappymail/v/0.0.0/app/localization/relativetimeformat/en-GB.js create mode 100644 snappymail/v/0.0.0/app/localization/sv-SE/admin.json rename snappymail/v/0.0.0/app/localization/{relativetimeformat/se.js => sv-SE/relativetimeformat.js} (100%) create mode 100644 snappymail/v/0.0.0/app/localization/sv-SE/static.json create mode 100644 snappymail/v/0.0.0/app/localization/sv-SE/user.json delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/README delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/_source.en.yml delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/de_DE.yml delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/en_GB.yml delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/en_US.yml delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/es_ES.yml delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/fr_FR.yml delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/hu_HU.yml delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/nl_NL.yml delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/sv_SE.yml delete mode 100644 snappymail/v/0.0.0/app/localization/webmail/zh_CN.yml create mode 100644 snappymail/v/0.0.0/app/localization/zh-CN/admin.json rename snappymail/v/0.0.0/app/localization/{relativetimeformat/cn.js => zh-CN/relativetimeformat.js} (100%) create mode 100644 snappymail/v/0.0.0/app/localization/zh-CN/static.json create mode 100644 snappymail/v/0.0.0/app/localization/zh-CN/user.json diff --git a/dev/Common/Translator.js b/dev/Common/Translator.js index 552d16d15..47f674400 100644 --- a/dev/Common/Translator.js +++ b/dev/Common/Translator.js @@ -3,7 +3,7 @@ import { Notification, UploadErrorCode } from 'Common/Enums'; import { langLink } from 'Common/Links'; import { doc, createElement } from 'Common/Globals'; -let I18N_DATA = window.rainloopI18N || {}; +let I18N_DATA = window.snappymailI18N || {}; export const trigger = ko.observable(false); @@ -14,7 +14,8 @@ export const trigger = ko.observable(false); * @returns {string} */ export function i18n(key, valueList, defaulValue) { - let result = I18N_DATA[key] || defaulValue || key; + let path = key.split('/'), + result = I18N_DATA[path[0]][path[1]] || defaulValue || key; if (valueList) { Object.entries(valueList).forEach(([key, value]) => { @@ -75,7 +76,7 @@ function getNotificationMessage(code) { let key = getKeyByValue(Notification, code); if (key) { key = i18nKey(key).replace('_NOTIFICATION', '_ERROR'); - return I18N_DATA['NOTIFICATIONS/' + key]; + return I18N_DATA.NOTIFICATIONS[key]; } } @@ -125,13 +126,13 @@ export function reload(admin, language) { const script = createElement('script'); script.onload = () => { // reload the data - if (window.rainloopI18N) { - I18N_DATA = window.rainloopI18N || {}; + if (window.snappymailI18N) { + I18N_DATA = window.snappymailI18N; i18nToNodes(doc); dispatchEvent(new CustomEvent('reload-time')); trigger(!trigger()); } - window.rainloopI18N = null; + window.snappymailI18N = null; script.remove(); resolve(); }; @@ -150,7 +151,7 @@ export function reload(admin, language) { */ export function convertLangName(language, isEng = false) { return i18n( - 'LANGS_NAMES' + (true === isEng ? '_EN' : '') + '/LANG_' + language.toUpperCase().replace(/[^a-zA-Z0-9]+/g, '_'), + 'LANGS_NAMES' + (true === isEng ? '_EN' : '') + '/' + language, null, language ); diff --git a/snappymail/v/0.0.0/app/handle.php b/snappymail/v/0.0.0/app/handle.php index ccac1b8e1..8c4d2dffe 100644 --- a/snappymail/v/0.0.0/app/handle.php +++ b/snappymail/v/0.0.0/app/handle.php @@ -30,16 +30,6 @@ if (\class_exists('RainLoop\Api')) { \MailSo\Base\Loader::Init(); - if (!\function_exists('yaml_parse')) { - function yaml_parse(string $input) { - require_once RAINLOOP_APP_LIBRARIES_PATH.'spyc/Spyc.php'; - return \Spyc::YAMLLoadString(\str_replace(array(': >-', ': |-', ': |+'), array(': >', ': |', ': |'), $input)); - } - function yaml_parse_file(string $filename) { - return yaml_parse(\file_get_contents($filename)); - } - } - if (!empty($_ENV['RAINLOOP_INCLUDE_AS_API'])) { if (!\defined('APP_API_STARTED')) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index 68fb6e671..66e6fa5a5 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -1009,8 +1009,8 @@ class Actions 'faviconStatus' => (bool)$oConfig->Get('labs', 'favicon_status', true), 'listPermanentFiltered' => '' !== \trim(Api::Config()->Get('labs', 'imap_message_list_permanent_filter', '')), 'themes' => $this->GetThemes(), - 'languages' => $this->GetLanguages(false), - 'languagesAdmin' => $this->GetLanguages(true), + 'languages' => \SnappyMail\L10n::getLanguages(false), + 'languagesAdmin' => \SnappyMail\L10n::getLanguages(true), 'attachmentsActions' => $aAttachmentsActions ), $bAdmin ? array( 'adminHostUse' => '' !== $oConfig->Get('security', 'admin_panel_host', ''), @@ -2223,47 +2223,43 @@ class Actions public function ValidateLanguage(string $sLanguage, string $sDefault = '', bool $bAdmin = false, bool $bAllowEmptyResult = false): string { - $sResult = ''; - $aLang = $this->GetLanguages($bAdmin); + $aLang = \SnappyMail\L10n::getLanguages($bAdmin); - $aHelper = array('en' => 'en_us', 'ar' => 'ar_sa', 'cs' => 'cs_cz', 'no' => 'nb_no', 'ua' => 'uk_ua', - 'cn' => 'zh_cn', 'zh' => 'zh_cn', 'tw' => 'zh_tw', 'fa' => 'fa_ir'); + $aHelper = array( + 'ar' => 'ar-SA', + 'cs' => 'cs-CZ', + 'no' => 'nb-NO', + 'ua' => 'uk-UA', + 'cn' => 'zh-CN', + 'zh' => 'zh-CN', + 'tw' => 'zh-TW', + 'fa' => 'fa-IR' + ); - $sLanguage = isset($aHelper[$sLanguage]) ? $aHelper[$sLanguage] : $sLanguage; - $sDefault = isset($aHelper[$sDefault]) ? $aHelper[$sDefault] : $sDefault; - - $sLanguage = \strtolower(\str_replace('-', '_', $sLanguage)); - if (2 === strlen($sLanguage)) { - $sLanguage = $sLanguage . '_' . $sLanguage; - } - - $sDefault = \strtolower(\str_replace('-', '_', $sDefault)); - if (2 === strlen($sDefault)) { - $sDefault = $sDefault . '_' . $sDefault; - } - - $sLanguage = \preg_replace_callback('/_([a-zA-Z0-9]{2})$/', function ($aData) { - return \strtoupper($aData[0]); - }, $sLanguage); - - $sDefault = \preg_replace_callback('/_([a-zA-Z0-9]{2})$/', function ($aData) { - return \strtoupper($aData[0]); - }, $sDefault); + $sLanguage = isset($aHelper[$sLanguage]) ? $aHelper[$sLanguage] : \strtr($sLanguage, '_', '-'); + $sDefault = isset($aHelper[$sDefault]) ? $aHelper[$sDefault] : \strtr($sDefault, '_', '-'); if (\in_array($sLanguage, $aLang)) { - $sResult = $sLanguage; + return $sLanguage; } - if (empty($sResult) && !empty($sDefault) && \in_array($sDefault, $aLang)) { - $sResult = $sDefault; + $sLangCountry = \preg_replace_callback('/-([a-zA-Z]{2})$/', function ($aData) { + return \strtoupper($aData[0]); + }, $sLanguage); + if (\in_array($sLangCountry, $aLang)) { + return $sLangCountry; } - if (empty($sResult) && !$bAllowEmptyResult) { - $sResult = $this->Config()->Get('webmail', $bAdmin ? 'language_admin' : 'language', 'en_US'); - $sResult = \in_array($sResult, $aLang) ? $sResult : 'en_US'; + if (\in_array($sDefault, $aLang)) { + return $sDefault; } - return $sResult; + if ($bAllowEmptyResult) { + return ''; + } + + $sResult = $this->Config()->Get('webmail', $bAdmin ? 'language_admin' : 'language', 'en'); + return \in_array($sResult, $aLang) ? $sResult : 'en'; } public function ValidateContactPdoType(string $sType): string @@ -2331,44 +2327,6 @@ class Actions return $aCache; } - /** - * @staticvar array $aCache - */ - public function GetLanguages(bool $bAdmin = false): array - { - static $aCache = array(); - $sDir = APP_VERSION_ROOT_PATH . 'app/localization/' . ($bAdmin ? 'admin' : 'webmail') . '/'; - - if (isset($aCache[$sDir])) { - return $aCache[$sDir]; - } - - $aTop = array(); - $aList = array(); - - if (\is_dir($sDir)) { - $rDirH = \opendir($sDir); - if ($rDirH) { - while (($sFile = \readdir($rDirH)) !== false) { - if ('.' !== $sFile[0] && \is_file($sDir . '/' . $sFile) && '.yml' === \substr($sFile, -4)) { - $sLang = \substr($sFile, 0, -4); - if (0 < \strlen($sLang) && 'always' !== $sLang && '_source.en' !== $sLang) { - \array_push($aList, $sLang); - } - } - } - - \closedir($rDirH); - } - } - - \sort($aTop); - \sort($aList); - - $aCache[$sDir] = \array_merge($aTop, $aList); - return $aCache[$sDir]; - } - public function ProcessTemplate(string $sName, string $sHtml): string { $sHtml = \preg_replace('/