Source of file TranslateHelper.php

Size: 11,628 Bytes - Last Modified: 2020-10-24T02:46:31+00:00

/home/travis/build/NextDom/nextdom-core/src/Helpers/TranslateHelper.php

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
<?php

/* This file is part of Jeedom.
 *
 * Jeedom is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Jeedom is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Jeedom. If not, see <http://www.gnu.org/licenses/>.
 */

/* This file is part of NextDom Software.
 *
 * NextDom is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * NextDom Software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with NextDom Software. If not, see <http://www.gnu.org/licenses/>.
 */

namespace NextDom\Helpers;

use NextDom\Managers\ConfigManager;
use NextDom\Managers\PluginManager;
use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Translation\Translator;

/**
 * Class TranslateHelper
 * @package NextDom\Helpers
 */
class TranslateHelper
{

    /**
     * @var array Data of translation
     */
    protected static $translation;

    /**
     * @var bool Etat du chargement des traductions
     */
    protected static $translationLoaded = false;

    /**
     * @var string Langage par défaut
     */
    protected static $language = null;

    /**
     * @var Translator Outil de traduction
     */
    protected static $translator = null;

    /**
     * @var array Informations de la configuration
     */
    protected static $config = null;

    /**
     * Traduction direct d'une phrase
     *
     * @param string $sentenceToTranslate Phrase à traduire
     * @param string $filename Nom du fichier appelant
     * @param bool $backslash @TODO: Toujours comprendre à quoi ça sert ?
     *
     * @return string Phrase traduite
     * @throws \Exception
     */
    public static function sentence(string $sentenceToTranslate, string $filename, bool $backslash = false): string
    {
        $result = '';
        // Ancienne méthode
        if (strpos($filename, '/plugins') === 0) {
            $result = self::exec("{{" . $sentenceToTranslate . "}}", $filename, $backslash);
        } // Nouvelle méthode
        else {
            // S'assure que la traduction est chargée
            self::getTranslation('fr_FR');
            $result = self::$translator->trans($sentenceToTranslate);
        }
        return $result;
    }

    /**
     *  Lance la traduction d'un texte
     *
     * @param string $content Contenu à traduire
     * @param string $filename Nom du fichier contenant les informations à traduire (ancienne version)
     * @param bool $backslash @TODO: Comprendre à quoi ça sert
     * @return string Texte traduit
     * @throws \Exception
     */
    public static function exec(string $content, string $filename = '', bool $backslash = false): string
    {
        if ($content == '') {// || $filename == '') {
            return '';
        }

        $oldTranslationMode = false;
        $translate = self::getTranslation('fr_FR');
        // Ancienne version pour les plugins
        $pluginsPos = strpos($filename, 'plugins');
        if ($pluginsPos === 0 || $pluginsPos === 1) {
            $filename = substr($filename, strpos($filename, 'plugins'));
            $oldTranslationMode = true;
        }

        $modify = false;
        $replace = [];
        preg_match_all("/{{(.*?)}}/s", $content, $matches);
        if ($oldTranslationMode) {
            foreach ($matches[1] as $text) {
                if (trim($text) == '') {
                    $replace["{{" . $text . "}}"] = $text;
                }
                if (isset($translate[$filename]) && isset($translate[$filename][$text])) {
                    $replace["{{" . $text . "}}"] = $translate[$filename][$text];
                }
                if (!isset($replace["{{" . $text . "}}"]) && isset($translate['common']) && isset($translate['common'][$text])) {
                    $replace["{{" . $text . "}}"] = $translate['common'][$text];
                }
                if (!isset($replace["{{" . $text . "}}"])) {
                    if (strpos($filename, '#') === false) {
                        $modify = true;
                        if (!isset($translate[$filename])) {
                            $translate[$filename] = [];
                        }
                        $translate[$filename][$text] = $text;
                    }
                }
                if ($backslash && isset($replace["{{" . $text . "}}"])) {
                    $replace["{{" . $text . "}}"] = str_replace("'", "\'", str_replace("\'", "'", $replace["{{" . $text . "}}"]));
                }
                if (!isset($replace["{{" . $text . "}}"]) || is_array($replace["{{" . $text . "}}"])) {
                    $replace["{{" . $text . "}}"] = $text;
                }
            }
        } else {
            foreach ($matches[1] as $text) {
                $replace['{{' . $text . '}}'] = self::$translator->trans($text);
            }
        }
        // @TODO: Refaire la génération de fichiers de traduction
        /*
          if ($language == 'fr_FR' && $modify) {
          static::$translation[self::getLanguage()] = $translate;
          self::saveTranslation($language);
          }
         */
        return str_replace(array_keys($replace), $replace, $content);
    }

