Compare commits

...

3 Commits

Author SHA1 Message Date
fe476152d2
code review 2023-11-04 22:03:58 +01:00
d63eaeb95a
maybe better permissions check 2023-10-21 22:45:58 +02:00
12481455ca
upgrade to dotclear 2.28 2023-10-21 11:45:02 +02:00
19 changed files with 785 additions and 580 deletions

View File

@ -1,3 +1,16 @@
translater 2023.11.04
===========================================================
* Require Dotclear 2.28
* Require PHP 8.1
* Cosmetic code review
translater 2023.10.21
===========================================================
* Require Dotclear 2.28
* Require PHP 8.1
* Upgrade to Dotclear 2.28
* Code review (phpstan)
translater 2023.08.15 translater 2023.08.15
=========================================================== ===========================================================
* Require Dotclear 2.27 * Require Dotclear 2.27

View File

@ -1,25 +1,22 @@
# README # README
[![Release](https://img.shields.io/badge/release-2023.08.15-a2cbe9.svg)](https://git.dotclear.watch/JcDenis/translater/releases) [![Release](https://img.shields.io/badge/release-2023.11.04-a2cbe9.svg)](https://git.dotclear.watch/JcDenis/translater/releases)
[![Date](https://img.shields.io/badge/date-2023.08.15-c44d58.svg)](https://git.dotclear.watch/JcDenis/translater/releases) ![Date](https://img.shields.io/badge/date-2023.11.04-c44d58.svg)
[![Dotclear](https://img.shields.io/badge/dotclear-v2.27-137bbb.svg)](https://fr.dotclear.org/download) [![Dotclear](https://img.shields.io/badge/dotclear-v2.28-137bbb.svg)](https://fr.dotclear.org/download)
[![Dotaddict](https://img.shields.io/badge/dotaddict-official-9ac123.svg)](https://plugins.dotaddict.org/dc2/details/translater) [![Dotaddict](https://img.shields.io/badge/dotaddict-official-9ac123.svg)](https://plugins.dotaddict.org/dc2/details/translater)
[![License](https://img.shields.io/github/license/JcDenis/translater)](https://git.dotclear.watch/JcDenis/translater/blob/master/LICENSE) [![License](https://img.shields.io/badge/license-GPL--2.0-ececec.svg)](https://git.dotclear.watch/JcDenis/translater/src/branch/master/LICENSE)
## WHAT IS TRANSLATER ? ## ABOUT
_translater_ is a plugins for the open-source _translater_ is a plugin for the open-source web publishing software called [Dotclear](https://www.dotclear.org).
web publishing software called Dotclear.
It helps dev to translate plugin and theme. > Help dev to translate plugin and theme.
## REQUIREMENTS ## REQUIREMENTS
_translater_ requires: * Dotclear 2.28
* super admin permissions
* Dotclear 2.27
* PHP 8.1+ * PHP 8.1+
* Dotclear super admin permissions
## USAGE ## USAGE
@ -35,10 +32,11 @@ or direct from plugins / themes list with a ''Translate'' button.
## LINKS ## LINKS
* License : [GNU GPL v2](https://www.gnu.org/licenses/old-licenses/lgpl-2.0.html) * [License](https://git.dotclear.watch/JcDenis/translater/src/branch/master/LICENSE)
* Source & contribution : [Gitea Page](https://git.dotclear.watch/JcDenis/translater) or [GitHub Page](https://github.com/JcDenis/translater) * [Packages & details](https://git.dotclear.watch/JcDenis/translater/releases) (or on [Dotaddict](https://plugins.dotaddict.org/dc2/details/translater))
* Packages & details: [Gitea Page](https://git.dotclear.watch/JcDenis/translater/releases) or [Dotaddict Page](https://plugins.dotaddict.org/dc2/details/translater) * [Sources & contributions](https://git.dotclear.watch/JcDenis/translater) (or on [GitHub](https://github.com/JcDenis/translater))
* Discussion & Help: [Dotclear Forum](https://forum.dotclear.org/viewtopic.php?id=39220) * [Issues & security](https://git.dotclear.watch/JcDenis/translater/issues) (or on [GitHub](https://github.com/JcDenis/translater/issues))
* [Discussion & Help](https://forum.dotclear.org/viewtopic.php?id=39220)
## CONTRIBUTORS ## CONTRIBUTORS

View File

@ -1,30 +1,26 @@
<?php <?php
/** /**
* @brief translater, a plugin for Dotclear 2 * @file
* @brief The plugin translater definition
* @ingroup translater
* *
* @package Dotclear * @defgroup translater Plugin translater.
* @subpackage Plugin
* *
* @author Jean-Christian Denis & contributors * Translate your Dotclear plugins and themes.
* *
* @copyright Jean-Christian Denis * @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_RC_PATH')) { declare(strict_types=1);
return;
}
$this->registerModule( $this->registerModule(
'Translater', 'Translater',
'Translate your Dotclear plugins and themes', 'Translate your Dotclear plugins and themes',
'Jean-Christian Denis & contributors', 'Jean-Christian Denis & contributors',
'2023.08.15', '2023.11.04',
[ [
'requires' => [ 'requires' => [['core', '2.28']],
['php', '8.1'], 'permissions' => 'My',
['core', '2.27'],
],
'permissions' => null,
'type' => 'plugin', 'type' => 'plugin',
'support' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/issues', 'support' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/issues',
'details' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/src/branch/master/README.md', 'details' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/src/branch/master/README.md',

View File

@ -2,11 +2,11 @@
<modules xmlns:da="http://dotaddict.org/da/"> <modules xmlns:da="http://dotaddict.org/da/">
<module id="translater"> <module id="translater">
<name>Translater</name> <name>Translater</name>
<version>2023.08.15</version> <version>2023.11.04</version>
<author>Jean-Christian Denis &amp; contributors</author> <author>Jean-Christian Denis &amp; contributors</author>
<desc>Translate your Dotclear plugins and themes</desc> <desc>Translate your Dotclear plugins and themes</desc>
<file>https://git.dotclear.watch/JcDenis/translater/releases/download/v2023.08.15/plugin-translater.zip</file> <file>https://git.dotclear.watch/JcDenis/translater/releases/download/v2023.11.04/plugin-translater.zip</file>
<da:dcmin>2.27</da:dcmin> <da:dcmin>2.28</da:dcmin>
<da:details>https://git.dotclear.watch/JcDenis/translater/src/branch/master/README.md</da:details> <da:details>https://git.dotclear.watch/JcDenis/translater/src/branch/master/README.md</da:details>
<da:support>https://git.dotclear.watch/JcDenis/translater/issues</da:support> <da:support>https://git.dotclear.watch/JcDenis/translater/issues</da:support>
</module> </module>

View File

@ -1,10 +1,11 @@
<?php <?php
/**
* @package Dotclear // Language: Français
* // Module: translater - 2023.10.21
* @copyright Olivier Meunier & Association Dotclear // Date: 2023-10-21 09:42:21
* @copyright GPL-2.0-only // Author: , contact@jcdenis.fr
*/ // Translated with Translater - 2023.10.21
# #
# DOT NOT MODIFY THIS FILE ! # DOT NOT MODIFY THIS FILE !
# #
@ -46,7 +47,6 @@ L10n::$locales['Language successfully added'] = 'Langue cr
L10n::$locales['Language successfully deleted'] = 'Langue effacée avec succès'; L10n::$locales['Language successfully deleted'] = 'Langue effacée avec succès';
L10n::$locales['Nothing to update'] = 'Rien à mettre à jour'; L10n::$locales['Nothing to update'] = 'Rien à mettre à jour';
L10n::$locales['Language successfully updated'] = 'Langue mise à jour avec succès'; L10n::$locales['Language successfully updated'] = 'Langue mise à jour avec succès';
L10n::$locales['Themes'] = 'Thèmes';
L10n::$locales['%s language edition'] = 'Edition de la langue %s'; L10n::$locales['%s language edition'] = 'Edition de la langue %s';
L10n::$locales['Use this text'] = 'Utiliser ce texte'; L10n::$locales['Use this text'] = 'Utiliser ce texte';
L10n::$locales['Translate module %s'] = 'Traduire le module %s'; L10n::$locales['Translate module %s'] = 'Traduire le module %s';

View File

@ -1,394 +1,389 @@
# Language: Français # Language: Français
# Module: translater - 2023.03.17 # Module: translater - 2023.10.21
# Date: 2023-03-17 23:23:46 # Date: 2023-10-21 09:42:21
# Author: , contact@jcdenis.fr # Author: , contact@jcdenis.fr
# Translated with translater 2023.03.17 # Translated with translater 2023.10.21
msgid "" msgid ""
msgstr "" msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: translater 2023.03.17\n" "Project-Id-Version: translater 2023.10.21\n"
"POT-Creation-Date: \n" "POT-Creation-Date: \n"
"PO-Revision-Date: 2023-03-17T23:23:46+00:00\n" "PO-Revision-Date: 2023-10-21T09:42:21+00:00\n"
"Last-Translator: Jean-Christian Denis\n" "Last-Translator: Jean-Christian Denis\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: src/BackendBehaviors.php:64 #: src/BackendBehaviors.php:68
msgid "Translate" msgid "Translate"
msgstr "Traduire" msgstr "Traduire"
#: src/Config.php:90 #: src/Config.php:89
#: src/Manage.php:446 #: src/Manage.php:473
msgid "Translation" msgid "Translation"
msgstr "Traduction" msgstr "Traduction"
#: src/Config.php:94 #: src/Config.php:93
msgid "Write .lang.php files" msgid "Write .lang.php files"
msgstr "Ecrire le fichier .lang.php" msgstr "Ecrire le fichier .lang.php"
#: src/Config.php:99 #: src/Config.php:98
msgid "Translate also strings of template files" msgid "Translate also strings of template files"
msgstr "Traduire également les chaines des fichiers de template" msgstr "Traduire également les chaines des fichiers de template"
#: src/Config.php:104 #: src/Config.php:103
msgid "Translate only unknow strings" msgid "Translate only unknow strings"
msgstr "Traduire uniquement les chaines inconnues" msgstr "Traduire uniquement les chaines inconnues"
#: src/Config.php:109 #: src/Config.php:108
msgid "Hide default modules of Dotclear" msgid "Hide default modules of Dotclear"
msgstr "Cacher les modules de la distribution de Dotclear" msgstr "Cacher les modules de la distribution de Dotclear"
#: src/Config.php:114 #: src/Config.php:113
msgid "Write comments in files" msgid "Write comments in files"
msgstr "Ecrire les commentaires dans les fichiers" msgstr "Ecrire les commentaires dans les fichiers"
#: src/Config.php:119 #: src/Config.php:118
msgid "Write informations about author in files" msgid "Write informations about author in files"
msgstr "Ecrire les informations à propos de l'auteur" msgstr "Ecrire les informations à propos de l'auteur"
#: src/Config.php:123 #: src/Config.php:122
msgid "User info:" msgid "User info:"
msgstr "Information à propos de l'auteur :" msgstr "Information à propos de l'auteur :"
#: src/Config.php:127 #: src/Config.php:126
msgid "Following informations can be used: %s" msgid "Following informations can be used: %s"
msgstr "Les informations suivantes peuvent être utilisées : %s" msgstr "Les informations suivantes peuvent être utilisées : %s"
#: src/Config.php:135 #: src/Config.php:134
msgid "Overwrite existing languages" msgid "Overwrite existing languages"
msgstr "Ecraser les langues existantes" msgstr "Ecraser les langues existantes"
#: src/Config.php:139 #: src/Config.php:138
msgid "Name of exported package:" msgid "Name of exported package:"
msgstr "Nom du paquetage exporté :" msgstr "Nom du paquetage exporté :"
#: src/Config.php:143 #: src/Config.php:142
#: src/Manage.php:262 #: src/Manage.php:274
msgid "Backups" msgid "Backups"
msgstr "Sauvegardes" msgstr "Sauvegardes"
#: src/Config.php:147 #: src/Config.php:146
msgid "Make backups when changes are made" msgid "Make backups when changes are made"
msgstr "Faire une sauvegarde quand des changements sont effectués" msgstr "Faire une sauvegarde quand des changements sont effectués"
#: src/Config.php:151 #: src/Config.php:150
msgid "Limit backups per module to:" msgid "Limit backups per module to:"
msgstr "Limiter les sauvegardes par module à :" msgstr "Limiter les sauvegardes par module à :"
#: src/Config.php:154 #: src/Config.php:153
msgid "Set to 0 for no limit." msgid "Set to 0 for no limit."
msgstr "Mettre à 0 pour aucune limite." msgstr "Mettre à 0 pour aucune limite."
#: src/Config.php:157 #: src/Config.php:156
msgid "Store backups in:" msgid "Store backups in:"
msgstr "Enregistrer les sauvegardes dans :" msgstr "Enregistrer les sauvegardes dans :"
#: src/Config.php:161 #: src/Config.php:160
msgid "Behaviors" msgid "Behaviors"
msgstr "Comportements" msgstr "Comportements"
#: src/Config.php:164 #: src/Config.php:163
msgid "Default start menu:" msgid "Default start menu:"
msgstr "Menu de départ par défaut :" msgstr "Menu de départ par défaut :"
#: src/Config.php:170 #: src/Config.php:169
msgid "Enable menu on plugins page" msgid "Enable menu on plugins page"
msgstr "Activer le menu sur la page des plugins" msgstr "Activer le menu sur la page des plugins"
#: src/Config.php:175 #: src/Config.php:174
msgid "Enable menu on themes page" msgid "Enable menu on themes page"
msgstr "Activer le menu sur la page des thèmes" msgstr "Activer le menu sur la page des thèmes"
#: src/Manage.php:48 #: src/Manage.php:57
msgid "Nothing to backup" msgid "Nothing to backup"
msgstr "Rien à sauvegarder" msgstr "Rien à sauvegarder"
#: src/Manage.php:56 #: src/Manage.php:65
msgid "Backup successfully created" msgid "Backup successfully created"
msgstr "Sauvegarde créée avec succès" msgstr "Sauvegarde créée avec succès"
#: src/Manage.php:61 #: src/Manage.php:70
msgid "Nothing to restore" msgid "Nothing to restore"
msgstr "Rien à restaurer" msgstr "Rien à restaurer"
#: src/Manage.php:69 #: src/Manage.php:78
msgid "Backup successfully restored" msgid "Backup successfully restored"
msgstr "Sauvegarde restaurée avec succès" msgstr "Sauvegarde restaurée avec succès"
#: src/Manage.php:74 #: src/Manage.php:83
msgid "Nothing to delete" msgid "Nothing to delete"
msgstr "Rien à effacer" msgstr "Rien à effacer"
#: src/Manage.php:82 #: src/Manage.php:91
msgid "Backup successfully deleted" msgid "Backup successfully deleted"
msgstr "Sauvegarde effacée avec succès" msgstr "Sauvegarde effacée avec succès"
#: src/Manage.php:87 #: src/Manage.php:96
#: src/TranslaterModule.php:359 #: src/TranslaterModule.php:435
msgid "Nothing to export" msgid "Nothing to export"
msgstr "Rien à exporter" msgstr "Rien à exporter"
#: src/Manage.php:91 #: src/Manage.php:100
msgid "Language successfully exported" msgid "Language successfully exported"
msgstr "Langue exportée avec succès" msgstr "Langue exportée avec succès"
#: src/Manage.php:100 #: src/Manage.php:109
msgid "Language successfully imported" msgid "Language successfully imported"
msgstr "Langue importée avec succès" msgstr "Langue importée avec succès"
#: src/Manage.php:105 #: src/Manage.php:114
msgid "Nothing to create" msgid "Nothing to create"
msgstr "Rien à créer" msgstr "Rien à créer"
#: src/Manage.php:109 #: src/Manage.php:118
msgid "Language successfully added" msgid "Language successfully added"
msgstr "Langue créée avec succès" msgstr "Langue créée avec succès"
#: src/Manage.php:122 #: src/Manage.php:131
msgid "Language successfully deleted" msgid "Language successfully deleted"
msgstr "Langue effacée avec succès" msgstr "Langue effacée avec succès"
#: src/Manage.php:127 #: src/Manage.php:136
msgid "Nothing to update" msgid "Nothing to update"
msgstr "Rien à mettre à jour" msgstr "Rien à mettre à jour"
#: src/Manage.php:138 #: src/Manage.php:147
msgid "Language successfully updated" msgid "Language successfully updated"
msgstr "Langue mise à jour avec succès" msgstr "Langue mise à jour avec succès"
#: src/Manage.php:159 #: src/Manage.php:175
#: src/My.php:64
msgid "Themes"
msgstr "Thèmes"
#: src/Manage.php:166
msgid "%s language edition" msgid "%s language edition"
msgstr "Edition de la langue %s" msgstr "Edition de la langue %s"
#: src/Manage.php:174 #: src/Manage.php:183
msgid "Use this text" msgid "Use this text"
msgstr "Utiliser ce texte" msgstr "Utiliser ce texte"
#: src/Manage.php:203 #: src/Manage.php:212
msgid "Translate module %s" msgid "Translate module %s"
msgstr "Traduire le module %s" msgstr "Traduire le module %s"
#: src/Manage.php:217 #: src/Manage.php:229
msgid "Edit language %s of module %s" msgid "Edit language %s of module %s"
msgstr "Modifier la langue %s du module %s" msgstr "Modifier la langue %s du module %s"
#: src/Manage.php:237 #: src/Manage.php:249
msgid "Modules list of type \"%s\"" msgid "Modules list of type \"%s\""
msgstr "Listes de modules de type \"%s\"" msgstr "Listes de modules de type \"%s\""
#: src/Manage.php:247 #: src/Manage.php:259
msgid "There is no editable modules" msgid "There is no editable modules"
msgstr "Il n'y a pas de module modifiable" msgstr "Il n'y a pas de module modifiable"
#: src/Manage.php:258 #: src/Manage.php:270
msgid "Module %s %s by %s" msgid "Module %s %s by %s"
msgstr "Module %s %s par %s" msgstr "Module %s %s par %s"
#: src/Manage.php:260 #: src/Manage.php:272
msgid "Root" msgid "Root"
msgstr "Racine" msgstr "Racine"
#: src/Manage.php:272 #: src/Manage.php:284
msgid "Existing languages translations" msgid "Existing languages translations"
msgstr "Traductions existantes" msgstr "Traductions existantes"
#: src/Manage.php:277 #: src/Manage.php:289
msgid "Last backup" msgid "Last backup"
msgstr "Dernière sauvegarde" msgstr "Dernière sauvegarde"
#: src/Manage.php:287 #: src/Manage.php:299
msgid "Edit %s language" msgid "Edit %s language"
msgstr "Modifier la langue %s" msgstr "Modifier la langue %s"
#: src/Manage.php:303 #: src/Manage.php:315
msgid "no backups" msgid "no backups"
msgstr "aucune sauvegarde" msgstr "aucune sauvegarde"
#: src/Manage.php:311 #: src/Manage.php:324
msgid "Selected languages action:" msgid "Selected languages action:"
msgstr "Action sur les langues sélectionnées :" msgstr "Action sur les langues sélectionnées :"
#: src/Manage.php:313 #: src/Manage.php:326
msgid "Backup languages" msgid "Backup languages"
msgstr "Sauvegarder les langues" msgstr "Sauvegarder les langues"
#: src/Manage.php:314 #: src/Manage.php:327
msgid "Delete languages" msgid "Delete languages"
msgstr "Effacer les langues" msgstr "Effacer les langues"
#: src/Manage.php:315 #: src/Manage.php:328
msgid "Export languages" msgid "Export languages"
msgstr "Exporter les langues" msgstr "Exporter les langues"
#: src/Manage.php:333 #: src/Manage.php:346
msgid "Existing languages backups" msgid "Existing languages backups"
msgstr "Sauvegardes existantes" msgstr "Sauvegardes existantes"
#: src/Manage.php:377 #: src/Manage.php:391
msgid "Selected backups action:" msgid "Selected backups action:"
msgstr "Action sur les sauvegardes sélectionnées :" msgstr "Action sur les sauvegardes sélectionnées :"
#: src/Manage.php:379 #: src/Manage.php:393
msgid "Restore backups" msgid "Restore backups"
msgstr "Restaurer des sauvegardes" msgstr "Restaurer des sauvegardes"
#: src/Manage.php:380 #: src/Manage.php:394
msgid "Delete backups" msgid "Delete backups"
msgstr "Effacer des sauvegardes" msgstr "Effacer des sauvegardes"
#: src/Manage.php:396 #: src/Manage.php:410
msgid "Add language" msgid "Add language"
msgstr "Ajouter une langue" msgstr "Ajouter une langue"
#: src/Manage.php:404 #: src/Manage.php:422
msgid "Copy from language:" msgid "Copy from language:"
msgstr "Copier depuis la langue :" msgstr "Copier depuis la langue :"
#: src/Manage.php:405 #: src/Manage.php:424
msgid "optionnal" msgid "optionnal"
msgstr "optionnel" msgstr "optionnel"
#: src/Manage.php:420 #: src/Manage.php:443
msgid "Select languages package to import:" msgid "Select languages package to import:"
msgstr "Sélectionner le paquetage de langues à importer :" msgstr "Sélectionner le paquetage de langues à importer :"
#: src/Manage.php:442 #: src/Manage.php:469
msgid "List of %s localized strings" msgid "List of %s localized strings"
msgstr "Liste des %s chaines de traduction" msgstr "Liste des %s chaines de traduction"
#: src/Manage.php:444 #: src/Manage.php:471
msgid "Group" msgid "Group"
msgstr "Groupe" msgstr "Groupe"
#: src/Manage.php:445 #: src/Manage.php:472
msgid "String" msgid "String"
msgstr "Chaine" msgstr "Chaine"
#: src/Manage.php:447 #: src/Manage.php:474
msgid "Existing" msgid "Existing"
msgstr "Existant" msgstr "Existant"
#: src/Manage.php:489 #: src/Manage.php:516
msgid "%s occurrences" msgid "%s occurrences"
msgstr "%s occurences" msgstr "%s occurences"
#: src/Manage.php:529 #: src/Manage.php:556
msgid "Plural \"%s\"" msgid "Plural \"%s\""
msgstr "Pluriel \"%s\"" msgstr "Pluriel \"%s\""
#: src/Manage.php:530 #: src/Manage.php:557
msgid "Plural form of \"%s\"" msgid "Plural form of \"%s\""
msgstr "Forme plurielle de \"%s\"" msgstr "Forme plurielle de \"%s\""
#: src/Manage.php:558 #: src/Manage.php:586
msgid "Change the group of the selected translations to:" msgid "Change the group of the selected translations to:"
msgstr "Changer le groupe des chaines sélectionnées vers :" msgstr "Changer le groupe des chaines sélectionnées vers :"
#: src/Manage.php:577 #: src/Manage.php:608
msgid "Translate your Dotclear plugins and themes" msgid "Translate your Dotclear plugins and themes"
msgstr "Traduire vos plugins et thèmes Dotclear" msgstr "Traduire vos plugins et thèmes Dotclear"
#: src/Manage.php:584 #: src/Manage.php:615
msgid "Translate plugins" msgid "Translate plugins"
msgstr "Traduire des plugins" msgstr "Traduire des plugins"
#: src/Manage.php:590 #: src/Manage.php:621
msgid "Translate themes" msgid "Translate themes"
msgstr "Traduire des thèmes" msgstr "Traduire des thèmes"
#: src/My.php:49 #: src/My.php:39
msgid "locales folders of each module" msgid "locales folders of each module"
msgstr "le fichier locales de chaque module" msgstr "le fichier locales de chaque module"
#: src/My.php:50 #: src/My.php:40
msgid "plugins folder root" msgid "plugins folder root"
msgstr "la racine du dossier des plugins" msgstr "la racine du dossier des plugins"
#: src/My.php:51 #: src/My.php:41
msgid "public folder root" msgid "public folder root"
msgstr "la racine du dossier public" msgstr "la racine du dossier public"
#: src/My.php:52 #: src/My.php:42
msgid "cache folder of Dotclear" msgid "cache folder of Dotclear"
msgstr "le dossier cache de Dotclear" msgstr "le dossier cache de Dotclear"
#: src/My.php:53 #: src/My.php:43
msgid "locales folder of translater" msgid "locales folder of translater"
msgstr "le dossier locales de Traducteur" msgstr "le dossier locales de Traducteur"
#: src/Translater.php:97 #: src/Translater.php:94
msgid "Failed to find module %s" msgid "Failed to find module %s"
msgstr "Impossible de trouver le module %s" msgstr "Impossible de trouver le module %s"
#: src/Translater.php:116 #: src/Translater.php:113
msgid "Failed find language %s" msgid "Failed find language %s"
msgstr "Impossible de trouver la langue %s" msgstr "Impossible de trouver la langue %s"
#: src/Translater.php:240 #: src/Translater.php:243
msgid "Limit of %s backups for module %s exceed" msgid "Limit of %s backups for module %s exceed"
msgstr "La limite de %s sauvegardes pour le module %s est atteinte" msgstr "La limite de %s sauvegardes pour le module %s est atteinte"
#: src/TranslaterModule.php:131 #: src/TranslaterModule.php:177
msgid "Failed to find backups folder for module %s" msgid "Failed to find backups folder for module %s"
msgstr "Impossible de trouver le dossier de sauvegarde pour le module %s" msgstr "Impossible de trouver le dossier de sauvegarde pour le module %s"
#: src/TranslaterModule.php:192 #: src/TranslaterModule.php:267
msgid "Failed to find language %s" msgid "Failed to find language %s"
msgstr "Impossible de trouver la langue %s" msgstr "Impossible de trouver la langue %s"
#: src/TranslaterModule.php:238 #: src/TranslaterModule.php:312
msgid "Failed to find file %s" msgid "Failed to find file %s"
msgstr "Impossible de trouver le fichier %s" msgstr "Impossible de trouver le fichier %s"
#: src/TranslaterModule.php:278 #: src/TranslaterModule.php:353
msgid "Failed to delete file %s" msgid "Failed to delete file %s"
msgstr "Impossible d'effacer le fichier %s" msgstr "Impossible d'effacer le fichier %s"
#: src/TranslaterModule.php:337 #: src/TranslaterModule.php:413
msgid "Some languages has not been overwrited %s" msgid "Some languages has not been overwrited %s"
msgstr "Des langues n'ont pas été écrasées : %s" msgstr "Des langues n'ont pas été écrasées : %s"
#: src/TranslaterModule.php:342 #: src/TranslaterModule.php:418
msgid "Nothing to import from %s" msgid "Nothing to import from %s"
msgstr "Rien à importer" msgstr "Rien à importer"
#: src/TranslaterModule.php:366 #: src/TranslaterModule.php:442
msgid "Export mask is not set in plugin configuration" msgid "Export mask is not set in plugin configuration"
msgstr "Le masque d'export n'est pas renseigné dans la configuration du plugin" msgstr "Le masque d'export n'est pas renseigné dans la configuration du plugin"
#: src/TranslaterModule.php:436 #: src/TranslaterModule.php:512
msgid "Zip file %s is not in translater format" msgid "Zip file %s is not in translater format"
msgstr "Le fichier zip n'est pas au format de traduction" msgstr "Le fichier zip n'est pas au format de traduction"
#: src/TranslaterModule.php:518 #: src/TranslaterModule.php:616
msgid "Unknow language %s" msgid "Unknow language %s"
msgstr "Langue %s inconnue" msgstr "Langue %s inconnue"
#: src/TranslaterModule.php:526 #: src/TranslaterModule.php:624
msgid "Language %s already exists" msgid "Language %s already exists"
msgstr "La langue %s existe déjà" msgstr "La langue %s existe déjà"
#: src/TranslaterModule.php:535 #: src/TranslaterModule.php:633
msgid "Failed to copy file from language %s" msgid "Failed to copy file from language %s"
msgstr "Impossible de copier le fichier depuis la langue %s" msgstr "Impossible de copier le fichier depuis la langue %s"
#: src/TranslaterModule.php:616 #: src/TranslaterModule.php:714
msgid "No string to write, language %s deleted" msgid "No string to write, language %s deleted"
msgstr "Rien à écrire, le fichiers de langue %s est effacé" msgstr "Rien à écrire, le fichiers de langue %s est effacé"
#: src/TranslaterModule.php:744 #: src/TranslaterModule.php:844
msgid "Failed to grant write acces on file %s" msgid "Failed to grant write acces on file %s"
msgstr "Impossible d'avoir les droits en écriture sur le fichier %s" msgstr "Impossible d'avoir les droits en écriture sur le fichier %s"
#: src/TranslaterModule.php:751 #: src/TranslaterModule.php:851
msgid "Failed to write file %s" msgid "Failed to write file %s"
msgstr "Impossible d'écrire le fichier %s" msgstr "Impossible d'écrire le fichier %s"

View File

@ -1,19 +1,12 @@
<?php <?php
/** /**
* @brief translater, a plugin for Dotclear 2 * @file
* @brief The plugin translater locales resources
* @ingroup translater
* *
* @package Dotclear * @author Jean-Christian Denis
* @subpackage Plugin * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_RC_PATH')) {
return;
}
foreach (['index', 'type', 'module', 'lang', 'config'] as $v) { foreach (['index', 'type', 'module', 'lang', 'config'] as $v) {
dcCore::app()->resources['help']['translater.' . $v] = __DIR__ . '/help/translater.' . $v . '.html'; \Dotclear\App::backend()->resources()->set('help', 'translater.' . $v, __DIR__ . '/help/translater.' . $v . '.html');
} }

View File

@ -1,23 +1,20 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore; use Dotclear\App;
use Dotclear\Core\Process; use Dotclear\Core\Process;
use Dotclear\Core\Backend\Favorites; use Dotclear\Core\Backend\Favorites;
/**
* @brief translater backend class.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Backend extends Process class Backend extends Process
{ {
public static function init(): bool public static function init(): bool
@ -33,16 +30,15 @@ class Backend extends Process
My::addBackendMenuItem(); My::addBackendMenuItem();
dcCore::app()->addBehaviors([ App::behavior()->addBehaviors([
'adminModulesListGetActions' => [BackendBehaviors::class, 'adminModulesGetActions'], 'adminModulesListGetActions' => BackendBehaviors::adminModulesGetActions(...),
'adminModulesListDoActions' => [BackendBehaviors::class, 'adminModulesDoActions'], 'adminModulesListDoActions' => BackendBehaviors::adminModulesDoActions(...),
'adminDashboardFavoritesV2' => function (Favorites $favs): void { 'adminDashboardFavoritesV2' => function (Favorites $favs): void {
$favs->register(My::id(), [ $favs->register(My::id(), [
'title' => My::name(), 'title' => My::name(),
'url' => My::manageUrl(), 'url' => My::manageUrl(),
'small-icon' => My::icons(), 'small-icon' => My::icons(),
'large-icon' => My::icons(), 'large-icon' => My::icons(),
//'permissions' => null,
]); ]);
}, },
]); ]);

View File

@ -1,37 +1,38 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore; use Dotclear\App;
use Dotclear\Core\Backend\ModulesList; use Dotclear\Core\Backend\ModulesList;
use Dotclear\Helper\Html\Form\Submit; use Dotclear\Helper\Html\Form\Submit;
use Dotclear\Helper\Html\Html; use Dotclear\Helper\Html\Html;
/**
* @brief translater backend behaviors class.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class BackendBehaviors class BackendBehaviors
{ {
/** @var Translater Translater instance */ /**
* Translater instance.
*
* @var ?Translater $translater
*/
private static $translater = null; private static $translater = null;
/** /**
* Create instance of Translater once * Create instance of Translater once.
* *
* @return Translater Translater instance * @return Translater Translater instance
*/ */
private static function translater(): Translater private static function translater(): Translater
{ {
if (!is_a(self::$translater, Translater::class)) { if (is_null(self::$translater)) {
self::$translater = new Translater(false); self::$translater = new Translater(false);
} }
@ -39,19 +40,22 @@ class BackendBehaviors
} }
/** /**
* Add button to go to module translation * Add button to go to module translation.
* *
* @param ModulesList $list ModulesList instance * @param ModulesList $list ModulesList instance
* @param string $id Module id * @param string $id Module id
* @param array $prop Module properties * @param array<string, mixed> $prop Module properties
* *
* @return string HTML submit button * @return ?string HTML submit button
*/ */
public static function adminModulesGetActions(ModulesList $list, string $id, array $prop): ?string public static function adminModulesGetActions(ModulesList $list, string $id, array $prop): ?string
{ {
if (!is_string($prop['type'])) {
return null;
}
if ($list->getList() != $prop['type'] . '-activate' if ($list->getList() != $prop['type'] . '-activate'
|| !self::translater()->getSetting($prop['type'] . '_menu') || !self::translater()->getSetting($prop['type'] . '_menu')
|| !dcCore::app()->auth?->isSuperAdmin() || !App::auth()->isSuperAdmin()
) { ) {
return null; return null;
} }
@ -61,15 +65,15 @@ class BackendBehaviors
return null; return null;
} }
return (new Submit(['translater[' . Html::escapeHTML($id) . ']', null]))->value(__('Translate'))->render(); return (new Submit(['translater[' . Html::escapeHTML($id) . ']']))->value(__('Translate'))->render();
} }
/** /**
* Redirect to module translation * Redirect to module translation.
* *
* @param ModulesList $list ModulesList instance * @param ModulesList $list ModulesList instance
* @param array $modules Selected modules ids * @param array<int, string> $modules Selected modules ids
* @param string $type List type (plugin|theme) * @param string $type List type (plugin|theme)
*/ */
public static function adminModulesDoActions(ModulesList $list, array $modules, string $type): void public static function adminModulesDoActions(ModulesList $list, array $modules, string $type): void
{ {

View File

@ -1,20 +1,10 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore; use Dotclear\App;
use Dotclear\Core\Process; use Dotclear\Core\Process;
use Dotclear\Core\Backend\{ use Dotclear\Core\Backend\{
Notices, Notices,
@ -34,6 +24,13 @@ use Dotclear\Helper\Html\Form\{
}; };
use Exception; use Exception;
/**
* @brief translater backend config class.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Config extends Process class Config extends Process
{ {
public static function init(): bool public static function init(): bool
@ -56,6 +53,9 @@ class Config extends Process
try { try {
foreach ($s->listSettings() as $key => $value) { foreach ($s->listSettings() as $key => $value) {
if (!is_string($key)) {
continue;
}
if (is_bool($value)) { if (is_bool($value)) {
$s->writeSetting($key, !empty($_POST[$key])); $s->writeSetting($key, !empty($_POST[$key]));
} else { } else {
@ -66,12 +66,12 @@ class Config extends Process
Notices::addSuccessNotice( Notices::addSuccessNotice(
__('Configuration successfully updated.') __('Configuration successfully updated.')
); );
dcCore::app()->admin->url->redirect( App::backend()->url()->redirect(
'admin.plugins', 'admin.plugins',
['module' => My::id(), 'conf' => 1, 'redir' => dcCore::app()->admin->__get('list')->getRedir()] ['module' => My::id(), 'conf' => 1, 'redir' => App::backend()->__get('list')->getRedir()]
); );
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); App::error()->add($e->getMessage());
} }
return true; return true;
@ -120,7 +120,7 @@ class Config extends Process
// parse_userinfo // parse_userinfo
(new Para())->items([ (new Para())->items([
(new Label(__('User info:')))->for('parse_userinfo'), (new Label(__('User info:')))->for('parse_userinfo'),
(new Input('parse_userinfo'))->size(65)->maxlenght(255)->value($s->parse_userinfo), (new Input('parse_userinfo'))->size(65)->maxlength(255)->value($s->parse_userinfo),
]), ]),
(new Note())->text(sprintf( (new Note())->text(sprintf(
__('Following informations can be used: %s'), __('Following informations can be used: %s'),
@ -136,7 +136,7 @@ class Config extends Process
// export_filename // export_filename
(new Para())->items([ (new Para())->items([
(new Label(__('Name of exported package:')))->for('export_filename'), (new Label(__('Name of exported package:')))->for('export_filename'),
(new Input('export_filename'))->size(65)->maxlenght(255)->value($s->export_filename), (new Input('export_filename'))->size(65)->maxlength(255)->value($s->export_filename),
]), ]),
]), ]),
(new Fieldset())->class('fieldset')->legend((new Legend(__('Backups'))))->fields([ (new Fieldset())->class('fieldset')->legend((new Legend(__('Backups'))))->fields([

View File

@ -1,24 +1,21 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore; use Dotclear\App;
use dcNamespace;
use Dotclear\Core\Process; use Dotclear\Core\Process;
use Dotclear\Database\Statement\SelectStatement;
use Exception; use Exception;
/**
* @brief translater install class.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Install extends Process class Install extends Process
{ {
public static function init(): bool public static function init(): bool
@ -37,7 +34,7 @@ class Install extends Process
return true; return true;
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); App::error()->add($e->getMessage());
} }
return true; return true;
@ -50,22 +47,29 @@ class Install extends Process
*/ */
private static function growUp() private static function growUp()
{ {
$current = dcCore::app()->getVersion(My::id()); $current = App::version()->getVersion(My::id());
// use short settings id // use short settings id
if ($current && version_compare($current, '2022.12.22', '<')) { if ($current && version_compare($current, '2022.12.22', '<')) {
$record = dcCore::app()->con->select( $sql = new SelectStatement();
'SELECT * FROM ' . dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME . ' ' . $record = $sql
"WHERE setting_ns = 'translater' " ->column('*')
); ->from(App::con()->prefix() . App::blogWorkspace()::NS_TABLE_NAME)
->where("setting_ns = 'translater' ")
->select();
if (!$record) {
return true;
}
while ($record->fetch()) { while ($record->fetch()) {
if (preg_match('/^translater_(.*?)$/', $record->f('setting_id'), $match)) { if (preg_match('/^translater_(.*?)$/', $record->f('setting_id'), $match)) {
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME); $cur = App::blogWorkspace()->openBlogWorkspaceCursor();
$cur->setField('setting_id', $match[1]); $cur->setField('setting_id', $match[1]);
$cur->setField('setting_ns', My::id()); $cur->setField('setting_ns', My::id());
$cur->update( $cur->update(
"WHERE setting_id = '" . $record->f('setting_id') . "' and setting_ns = 'translater' " . "WHERE setting_id = '" . $record->f('setting_id') . "' and setting_ns = 'translater' " .
'AND blog_id ' . (null === $record->f('blog_id') ? 'IS NULL ' : ("= '" . dcCore::app()->con->escapeStr((string) $record->f('blog_id')) . "' ")) 'AND blog_id ' . (null === $record->f('blog_id') ? 'IS NULL ' : ("= '" . App::con()->escapeStr((string) $record->f('blog_id')) . "' "))
); );
} }
} }

View File

@ -1,20 +1,10 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore; use Dotclear\App;
use Dotclear\Core\Process; use Dotclear\Core\Process;
use Dotclear\Core\Backend\{ use Dotclear\Core\Backend\{
Notices, Notices,
@ -38,6 +28,13 @@ use Dotclear\Helper\Date;
use Dotclear\Helper\Html\Html; use Dotclear\Helper\Html\Html;
use Exception; use Exception;
/**
* @brief translater manage class.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Manage extends Process class Manage extends Process
{ {
public static function init(): bool public static function init(): bool
@ -72,7 +69,7 @@ class Manage extends Process
if (empty($current->module) || empty($_POST['files'])) { if (empty($current->module) || empty($_POST['files'])) {
throw new Exception(__('Nothing to restore')); throw new Exception(__('Nothing to restore'));
} }
foreach ($current->module->getBackups(true) as $backup_file) { foreach ($current->module->getBackupsFilename() as $backup_file) {
if (in_array($backup_file, $_POST['files'])) { if (in_array($backup_file, $_POST['files'])) {
$current->module->restoreBackup($backup_file); $current->module->restoreBackup($backup_file);
} }
@ -85,7 +82,7 @@ class Manage extends Process
if (empty($current->module) || empty($_POST['files'])) { if (empty($current->module) || empty($_POST['files'])) {
throw new Exception(__('Nothing to delete')); throw new Exception(__('Nothing to delete'));
} }
foreach ($current->module->getBackups(true) as $backup_file) { foreach ($current->module->getBackupsFilename() as $backup_file) {
if (in_array($backup_file, $_POST['files'])) { if (in_array($backup_file, $_POST['files'])) {
$current->module->deleteBackup($backup_file); $current->module->deleteBackup($backup_file);
} }
@ -150,7 +147,7 @@ class Manage extends Process
self::redirect(__('Language successfully updated'), $_POST['code']); self::redirect(__('Language successfully updated'), $_POST['code']);
} }
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); App::error()->add($e->getMessage());
} }
return true; return true;
@ -190,7 +187,7 @@ class Manage extends Process
My::jsLoad('backend') . My::jsLoad('backend') .
# --BEHAVIOR-- translaterAdminHeaders # --BEHAVIOR-- translaterAdminHeaders
dcCore::app()->callBehavior('translaterAdminHeaders') App::behavior()->callBehavior('translaterAdminHeaders')
); );
echo echo
@ -223,6 +220,9 @@ class Manage extends Process
} }
$codes = $module->getLangs(); $codes = $module->getLangs();
foreach ($codes as $code_id => $code_name) { foreach ($codes as $code_id => $code_name) {
if (!is_string($code_name)) {
continue;
}
if ($module->root_writable) { if ($module->root_writable) {
$codes[$code_id] = sprintf( $codes[$code_id] = sprintf(
'<a class="wait maximal nowrap" title="%s" href="%s">%s (%s)</a>', '<a class="wait maximal nowrap" title="%s" href="%s">%s (%s)</a>',
@ -309,7 +309,7 @@ class Manage extends Process
echo echo
'<td class="nowrap">' . count($backups[$code_id]) . '</td>' . '<td class="nowrap">' . count($backups[$code_id]) . '</td>' .
'<td class="nowrap"> ' . '<td class="nowrap"> ' .
Date::str('%Y-%m-%d %H:%M', (int) $time[$code_id], (string) dcCore::app()->blog?->settings->get('system')->get('blog_timezone')) . Date::str('%Y-%m-%d %H:%M', (int) $time[$code_id], (string) App::blog()->settings()->get('system')->get('blog_timezone')) .
'</td>'; '</td>';
} else { } else {
echo '<td class="nowrap">' . __('no backups') . '</td><td class="maximal nowrap">-</td>'; echo '<td class="nowrap">' . __('no backups') . '</td><td class="maximal nowrap">-</td>';
@ -365,20 +365,20 @@ class Manage extends Process
foreach ($backups as $backup_codes) { foreach ($backups as $backup_codes) {
foreach ($backup_codes as $backup_file => $backup_code) { foreach ($backup_codes as $backup_file => $backup_code) {
$i++; $i++;
$form_id = 'form_file_' . $backup_code['code'] . $backup_code['time']; $form_id = 'form_file_' . (is_string($backup_code['code']) ? $backup_code['code'] : '') . (is_string($backup_code['time']) ? $backup_code['time'] : '');
echo sprintf( echo sprintf(
$table_line, $table_line,
(new Checkbox(['files[]', $form_id]))->value($backup_file)->render(), (new Checkbox(['files[]', $form_id]))->value($backup_file)->render(),
$form_id, $form_id,
$backup_code['name'], is_string($backup_code['name']) ? $backup_code['name'] : 'unknown',
$backup_code['code'], is_string($backup_code['code']) ? $backup_code['code'] : 'unknown',
Date::str( Date::str(
dcCore::app()->blog?->settings->get('system')->get('date_format') . ' ' . dcCore::app()->blog?->settings->get('system')->get('time_format'), App::blog()->settings()->get('system')->get('date_format') . ' ' . App::blog()->settings()->get('system')->get('time_format'),
(int) $backup_code['time'], (int) $backup_code['time'],
dcCore::app()->blog?->settings->get('system')->get('blog_timezone') App::blog()->settings()->get('system')->get('blog_timezone')
), ),
$backup_code['path']['basename'], is_array($backup_code['path']) ? $backup_code['path']['basename'] : '',
Files::size($backup_code['size']) Files::size((int) $backup_code['size'])
); );
} }
} }
@ -411,7 +411,7 @@ class Manage extends Process
<form id="module-code-create-form" method="post" action="' . My::manageUrl() . '">' . <form id="module-code-create-form" method="post" action="' . My::manageUrl() . '">' .
(new Para())->class('field')->items([ (new Para())->class('field')->items([
(new Label(__('Select language:')))->for('code'), (new Label(__('Select language:')))->for('code'),
(new Select(['code']))->default((string) dcCore::app()->auth?->getInfo('user_lang'))->items(array_merge(['-' => '-'], $unused_codes)), (new Select(['code']))->default((string) App::auth()->getInfo('user_lang'))->items(array_merge(['-' => '-'], $unused_codes)),
])->render(); ])->render();
if (empty($codes)) { if (empty($codes)) {
@ -525,7 +525,7 @@ class Manage extends Process
(new Select(['entries[' . $i . '][group]']))->default($rs['group'])->items(My::l10nGroupsCombo())->disabled($in_dc)->render(), (new Select(['entries[' . $i . '][group]']))->default($rs['group'])->items(My::l10nGroupsCombo())->disabled($in_dc)->render(),
Html::escapeHTML($msgid), Html::escapeHTML($msgid),
(new Hidden(['entries[' . $i . '][msgid]'], Html::escapeHTML($msgid)))->render() . (new Hidden(['entries[' . $i . '][msgid]'], Html::escapeHTML($msgid)))->render() .
(new Input(['entries[' . $i . '][msgstr][0]']))->size(48)->maxlenght(255)->value(Html::escapeHTML($rs['msgstr'][0]))->disabled($in_dc)->render(), (new Input(['entries[' . $i . '][msgstr][0]']))->size(48)->maxlength(255)->value(Html::escapeHTML($rs['msgstr'][0]))->disabled($in_dc)->render(),
implode('', $t_msgstr), implode('', $t_msgstr),
implode('', $t_files) implode('', $t_files)
); );
@ -556,7 +556,7 @@ class Manage extends Process
sprintf(__('Plural "%s"'), $plural), sprintf(__('Plural "%s"'), $plural),
sprintf(__('Plural form of "%s"'), $rs['plural']), sprintf(__('Plural form of "%s"'), $rs['plural']),
(new Hidden(['entries[' . $i . '][msgid_plural]'], Html::escapeHTML($rs['plural'])))->render() . (new Hidden(['entries[' . $i . '][msgid_plural]'], Html::escapeHTML($rs['plural'])))->render() .
(new Input(['entries[' . $i . '][msgstr][' . ($j + 1) . ']']))->size(48)->maxlenght(255)->value(Html::escapeHTML($rs['msgstr'][$j + 1] ?? ''))->disbaled($in_dc)->render(), (new Input(['entries[' . $i . '][msgstr][' . ($j + 1) . ']']))->size(48)->maxlength(255)->value(Html::escapeHTML($rs['msgstr'][$j + 1] ?? ''))->disabled($in_dc)->render(),
implode('', $t_msgstr), implode('', $t_msgstr),
'' ''
); );
@ -569,8 +569,8 @@ class Manage extends Process
' offline', ' offline',
(new Checkbox(['entries[' . $i . '][check]']))->value(1)->render(), (new Checkbox(['entries[' . $i . '][check]']))->value(1)->render(),
(new Select(['entries[' . $i . '][group]']))->items(My::l10nGroupsCombo())->default('main')->render(), (new Select(['entries[' . $i . '][group]']))->items(My::l10nGroupsCombo())->default('main')->render(),
(new Input(['entries[' . $i . '][msgid]']))->size(48)->maxlenght(255)->render(), (new Input(['entries[' . $i . '][msgid]']))->size(48)->maxlength(255)->render(),
(new Input(['entries[' . $i . '][msgstr][0]']))->size(48)->maxlenght(255)->render(), (new Input(['entries[' . $i . '][msgstr][0]']))->size(48)->maxlength(255)->render(),
'', '',
'' ''
); );
@ -590,8 +590,8 @@ class Manage extends Process
(new Para())->class('col right')->items([ (new Para())->class('col right')->items([
(new Submit('do-action'))->value(__('Save') . ' (s)')->accesskey('s'), (new Submit('do-action'))->value(__('Save') . ' (s)')->accesskey('s'),
... My::hiddenFields([ ... My::hiddenFields([
'type' => $current->module->type, 'type' => (string) $current->module?->type,
'module' => $current->module->id, 'module' => (string) $current->module?->id,
'action' => 'module_update_code', 'action' => 'module_update_code',
'lang' => $current->lang->code, 'lang' => $current->lang->code,
'code' => $current->lang->code, //? 'code' => $current->lang->code, //?
@ -634,7 +634,7 @@ class Manage extends Process
$redir = [ $redir = [
'type' => $current->type, 'type' => $current->type,
'module' => $current->module?->id, 'module' => (string) $current->module?->id,
]; ];
if ($lang) { if ($lang) {
$redir['lang'] = $lang; $redir['lang'] = $lang;

View File

@ -1,35 +1,66 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore; use Dotclear\App;
use Exception; use Exception;
/**
* @brief translater vars helper.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class ManageVars class ManageVars
{ {
/** /**
* @var ManageVars self instance * self instance.
*
* @var ManageVars $instance
*/ */
private static $container; private static $instance;
/**
* translater instance.
*
* @var Translater $translater
*/
public readonly Translater $translater; public readonly Translater $translater;
/**
* Module instance.
*
* @var TranslaterModule $module
*/
public readonly ?TranslaterModule $module; public readonly ?TranslaterModule $module;
/**
* Lang instance.
*
* @var TranslaterLang $lang
*/
public readonly ?TranslaterLang $lang; public readonly ?TranslaterLang $lang;
/**
* The module type.
*
* @var string $type
*/
public readonly string $type; public readonly string $type;
/**
* The action.
*
* @var string $action
*/
public readonly string $action; public readonly string $action;
/**
* Constructor.
*/
protected function __construct() protected function __construct()
{ {
$this->translater = new Translater(); $this->translater = new Translater();
@ -48,7 +79,7 @@ class ManageVars
try { try {
$module = $this->translater->getModule($type, $module); $module = $this->translater->getModule($type, $module);
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); App::error()->add($e->getMessage());
$module = null; $module = null;
} }
} }
@ -57,7 +88,7 @@ class ManageVars
try { try {
$lang = $this->translater->getLang($module, $lang); $lang = $this->translater->getLang($module, $lang);
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); App::error()->add($e->getMessage());
$lang = null; $lang = null;
} }
} }
@ -68,12 +99,17 @@ class ManageVars
$this->action = $action; $this->action = $action;
} }
/**
* Get self instance.
*
* @return ManageVars self instance
*/
public static function init(): ManageVars public static function init(): ManageVars
{ {
if (!(self::$container instanceof self)) { if (!(self::$instance instanceof self)) {
self::$container = new self(); self::$instance = new self();
} }
return self::$container; return self::$instance;
} }
} }

View File

@ -1,36 +1,41 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore; use Dotclear\App;
use Dotclear\Module\MyPlugin; use Dotclear\Module\MyPlugin;
/** /**
* Plugin definitions * @brief translater My helper.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class My extends MyPlugin class My extends MyPlugin
{ {
/** @var string Locales folder name */ /**
* Locales folder name.
*
* @var string LOCALES_FOLDER
*/
public const LOCALES_FOLDER = 'locales'; public const LOCALES_FOLDER = 'locales';
public static function checkCustomContext(int $context): ?bool public static function checkCustomContext(int $context): ?bool
{ {
return in_array($context, [My::BACKEND, My::MANAGE, My::MENU]) ? dcCore::app()->auth->isSuperAdmin() : null; return match ($context) {
// Limit to super admin
self::MODULE => App::auth()->isSuperAdmin(),
default => null,
};
} }
/** /**
* List of allowed backup folder * List of allowed backup folder.
*
* @return array<string, string>
*/ */
public static function backupFoldersCombo(): array public static function backupFoldersCombo(): array
{ {
@ -44,7 +49,9 @@ class My extends MyPlugin
} }
/** /**
* List of possible home tab of the plugin * List of possible home tab of the plugin.
*
* @return array<string, string>
*/ */
public static function startPageCombo(): array public static function startPageCombo(): array
{ {
@ -56,7 +63,9 @@ class My extends MyPlugin
} }
/** /**
* List of place of tranlsations * List of place of tranlsations.
*
* @return array<string, string>
*/ */
public static function l10nGroupsCombo(): array public static function l10nGroupsCombo(): array
{ {
@ -68,7 +77,9 @@ class My extends MyPlugin
} }
/** /**
* List of user info can be parsed * List of user info can be parsed.
*
* @return array<int, string>
*/ */
public static function defaultUserInformations(): array public static function defaultUserInformations(): array
{ {
@ -78,13 +89,17 @@ class My extends MyPlugin
} }
/** /**
* List of distributed plugins and themes * List of distributed plugins and themes.
*
* @param string $type The modules type
*
* @return array<int, string>
*/ */
public static function defaultDistribModules(string $type): array public static function defaultDistribModules(string $type): array
{ {
$types = [ $types = [
'plugin' => explode(',', DC_DISTRIB_PLUGINS), 'plugin' => explode(',', App::config()->distributedPlugins()),
'theme' => explode(',', DC_DISTRIB_THEMES), 'theme' => explode(',', App::config()->distributedThemes()),
]; ];
return $types[$type] ?? []; return $types[$type] ?? [];

View File

@ -1,64 +1,121 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
/**
* @brief translater settings helper.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Settings class Settings
{ {
// Show tranlsater button on plugins list /**
* Show tranlsater button on plugins list.
*
* @var bool $plugin_menu
*/
public readonly bool $plugin_menu; public readonly bool $plugin_menu;
// Show tranlsater button on themes list /**
* Show tranlsater button on themes list.
*
* @var bool $theme_menu
*/
public readonly bool $theme_menu; public readonly bool $theme_menu;
// Create language backup on save /**
* Create language backup on save.
*
* @var bool $backup_auto
*/
public readonly bool $backup_auto; public readonly bool $backup_auto;
// Backups number limit /**
* Backups number limit.
*
* @var int $backup_limit
*/
public readonly int $backup_limit; public readonly int $backup_limit;
// Backup main folder /**
* Backup main folder.
*
* @var string $backup_folder
*/
public readonly string $backup_folder; public readonly string $backup_folder;
// Default ui start page /**
* Default ui start page.
*
* @var string $start_page
*/
public readonly string $start_page; public readonly string $start_page;
// Write .lang.php file (deprecated) /**
* Write .lang.php file (deprecated).
*
* @var bool $write_langphp
*/
public readonly bool $write_langphp; public readonly bool $write_langphp;
// Scan also template files for translations /**
* Scan also template files for translations.
*
* @var bool $scan_tpl
*/
public readonly bool $scan_tpl; public readonly bool $scan_tpl;
// Disable translation of know dotclear strings /**
* Disable translation of know dotclear strings.
*
* @var bool $parse_nodc
*/
public readonly bool $parse_nodc; public readonly bool $parse_nodc;
// Hide official modules /**
* Hide official modules.
*
* @var bool $hide_default
*/
public readonly bool $hide_default; public readonly bool $hide_default;
// Add comment to translations files /**
* Add comment to translations files.
*
* @var bool $parse_comment
*/
public readonly bool $parse_comment; public readonly bool $parse_comment;
// Parse user info to translations files /**
* Parse user info to translations files.
*
* @var bool $parse_user
*/
public readonly bool $parse_user; public readonly bool $parse_user;
// User infos to parse /**
* User infos to parse.
*
* @var string $parse_userinfo
*/
public readonly string $parse_userinfo; public readonly string $parse_userinfo;
// Overwrite existing languages on import /**
* Overwrite existing languages on import.
*
* @var bool $import_overwrite
*/
public readonly bool $import_overwrite; public readonly bool $import_overwrite;
// Filename of exported lang /**
* Filename of exported lang.
*
* @var string $export_filename
*/
public readonly string $export_filename; public readonly string $export_filename;
/** /**
@ -68,30 +125,35 @@ class Settings
{ {
$s = My::settings(); $s = My::settings();
$this->plugin_menu = (bool) ($s?->get('plugin_menu') ?? false); $this->plugin_menu = (bool) ($s->get('plugin_menu') ?? false);
$this->theme_menu = (bool) ($s?->get('theme_menu') ?? false); $this->theme_menu = (bool) ($s->get('theme_menu') ?? false);
$this->backup_auto = (bool) ($s?->get('backup_auto') ?? false); $this->backup_auto = (bool) ($s->get('backup_auto') ?? false);
$this->backup_limit = (int) ($s?->get('backup_limit') ?? 20); $this->backup_limit = (int) ($s->get('backup_limit') ?? 20);
$this->backup_folder = (string) ($s?->get('backup_folder') ?? 'module'); $this->backup_folder = (string) ($s->get('backup_folder') ?? 'module');
$this->start_page = (string) ($s?->get('start_page') ?? '-'); $this->start_page = (string) ($s->get('start_page') ?? '-');
$this->write_langphp = (bool) ($s?->get('write_langphp') ?? false); $this->write_langphp = (bool) ($s->get('write_langphp') ?? false);
$this->scan_tpl = (bool) ($s?->get('scan_tpl') ?? true); $this->scan_tpl = (bool) ($s->get('scan_tpl') ?? true);
$this->parse_nodc = (bool) ($s?->get('parse_nodc') ?? true); $this->parse_nodc = (bool) ($s->get('parse_nodc') ?? true);
$this->hide_default = (bool) ($s?->get('hide_default') ?? true); $this->hide_default = (bool) ($s->get('hide_default') ?? true);
$this->parse_comment = (bool) ($s?->get('parse_comment') ?? false); $this->parse_comment = (bool) ($s->get('parse_comment') ?? false);
$this->parse_user = (bool) ($s?->get('parse_user') ?? false); $this->parse_user = (bool) ($s->get('parse_user') ?? false);
$this->parse_userinfo = (string) ($s?->get('parse_userinfo') ?? 'displayname, email'); $this->parse_userinfo = (string) ($s->get('parse_userinfo') ?? 'displayname, email');
$this->import_overwrite = (bool) ($s?->get('import_overwrite') ?? false); $this->import_overwrite = (bool) ($s->get('import_overwrite') ?? false);
$this->export_filename = (string) ($s?->get('export_filename') ?? 'type-module-l10n-timestamp'); $this->export_filename = (string) ($s->get('export_filename') ?? 'type-module-l10n-timestamp');
} }
/**
* Get a setting.
*
* @return null|bool|int|string
*/
public function getSetting(string $key): mixed public function getSetting(string $key): mixed
{ {
return $this->{$key} ?? null; return $this->{$key} ?? null;
} }
/** /**
* Overwrite a plugin settings (in db) * Overwrite a plugin settings (in db).
* *
* @param string $key The setting ID * @param string $key The setting ID
* @param mixed $value The setting value * @param mixed $value The setting value
@ -111,9 +173,9 @@ class Settings
} }
/** /**
* List defined settings keys * List defined settings keys.
* *
* @return array The settings keys * @return array<string, null|bool|int|string> The settings keys
*/ */
public function listSettings(): array public function listSettings(): array
{ {

View File

@ -1,40 +1,37 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore; use Dotclear\App;
use dcModuleDefine;
use dcThemes;
use Dotclear\Helper\File\Files; use Dotclear\Helper\File\Files;
use Dotclear\Helper\File\Path; use Dotclear\Helper\File\Path;
use Dotclear\Helper\L10n; use Dotclear\Helper\L10n;
use Dotclear\Helper\Text; use Dotclear\Helper\Text;
use Dotclear\Module\ModuleDefine;
use Exception; use Exception;
/** /**
* Translater tools. * @brief translater main tools class.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class Translater extends Settings class Translater extends Settings
{ {
/** @var array $modules List of modules we could work on */ /**
* List of modules we could work on.
*
* @var array<string, array<string, TranslaterModule>> $modules
*/
private $modules = []; private $modules = [];
/** /**
* translater instance * Construct translater instance.
* *
* @param boolean $full Also load modules * @param bool $full Also load modules
*/ */
public function __construct(bool $full = true) public function __construct(bool $full = true)
{ {
@ -48,33 +45,32 @@ class Translater extends Settings
/// @name modules methods /// @name modules methods
//@{ //@{
/** /**
* Load array of modules infos by type of modules * Load array of modules infos by type of modules.
*/ */
private function loadModules(): void private function loadModules(): void
{ {
$this->modules = ['theme' => [], 'plugin' => []]; $this->modules = ['theme' => [], 'plugin' => []];
if (!(dcCore::app()->themes instanceof dcThemes)) { if (App::themes()->isEmpty()) {
dcCore::app()->themes = new dcThemes(); App::themes()->loadModules(App::blog()->themesPath(), null);
dcCore::app()->themes->loadModules((string) dcCore::app()->blog?->themes_path, null);
} }
foreach ([ foreach ([
dcCore::app()->themes->getDefines(['state' => dcModuleDefine::STATE_ENABLED]), App::themes()->getDefines(['state' => ModuleDefine::STATE_ENABLED]),
dcCore::app()->plugins->getDefines(['state' => dcModuleDefine::STATE_ENABLED]), App::plugins()->getDefines(['state' => ModuleDefine::STATE_ENABLED]),
] as $modules) { ] as $modules) {
foreach ($modules as $define) { foreach ($modules as $define) {
$this->modules[$define->get('type')][$define->get('id')] = new TranslaterModule($this, $define); $this->modules[(string) $define->get('type')][(string) $define->get('id')] = new TranslaterModule($this, $define);
} }
} }
} }
/** /**
* Return array of modules infos by type of modules * Return array of modules infos by type of modules.
* *
* @param string $type The modules type * @param string $type The modules type
* *
* @return array The list of modules infos * @return array<string, TranslaterModule> The list of modules infos
*/ */
public function getModules(string $type = ''): array public function getModules(string $type = ''): array
{ {
@ -84,12 +80,12 @@ class Translater extends Settings
} }
/** /**
* Return module class of a particular module for a given type of module * Return module class of a particular module for a given type of module.
* *
* @param string $type The module type * @param string $type The module type
* @param string $id The module id * @param string $id The module id
* *
* @return TranslaterModule The TranslaterModule instance * @return TranslaterModule The TranslaterModule instance
*/ */
public function getModule(string $type, string $id): TranslaterModule public function getModule(string $type, string $id): TranslaterModule
{ {
@ -103,12 +99,12 @@ class Translater extends Settings
} }
/** /**
* Return module class of a particular module for a given type of module * Return module class of a particular module for a given type of module.
* *
* @param TranslaterModule $module TranslaterModule instance * @param TranslaterModule $module TranslaterModule instance
* @param string $lang The lang iso code * @param string $lang The lang iso code
* *
* @return TranslaterLang TranslaterLang instance or false * @return TranslaterLang TranslaterLang instance or false
*/ */
public function getLang(TranslaterModule $module, string $lang): TranslaterLang public function getLang(TranslaterModule $module, string $lang): TranslaterLang
{ {
@ -125,12 +121,13 @@ class Translater extends Settings
/// @name helper methods /// @name helper methods
//@{ //@{
/** /**
* Scan recursively a folder and return files and folders names * Scan recursively a folder and return files and folders names.
* *
* @param string $path The path to scan * @param string $path The path to scan
* @param string $dir Internal recursion * @param string $dir Internal recursion
* @param array $res Internal recursion * @param array<int, string> $res Internal recursion
* @return array List of path *
* @return array<int, string> List of path
*/ */
public static function scandir(string $path, string $dir = '', array $res = []): array public static function scandir(string $path, string $dir = '', array $res = []): array
{ {
@ -157,10 +154,11 @@ class Translater extends Settings
} }
/** /**
* Encode a string * Encode a string.
* *
* @param string $str The string to encode * @param string $str The string to encode
* @return string The encoded string *
* @return string The encoded string
*/ */
public static function encodeMsg(string $str): string public static function encodeMsg(string $str): string
{ {
@ -168,11 +166,12 @@ class Translater extends Settings
} }
/** /**
* Clean a po string * Clean a po string.
* *
* @param string $string The string to clean * @param string $string The string to clean
* @param boolean $reverse Un/escape string * @param bool $reverse Un/escape string
* @return string The cleaned string *
* @return string The cleaned string
*/ */
public static function poString(string $string, bool $reverse = false): string public static function poString(string $string, bool $reverse = false): string
{ {
@ -189,10 +188,11 @@ class Translater extends Settings
} }
/** /**
* Try if a file is a .po file * Try if a file is a po file.
* *
* @param string $file The path to test * @param string $file The path to test
* @return boolean Success *
* @return bool Success
*/ */
public static function isPoFile(string $file): bool public static function isPoFile(string $file): bool
{ {
@ -200,10 +200,11 @@ class Translater extends Settings
} }
/** /**
* Try if a file is a .lang.php file * Try if a file is a .lang.php file.
* *
* @param string $file The path to test * @param string $file The path to test
* @return boolean Success *
* @return bool Success
*/ */
public static function isLangphpFile(string $file): bool public static function isLangphpFile(string $file): bool
{ {
@ -211,13 +212,14 @@ class Translater extends Settings
} }
/** /**
* Check limit number of backup for a module * Check limit number of backup for a module.
* *
* @param string $id The module id * @param string $id The module id
* @param string $root The backups root * @param string $root The backups root
* @param integer $limit The backups limit * @param int $limit The backups limit
* @param boolean $throw Silently failed * @param bool $throw Silently failed
* @return boolean True if limit is riched *
* @return bool True if limit is riched
*/ */
public static function isBackupLimit(string $id, string $root, int $limit = 10, bool $throw = false): bool public static function isBackupLimit(string $id, string $root, int $limit = 10, bool $throw = false): bool
{ {
@ -249,13 +251,14 @@ class Translater extends Settings
} }
/** /**
* Extract messages from a php contents * Extract messages from a php contents.
* *
* support plurals * support plurals
* *
* @param string $content The contents * @param string $content The contents
* @param string $func The function name * @param string $func The function name
* @return array The messages *
* @return array<int<0, max>, array{0: array<int,string>, 1: int}> The messages
*/ */
public static function extractPhpMsgs(string $content, string $func = '__'): array public static function extractPhpMsgs(string $content, string $func = '__'): array
{ {
@ -308,11 +311,12 @@ class Translater extends Settings
} }
/** /**
* Extract messages from a tpl contents * Extract messages from a tpl contents.
* *
* @param string $content The contents * @param string $content The contents
* @param string $func The function name * @param string $func The function name
* @return array The messages *
* @return array<int<0, max>, array{0: array<int,string>, 1: int}> The messages
*/ */
public static function extractTplMsgs(string $content, string $func = 'tpl:lang'): array public static function extractTplMsgs(string $content, string $func = 'tpl:lang'): array
{ {

View File

@ -1,50 +1,56 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcModuleDefine; use Dotclear\App;
use Dotclear\Helper\File\Files; use Dotclear\Helper\File\Files;
use Dotclear\Helper\File\Path; use Dotclear\Helper\File\Path;
use Dotclear\Helper\L10n; use Dotclear\Helper\L10n;
use Dotclear\Module\ModuleDefine;
/**
* @brief translater lang tools class.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class TranslaterLang class TranslaterLang
{ {
/** @var string Lang code */ /**
public readonly string $code; * Lang name.
*
/** @var string Lang name */ * @var string $name
*/
public readonly string $name; public readonly string $name;
/** @var array Lang plural forms */ /**
* Lang plural forms.
*
* @var array<int, string> $plural
*/
public readonly array $plural; public readonly array $plural;
/** @var TranslaterModule TranslaterModule instance */ /**
private TranslaterModule $module; * Constructor.
*
public function __construct(TranslaterModule $module, string $lang) * @param TranslaterModule $module The module
{ * @param string $code The lang code
$this->module = $module; */
$this->code = $lang; public function __construct(
$this->name = L10n::getLanguageName($lang); private TranslaterModule $module,
$this->plural = explode(':', L10n::getLanguagePluralExpression($lang)); public readonly string $code
) {
$this->name = L10n::getLanguageName($code);
$this->plural = explode(':', L10n::getLanguagePluralExpression($code));
} }
/** /**
* Get a lang messages * Get a lang messages.
* *
* @return array The messages ids and translations * @return array<string, array<string, mixed>> The messages ids and translations
*/ */
public function getMessages(): array public function getMessages(): array
{ {
@ -59,7 +65,7 @@ class TranslaterLang
} }
# Add Dotclear str # Add Dotclear str
$dc_define = (new dcModuleDefine('dotclear'))->set('root', DC_ROOT); $dc_define = (new ModuleDefine('dotclear'))->set('root', App::config()->dotclearRoot());
$dc_module = new TranslaterModule($this->module->translater, $dc_define); $dc_module = new TranslaterModule($this->module->translater, $dc_define);
$dc_lang = new TranslaterLang($dc_module, $this->code); $dc_lang = new TranslaterLang($dc_module, $this->code);
$m_o_msgstrs['dotclear'] = $dc_lang->getMsgStrs(); $m_o_msgstrs['dotclear'] = $dc_lang->getMsgStrs();
@ -76,7 +82,7 @@ class TranslaterLang
# From str list # From str list
foreach ($m_msgstrs as $rs) { foreach ($m_msgstrs as $rs) {
if (!isset($res[$rs['msgid']])) { if (!is_string($rs['msgid']) || !isset($res[$rs['msgid']])) {
$res[$rs['msgid']]['files'][] = []; $res[$rs['msgid']]['files'][] = [];
$res[$rs['msgid']]['in_dc'] = false; $res[$rs['msgid']]['in_dc'] = false;
$res[$rs['msgid']]['o_msgstrs'] = []; $res[$rs['msgid']]['o_msgstrs'] = [];
@ -90,7 +96,7 @@ class TranslaterLang
# From others str list # From others str list
foreach ($m_o_msgstrs as $o_module => $o_msgstrs) { foreach ($m_o_msgstrs as $o_module => $o_msgstrs) {
foreach ($o_msgstrs as $rs) { foreach ($o_msgstrs as $rs) {
if (!isset($res[$rs['msgid']])) { if (!is_string($rs['msgid']) || !isset($res[$rs['msgid']])) {
continue; continue;
} }
@ -109,9 +115,9 @@ class TranslaterLang
} }
/** /**
* Get messages ids * Get messages ids.
* *
* @return array The messages ids * @return array<int, array<string, mixed>> The messages ids
*/ */
public function getMsgIds(): array public function getMsgIds(): array
{ {
@ -129,12 +135,11 @@ class TranslaterLang
} }
$contents = file_get_contents($this->module->root . '/' . $file); $contents = file_get_contents($this->module->root . '/' . $file);
$msgs = []; $msgs = [];
# php files
if ($extension == 'php') { if ($extension == 'php') {
# php files
$msgs = Translater::extractPhpMsgs((string) $contents); $msgs = Translater::extractPhpMsgs((string) $contents);
# tpl files
} elseif ($extension == 'html') { } elseif ($extension == 'html') {
# tpl files
$msgs = Translater::extractTplMsgs((string) $contents); $msgs = Translater::extractTplMsgs((string) $contents);
} }
foreach ($msgs as $msg) { foreach ($msgs as $msg) {
@ -153,15 +158,15 @@ class TranslaterLang
} }
/** /**
* Get messages translations * Get messages translations.
* *
* @return array The messages translations * @return array<int, array<string, string|array<int, string>>> The messages translations
*/ */
public function getMsgStrs(): array public function getMsgStrs(): array
{ {
$res = $exists = $scanned = []; $res = $exists = $scanned = [];
$langs = $this->module->getLangs(true); $langs = $this->module->getLangsPath();
if (!isset($langs[$this->code])) { if (!isset($langs[$this->code])) {
return $res; return $res;
} }

View File

@ -1,21 +1,10 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore; use Dotclear\App;
use dcModuleDefine;
use Dotclear\Helper\Date; use Dotclear\Helper\Date;
use Dotclear\Helper\File\Files; use Dotclear\Helper\File\Files;
use Dotclear\Helper\File\Path; use Dotclear\Helper\File\Path;
@ -23,46 +12,91 @@ use Dotclear\Helper\File\Zip\Unzip;
use Dotclear\Helper\File\Zip\Zip; use Dotclear\Helper\File\Zip\Zip;
use Dotclear\Helper\Html\Html; use Dotclear\Helper\Html\Html;
use Dotclear\Helper\L10n; use Dotclear\Helper\L10n;
use Dotclear\Module\ModuleDefine;
use Exception; use Exception;
/** /**
* Translater tools. * @brief translater module tools class.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class TranslaterModule class TranslaterModule
{ {
/** @var string Module id */ /**
* Module id.
*
* @var string $id
*/
public readonly string $id; public readonly string $id;
/** @var string Module type */ /**
* Module type.
*
* @var string $type
*/
public readonly string $type; public readonly string $type;
/** @var string Module name */ /**
* Module name.
*
* @var string $name
*/
public readonly string $name; public readonly string $name;
/** @var string Module author */ /**
* Module author.
*
* @var string $author
*/
public readonly string $author; public readonly string $author;
/** @var string Module version */ /**
* Module version.
*
* @var string $version
*/
public readonly string $version; public readonly string $version;
/** @var bool Module root writable */ /**
* Module root writable.
*
* @var bool $root_writable
*/
public readonly bool $root_writable; public readonly bool $root_writable;
/** @var string Module root (cleaned) */ /**
* Module root (cleaned).
*
* @var string $root
*/
public readonly string $root; public readonly string $root;
/** @var string Module locales root path */ /**
* Module locales root path.
*
* @var string $locales
*/
public readonly string $locales; public readonly string $locales;
/** @var Translater Translater instance */ /**
public readonly Translater $translater; * Backup file regexp.
*
/** @var string Backup file regexp */ * @var string $backup_file_regexp
*/
private $backup_file_regexp = '/^l10n-%s-(.*?)-[0-9]*?\.bck\.zip$/'; private $backup_file_regexp = '/^l10n-%s-(.*?)-[0-9]*?\.bck\.zip$/';
public function __construct(Translater $translater, dcModuleDefine $define) /**
{ * Constructor.
$this->translater = $translater; *
* @param Translater $translater The tanslater instance
* @param ModuleDefine $define The module define
*/
public function __construct(
public readonly Translater $translater,
ModuleDefine $define
) {
$this->id = $define->get('id'); $this->id = $define->get('id');
$this->type = $define->get('type'); $this->type = $define->get('type');
$this->name = $define->get('name'); $this->name = $define->get('name');
@ -76,10 +110,11 @@ class TranslaterModule
/// @name backup methods /// @name backup methods
//@{ //@{
/** /**
* Find backup folder of a module * Find backup folder of a module.
* *
* @param boolean $throw Silently failed * @param bool $throw Silently failed
* @return string|false The backup folder directory or false *
* @return string|false The backup folder directory or false
*/ */
public function getBackupRoot(bool $throw = false): string|false public function getBackupRoot(bool $throw = false): string|false
{ {
@ -93,7 +128,7 @@ class TranslaterModule
break; break;
case 'plugin': case 'plugin':
$exp = explode(PATH_SEPARATOR, DC_PLUGINS_ROOT); $exp = explode(PATH_SEPARATOR, App::config()->pluginsRoot());
$tmp = Path::real(array_pop($exp)); $tmp = Path::real(array_pop($exp));
if ($tmp !== false && is_writable($tmp)) { if ($tmp !== false && is_writable($tmp)) {
$dir = $tmp; $dir = $tmp;
@ -102,7 +137,7 @@ class TranslaterModule
break; break;
case 'public': case 'public':
$tmp = Path::real((string) dcCore::app()->blog?->public_path); $tmp = Path::real(App::blog()->publicPath());
if ($tmp !== false && is_writable($tmp)) { if ($tmp !== false && is_writable($tmp)) {
$dir = $tmp; $dir = $tmp;
} }
@ -110,7 +145,7 @@ class TranslaterModule
break; break;
case 'cache': case 'cache':
$tmp = Path::real(DC_TPL_CACHE); $tmp = Path::real(App::config()->cacheRoot());
if ($tmp !== false && is_writable($tmp)) { if ($tmp !== false && is_writable($tmp)) {
@mkDir($tmp . '/l10n'); @mkDir($tmp . '/l10n');
$dir = $tmp . '/l10n'; $dir = $tmp . '/l10n';
@ -138,12 +173,11 @@ class TranslaterModule
} }
/** /**
* Get a list of available backups * Get a list of available backups.
* *
* @param boolean $return_filename Return only filenames * @return array<string, array<string, array<string, string|array<string, string>>>> The module backups info
* @return array The module backups info
*/ */
public function getBackups(bool $return_filename = false): array public function getBackups(): array
{ {
$backup = $this->getBackupRoot(); $backup = $this->getBackupRoot();
if (!$backup) { if (!$backup) {
@ -162,26 +196,53 @@ class TranslaterModule
continue; continue;
} }
if ($return_filename) { $res[$m[1]][$file]['code'] = $m[1];
$res[] = $file; $res[$m[1]][$file]['name'] = L10n::getLanguageName($m[1]);
} else { $res[$m[1]][$file]['path'] = Path::info($backup . '/' . $file);
$res[$m[1]][$file]['code'] = $m[1]; $res[$m[1]][$file]['time'] = (string) filemtime($backup . '/' . $file);
$res[$m[1]][$file]['name'] = L10n::getLanguageName($m[1]); $res[$m[1]][$file]['size'] = (string) filesize($backup . '/' . $file);
$res[$m[1]][$file]['path'] = Path::info($backup . '/' . $file); $res[$m[1]][$file]['module'] = $this->id;
$res[$m[1]][$file]['time'] = filemtime($backup . '/' . $file);
$res[$m[1]][$file]['size'] = filesize($backup . '/' . $file);
$res[$m[1]][$file]['module'] = $this->id;
}
} }
return $res; return $res;
} }
/** /**
* Create a backup * Get a list of available backups filemnames.
* *
* @param string $lang The backup lang * @return array<int, string> The module backups info
* @return boolean True on success */
public function getBackupsFilename(): array
{
$backup = $this->getBackupRoot();
if (!$backup) {
return [];
}
$res = [];
$files = Translater::scandir($backup);
foreach ($files as $file) {
$is_backup = preg_match(sprintf($this->backup_file_regexp, preg_quote($this->id)), $file, $m);
if (is_dir($backup . '/' . $file)
|| !$is_backup
|| !L10n::isCode($m[1])
) {
continue;
}
$res[] = $file;
}
return $res;
}
/**
* Create a backup.
*
* @param string $lang The backup lang
*
* @return bool True on success
*/ */
public function createBackup(string $lang): bool public function createBackup(string $lang): bool
{ {
@ -226,10 +287,11 @@ class TranslaterModule
} }
/** /**
* Retore a backup * Retore a backup.
* *
* @param string $file The backup filename * @param string $file The backup filename
* @return boolean True on success *
* @return bool True on success
*/ */
public function restoreBackup(string $file): bool public function restoreBackup(string $file): bool
{ {
@ -257,10 +319,11 @@ class TranslaterModule
} }
/** /**
* Delete a module backup * Delete a module backup.
* *
* @param string $file The backup filename * @param string $file The backup filename
* @return boolean True on success *
* @return bool True on success
*/ */
public function deleteBackup(string $file): bool public function deleteBackup(string $file): bool
{ {
@ -288,10 +351,11 @@ class TranslaterModule
} }
/** /**
* Import a language pack * Import a language pack.
* *
* @param array $zip_file The uploaded file info * @param array<string, mixed> $zip_file The uploaded file info
* @return boolean True on success *
* @return bool True on success
*/ */
public function importPack(array $zip_file): bool public function importPack(array $zip_file): bool
{ {
@ -350,9 +414,9 @@ class TranslaterModule
} }
/** /**
* Export (to output) language pack * Export (to output) language pack.
* *
* @param array $langs Langs to export * @param array<int, string> $langs Langs to export
*/ */
public function exportPack(array $langs): void public function exportPack(array $langs): void
{ {
@ -414,11 +478,12 @@ class TranslaterModule
} }
/** /**
* Parse zip filename to module, lang info * Parse zip filename to module, lang info.
* *
* @param string $file The zip filename * @param string $file The zip filename
* @param boolean $throw Silently failed * @param bool $throw Silently failed
* @return array Array of file info *
* @return array<string, string> Array of file info
*/ */
public function parseZipFilename(string $file = '', bool $throw = false): array public function parseZipFilename(string $file = '', bool $throw = false): array
{ {
@ -454,12 +519,11 @@ class TranslaterModule
/// @name lang methods /// @name lang methods
//@{ //@{
/** /**
* List available langs of a module * List available langs of a module.
* *
* @param boolean $return_path Return path or name * @return array<string, string> The lang list
* @return array The lang list
*/ */
public function getLangs(bool $return_path = false): array public function getLangs(): array
{ {
$res = []; $res = [];
@ -475,20 +539,42 @@ class TranslaterModule
continue; continue;
} }
if ($return_path) { $res[$m[1]] = L10n::getLanguageName($m[1]); // Lang name
$res[$m[1]][] = $file; // Path }
} else {
$res[$m[1]] = L10n::getLanguageName($m[1]); // Lang name return $res;
}
/**
* List available langs path of a module.
*
* @return array<string, array<int, string>> The lang list
*/
public function getLangsPath(): array
{
$res = [];
$prefix = preg_match('/(' . preg_quote(My::LOCALES_FOLDER) . '(.*))$/', $this->locales) ? My::LOCALES_FOLDER : '';
$files = Translater::scandir($this->locales);
foreach ($files as $file) {
if (!preg_match('/.*?' . preg_quote(My::LOCALES_FOLDER) . '\/([^\/]*?)\/([^\/]*?)(.lang.php|.po)$/', $prefix . $file, $m)) {
continue;
} }
if (!L10n::isCode($m[1])) {
continue;
}
$res[$m[1]][] = $file; // Path
} }
return $res; return $res;
} }
/** /**
* List of used langs of a module * List of used langs of a module.
* *
* @return array The list of iso names and codes * @return array<string, string> The list of iso names and codes
*/ */
public function getUsedLangs(): array public function getUsedLangs(): array
{ {
@ -496,9 +582,9 @@ class TranslaterModule
} }
/** /**
* List of unsused langs of a module * List of unsused langs of a module.
* *
* @return array The list of iso names and codes * @return array<string, string> The list of iso names and codes
*/ */
public function getUnusedLangs(): array public function getUnusedLangs(): array
{ {
@ -506,11 +592,12 @@ class TranslaterModule
} }
/** /**
* Add a lang to a module * Add a lang to a module.
* *
* @param string $lang The lang id * @param string $lang The lang id
* @param string $from_lang The lang to copy from * @param string $from_lang The lang to copy from
* @return boolean True on success *
* @return bool True on success
*/ */
public function addLang(string $lang, string $from_lang = ''): bool public function addLang(string $lang, string $from_lang = ''): bool
{ {
@ -562,10 +649,10 @@ class TranslaterModule
} }
/** /**
* Update an existing lang * Update an existing lang.
* *
* @param string $lang The lang * @param string $lang The lang
* @param array $msgs The messages * @param array<string, mixed> $msgs The messages
*/ */
public function updLang(string $lang, array $msgs): void public function updLang(string $lang, array $msgs): void
{ {
@ -627,11 +714,12 @@ class TranslaterModule
} }
/** /**
* Delete a lang * Delete a lang.
* *
* @param string $lang The lang code * @param string $lang The lang code
* @param boolean $del_empty_dir Also remove empty locales dir * @param bool $del_empty_dir Also remove empty locales dir
* @return boolean True on success *
* @return bool True on success
*/ */
public function delLang(string $lang, bool $del_empty_dir = true): bool public function delLang(string $lang, bool $del_empty_dir = true): bool
{ {
@ -643,7 +731,7 @@ class TranslaterModule
)); ));
} }
$files = $this->getLangs(true); $files = $this->getLangsPath();
if (!isset($files[$lang])) { if (!isset($files[$lang])) {
throw new Exception(sprintf( throw new Exception(sprintf(
__('Failed to find language %s'), __('Failed to find language %s'),
@ -669,11 +757,11 @@ class TranslaterModule
} }
/** /**
* Construct and parse a .po file * Construct and parse a po file.
* *
* @param string $lang The lang code * @param string $lang The lang code
* @param string $group The lang group * @param string $group The lang group
* @param array $msgs The strings * @param array<int, mixed> $msgs The strings
*/ */
private function setPoContent(string $lang, string $group, array $msgs): void private function setPoContent(string $lang, string $group, array $msgs): void
{ {
@ -689,14 +777,14 @@ class TranslaterModule
$search = My::defaultUserInformations(); $search = My::defaultUserInformations();
$replace = []; $replace = [];
foreach ($search as $n) { foreach ($search as $n) {
$replace[] = dcCore::app()->auth?->getInfo('user_' . $n); $replace[] = App::auth()->getInfo('user_' . $n);
} }
$info = trim(str_replace($search, $replace, $this->translater->parse_userinfo)); $info = trim(str_replace($search, $replace, $this->translater->parse_userinfo));
if (!empty($info)) { if (!empty($info)) {
$content .= '# Author: ' . Html::escapeHTML($info) . "\n"; $content .= '# Author: ' . Html::escapeHTML($info) . "\n";
} }
} }
$content .= '# Translated with translater ' . dcCore::app()->plugins->moduleInfo(My::id(), 'version') . "\n\n"; $content .= '# Translated with translater ' . App::plugins()->moduleInfo(My::id(), 'version') . "\n\n";
} }
$content .= "msgid \"\"\n" . $content .= "msgid \"\"\n" .
"msgstr \"\"\n" . "msgstr \"\"\n" .
@ -704,7 +792,7 @@ class TranslaterModule
'"Project-Id-Version: ' . $this->id . ' ' . $this->version . '\n"' . "\n" . '"Project-Id-Version: ' . $this->id . ' ' . $this->version . '\n"' . "\n" .
'"POT-Creation-Date: \n"' . "\n" . '"POT-Creation-Date: \n"' . "\n" .
'"PO-Revision-Date: ' . date('c') . '\n"' . "\n" . '"PO-Revision-Date: ' . date('c') . '\n"' . "\n" .
'"Last-Translator: ' . dcCore::app()->auth?->getInfo('user_cn') . '\n"' . "\n" . '"Last-Translator: ' . App::auth()->getInfo('user_cn') . '\n"' . "\n" .
'"Language-Team: \n"' . "\n" . '"Language-Team: \n"' . "\n" .
'"MIME-Version: 1.0\n"' . "\n" . '"MIME-Version: 1.0\n"' . "\n" .
'"Content-Transfer-Encoding: 8bit\n"' . "\n" . '"Content-Transfer-Encoding: 8bit\n"' . "\n" .
@ -757,11 +845,11 @@ class TranslaterModule
} }
/** /**
* Construct and write a .lang.php file * Construct and write a .lang.php file.
* *
* @param string $lang The lang code * @param string $lang The lang code
* @param string $group The lang group * @param string $group The lang group
* @param array $msgs The strings * @param array<int, mixed> $msgs The strings
*/ */
private function setLangphpContent(string $lang, string $group, array $msgs): void private function setLangphpContent(string $lang, string $group, array $msgs): void
{ {
@ -781,14 +869,14 @@ class TranslaterModule
$search = My::defaultUserInformations(); $search = My::defaultUserInformations();
$replace = []; $replace = [];
foreach ($search as $n) { foreach ($search as $n) {
$replace[] = dcCore::app()->auth?->getInfo('user_' . $n); $replace[] = App::auth()->getInfo('user_' . $n);
} }
$info = trim(str_replace($search, $replace, $this->translater->parse_userinfo)); $info = trim(str_replace($search, $replace, $this->translater->parse_userinfo));
if (!empty($info)) { if (!empty($info)) {
$content .= '// Author: ' . Html::escapeHTML($info) . "\n"; $content .= '// Author: ' . Html::escapeHTML($info) . "\n";
} }
} }
$content .= '// Translated with Translater - ' . dcCore::app()->plugins->moduleInfo(My::id(), 'version') . "\n\n"; $content .= '// Translated with Translater - ' . App::plugins()->moduleInfo(My::id(), 'version') . "\n\n";
} }
L10n::generatePhpFileFromPo(implode(DIRECTORY_SEPARATOR, [$this->locales, $lang->code, $group]), $content); L10n::generatePhpFileFromPo(implode(DIRECTORY_SEPARATOR, [$this->locales, $lang->code, $group]), $content);

View File

@ -1,23 +1,19 @@
<?php <?php
/**
* @brief translater, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis & contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\translater; namespace Dotclear\Plugin\translater;
use dcCore;
use Dotclear\Core\Process; use Dotclear\Core\Process;
use Dotclear\Plugin\Uninstaller\Uninstaller; use Dotclear\Plugin\Uninstaller\Uninstaller;
/**
* @brief translater uninstall class.
* @ingroup translater
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Uninstall extends Process class Uninstall extends Process
{ {
public static function init(): bool public static function init(): bool
@ -27,7 +23,7 @@ class Uninstall extends Process
public static function process(): bool public static function process(): bool
{ {
if (!self::status() || !dcCore::app()->plugins->moduleExists('Uninstaller')) { if (!self::status()) {
return false; return false;
} }