    /**
     * Obtenir les traductions pour la langue courante
     *
     * @TODO: Vérifier le chargement pour les plugins
     *
     * @param string $language
     * @return mixed
     * @throws \Exception
     */
    public static function getTranslation($language): array
    {
        // Test si les traductions ont été mises en cache
        if (!self::$translationLoaded) {
            self::$translation = [
                self::getLanguage() => self::loadTranslation(),
            ];
            self::$translationLoaded = true;
        }
        return self::$translation[self::getLanguage()];
    }

    /**
     * Obtenir la langue configurée.
     * fr_FR par défaut
     *
     * @return string Langue
     * @throws \Exception
     */
    public static function getLanguage(): string
    {
        if (self::$language === null || self::$language === '') {
            self::$language = self::getConfig('language', 'fr_FR');
        }
        // @TODO: Pourquoi pas défault getConfig renvoie vide
        if (self::$language === '') {
            self::$language = 'fr_FR';
        }
        return self::$language;
    }

    /**
     * Définir la langue
     *
     * @param string $language Langue
     */
    public static function setLanguage(string $language)
    {
        self::$language = $language;
    }

    /**
     * Obtenir une des informations de la configuration liée à la traduction
     *
     * @param string $informationKey
     * @param string $defaultValue
     * @return mixed|string
     * @throws \Exception
     */
    public static function getConfig(string $informationKey, string $defaultValue = ''): string
    {
        $result = $defaultValue;
        // Lecture et mise en cache de la configuration
        if (self::$config === null) {
            self::$config = ConfigManager::byKeys(['language', 'generateTranslation'], 'core', ['language' => 'fr_FR']);
        }
        // Recherche de l'information
        if (isset(self::$config[$informationKey])) {
            $result = self::$config[$informationKey];
        }
        return $result;
    }

    /**
     * Charge les informations de traduction
     * @TODO: Même celles de tous les plugins. Les plugins sont chargés à l'ancienne
     * @return array Données chargées
     * @throws \Exception
     */
    public static function loadTranslation(): array
    {
        $result = [];
        $language = self::getLanguage();
        $filename = self::getPathTranslationFile($language);
        if (file_exists($filename)) {
            self::$translator = new Translator($language, null, NEXTDOM_DATA . '/cache/i18n');
            self::$translator->addLoader('yaml', new YamlFileLoader());
            self::$translator->addResource('yaml', $filename, $language);
            $pluginsDirList = scandir(NEXTDOM_ROOT . '/plugins');
            foreach ($pluginsDirList as $pluginDir) {
                if ($pluginDir !== '.' && $pluginDir !== '..' && is_dir(NEXTDOM_ROOT . '/plugins/' . $pluginDir)) {
                    $pluginTranslationFile = NEXTDOM_ROOT . '/plugins/' . $pluginDir . '/core/i18n/' . $language . '.json';
                    if (file_exists($pluginTranslationFile)) {
                        $pluginTranslationFileContent = file_get_contents($pluginTranslationFile);
                        if (Utils::isJson($pluginTranslationFileContent)) {
                            $result = array_merge($result, json_decode($pluginTranslationFileContent, true));
                        }
                    }
                }
            }
        }
        return $result;
    }

    /**
     * Obtenir le chemin du fichier de traduction d'une langue
     *
     * @param string $language Langue du fichier
     *
     * @return string Chemin vers le fichier
     */
    public static function getPathTranslationFile(string $language): string
    {
        return NEXTDOM_ROOT . '/translations/' . $language . '.yml';
    }

    /**
     * @param $_name
     * @return string
     */
    public static function getPluginFromName($_name)
    {
        if (strpos($_name, 'plugins/') === false) {
            return 'core';
        }
        preg_match_all('/plugins\/(.*?)\//m', $_name, $matches, PREG_SET_ORDER, 0);
        if (isset($matches[0]) && isset($matches[0][1])) {
            return $matches[0][1];
        }
        if (!isset($matches[1])) {
            return 'core';
        }
        return $matches[1];
    }

    /**
     * @TODO: Génération des fichiers de traduction
     */
    public static function saveTranslation()
    {
        $core = [];
        $plugins = [];
        foreach (self::getTranslation(self::getLanguage()) as $page => $translation) {
            if (strpos($page, 'plugins/') === false) {
                $core[$page] = $translation;
            } else {
                $plugin = substr($page, strpos($page, 'plugins/') + 8);
                $plugin = substr($plugin, 0, strpos($plugin, '/'));
                if (!isset($plugins[$plugin])) {
                    $plugins[$plugin] = [];
                }
                $plugins[$plugin][$page] = $translation;
            }
        }
        file_put_contents(self::getPathTranslationFile(self::getLanguage()), json_encode($core, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
        foreach ($plugins as $plugin_name => $translation) {
            try {
                $plugin = PluginManager::byId($plugin_name);
                $plugin->saveTranslation(self::getLanguage(), $translation);
            } catch (\Throwable $e) {

            }
        }
    }

}