12203 bug avec le format de language.json

This commit is contained in:
Fred Tempez 2023-02-04 17:39:50 +01:00
parent b491acb4e7
commit 42506dabfd
2 changed files with 100 additions and 83 deletions

View File

@ -19,10 +19,14 @@ class translate extends common
public static $actions = [ public static $actions = [
'index' => self::GROUP_ADMIN, 'index' => self::GROUP_ADMIN,
'copy' => self::GROUP_ADMIN, 'copy' => self::GROUP_ADMIN,
'add' => self::GROUP_ADMIN, // Ajouter une langue de contenu 'add' => self::GROUP_ADMIN,
'edit' => self::GROUP_ADMIN, // Éditer une langue de l'UI // Ajouter une langue de contenu
'locale' => self::GROUP_ADMIN, // Éditer une langue de contenu 'edit' => self::GROUP_ADMIN,
'delete' => self::GROUP_ADMIN, // Effacer une langue de contenu ou de l'interface // Éditer une langue de l'UI
'locale' => self::GROUP_ADMIN,
// Éditer une langue de contenu
'delete' => self::GROUP_ADMIN,
// Effacer une langue de contenu ou de l'interface
'content' => self::GROUP_VISITOR, 'content' => self::GROUP_VISITOR,
'update' => self::GROUP_ADMIN, 'update' => self::GROUP_ADMIN,
]; ];
@ -65,11 +69,11 @@ class translate extends common
// Jeton incorrect ou URl avec le code langue incorrecte // Jeton incorrect ou URl avec le code langue incorrecte
if ( if (
$this->getUrl(3) !== $_SESSION['csrf'] && $this->getUrl(3) !== $_SESSION['csrf'] &&
array_key_exists($lang, self::$languages) === false array_key_exists($lang, self::$languages) === false
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'translate',
'state' => false, 'state' => false,
'notification' => helper::translate('Action interdite') 'notification' => helper::translate('Action interdite')
]); ]);
@ -83,15 +87,15 @@ class translate extends common
$enumsStore = json_decode(helper::getUrlContents(common::ZWII_UI_URL . 'languages.json'), true); $enumsStore = json_decode(helper::getUrlContents(common::ZWII_UI_URL . 'languages.json'), true);
$enums = $this->getData(['languages']); $enums = $this->getData(['languages']);
$enums = array_merge($enums, [ $enums = array_merge($enums, [
$lang => $enumsStore[$lang] $lang => $enumsStore['languages'][$lang]
]); ]);
$response = (bool) $response && $this->setData(['languages', $enums]); $response = (bool) $response && $this->setData(['languages', $enums]);
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'translate',
'notification' => $response ? helper::translate('Copie terminée avec succès') : 'Copie terminée avec des erreurs', 'notification' => $response ? helper::translate('Copie terminée avec succès') : 'Copie terminée avec des erreurs',
'state' => $response 'state' => $response
]); ]);
} }
@ -111,19 +115,19 @@ class translate extends common
if ($copyFrom !== $toCreate) { if ($copyFrom !== $toCreate) {
// Création du dossier // Création du dossier
if (is_dir(self::DATA_DIR . $toCreate) === false) { // Si le dossier est déjà créé if (is_dir(self::DATA_DIR . $toCreate) === false) { // Si le dossier est déjà créé
$success = mkdir(self::DATA_DIR . $toCreate, 0755); $success = mkdir(self::DATA_DIR . $toCreate, 0755);
$success = mkdir(self::DATA_DIR . $toCreate . '/content', 0755); $success = mkdir(self::DATA_DIR . $toCreate . '/content', 0755);
} else { } else {
$success = true; $success = true;
} }
// Copier les données par défaut // Copier les données par défaut
$success = (copy(self::DATA_DIR . $copyFrom . '/locale.json', self::DATA_DIR . $toCreate . '/locale.json') === true && $success === true) ? true : false; $success = (copy(self::DATA_DIR . $copyFrom . '/locale.json', self::DATA_DIR . $toCreate . '/locale.json') === true && $success === true) ? true : false;
$success = (copy(self::DATA_DIR . $copyFrom . '/module.json', self::DATA_DIR . $toCreate . '/module.json') === true && $success === true) ? true : false; $success = (copy(self::DATA_DIR . $copyFrom . '/module.json', self::DATA_DIR . $toCreate . '/module.json') === true && $success === true) ? true : false;
$success = (copy(self::DATA_DIR . $copyFrom . '/page.json', self::DATA_DIR . $toCreate . '/page.json') === true && $success === true) ? true : false; $success = (copy(self::DATA_DIR . $copyFrom . '/page.json', self::DATA_DIR . $toCreate . '/page.json') === true && $success === true) ? true : false;
$success = ($this->copyDir(self::DATA_DIR . $copyFrom . '/content', self::DATA_DIR . $toCreate . '/content') === true && $success === true) ? true : false; $success = ($this->copyDir(self::DATA_DIR . $copyFrom . '/content', self::DATA_DIR . $toCreate . '/content') === true && $success === true) ? true : false;
// Enregistrer la langue // Enregistrer la langue
if ($success) { if ($success) {
$notification = sprintf(helper::translate('Données %s copiées vers %s'), self::$languages[$copyFrom], self::$languages[$toCreate]); $notification = sprintf(helper::translate('Données %s copiées vers %s'), self::$languages[$copyFrom], self::$languages[$toCreate]);
} else { } else {
$notification = helper::translate('Erreur de copie, vérifiez les permissions'); $notification = helper::translate('Erreur de copie, vérifiez les permissions');
} }
@ -133,10 +137,10 @@ class translate extends common
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => $notification, 'notification' => $notification,
'title' => 'Utilitaire de copie', 'title' => 'Utilitaire de copie',
'view' => 'index', 'view' => 'index',
'state' => $success 'state' => $success
]); ]);
} }
@ -179,7 +183,7 @@ class translate extends common
$messageLocale = ''; $messageLocale = '';
} }
self::$languagesInstalled[] = [ self::$languagesInstalled[] = [
template::flag($key, '20 %') . ' ' . $value . ' (' . $key . ')', template::flag($key, '20 %') . ' ' . $value . ' (' . $key . ')',
$messageLocale, $messageLocale,
template::button('translateContentLanguageLocaleEdit' . $key, [ template::button('translateContentLanguageLocaleEdit' . $key, [
'class' => file_exists(self::DATA_DIR . $key . '/locale.json') ? '' : ' disabled', 'class' => file_exists(self::DATA_DIR . $key . '/locale.json') ? '' : ' disabled',
@ -214,13 +218,14 @@ class translate extends common
// Langues disponibles en ligne // Langues disponibles en ligne
$storeUI = json_decode(helper::getUrlContents(common::ZWII_UI_URL . 'languages.json'), true); $storeUI = json_decode(helper::getUrlContents(common::ZWII_UI_URL . 'languages.json'), true);
$storeUI = $storeUI['languages'];
// Construction du tableau à partir des langues disponibles dans le store // Construction du tableau à partir des langues disponibles dans le store
foreach ($installedUI as $file => $value) { foreach ($installedUI as $file => $value) {
// La langue est-elle référencée ? // La langue est-elle référencée ?
if (array_key_exists(basename($file, '.json'), $installedUI)) { if (array_key_exists(basename($file, '.json'), $installedUI)) {
// La langue est déjà installée // La langue est déjà installée
self::$languagesUiInstalled[$file] = [ self::$languagesUiInstalled[$file] = [
template::flag($file, '20 %') . ' ' . self::$languages[$file], template::flag($file, '20 %') . ' ' . self::$languages[$file],
$value['version'], $value['version'],
helper::dateUTF8('%d/%m/%Y', $value['date']), helper::dateUTF8('%d/%m/%Y', $value['date']),
@ -246,26 +251,28 @@ class translate extends common
]), ]),
]; ];
} }
// Construction du tableau à partir des langues disponibles dans le store }
foreach ($storeUI as $file => $value) { // Construction du tableau à partir des langues disponibles dans le store
// La langue est-elle installée ? foreach ($storeUI as $file => $value) {
if (array_key_exists($file, $installedUI) === false) {
self::$languagesStore[$file] = [ // La langue est-elle installée ?
template::flag($file, '20 %') . ' ' . self::$languages[$file], if (array_key_exists($file, $installedUI) === false) {
$value['version'], self::$languagesStore[$file] = [
helper::dateUTF8('%d/%m/%Y', $value['date']), template::flag($file, '20 %') . ' ' . self::$languages[$file],
'', $value['version'],
template::button('translateContentLanguageUIDownload' . $file, [ helper::dateUTF8('%d/%m/%Y', $value['date']),
'class' => 'buttonGreen', '',
'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file . '/' . $_SESSION['csrf'], template::button('translateContentLanguageUIDownload' . $file, [
'value' => template::ico('shopping-basket'), 'class' => 'buttonGreen',
'help' => 'Installer', 'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file . '/' . $_SESSION['csrf'],
]) 'value' => template::ico('shopping-basket'),
]; 'help' => 'Installer',
} ])
];
} }
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Multilingue'), 'title' => helper::translate('Multilingue'),
@ -288,7 +295,7 @@ class translate extends common
$lang = $this->getInput('translateAddContent'); $lang = $this->getInput('translateAddContent');
// Stockage dans un sous-dossier localisé // Stockage dans un sous-dossier localisé
if (!file_exists(self::DATA_DIR . $lang)) { if (!file_exists(self::DATA_DIR . $lang)) {
mkdir(self::DATA_DIR . $lang, 0755); mkdir(self::DATA_DIR . $lang, 0755);
} }
// Valeurs en sortie // Valeurs en sortie
@ -329,7 +336,7 @@ class translate extends common
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'translate',
'state' => false, 'state' => false,
'notification' => helper::translate('Action interdite') 'notification' => helper::translate('Action interdite')
]); ]);
@ -347,17 +354,17 @@ class translate extends common
'page302' => $this->getInput('localePage302'), 'page302' => $this->getInput('localePage302'),
'legalPageId' => $this->getInput('localeLegalPageId'), 'legalPageId' => $this->getInput('localeLegalPageId'),
'searchPageId' => $this->getInput('localeSearchPageId'), 'searchPageId' => $this->getInput('localeSearchPageId'),
'searchPageLabel' => empty($this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT)) ? 'Rechercher' : $this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT), 'searchPageLabel' => empty($this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT)) ? 'Rechercher' : $this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT),
'legalPageLabel' => empty($this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT)) ? 'Mentions légales' : $this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT), 'legalPageLabel' => empty($this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT)) ? 'Mentions légales' : $this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT),
'sitemapPageLabel' => empty($this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT)) ? 'Plan du site' : $this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT), 'sitemapPageLabel' => empty($this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT)) ? 'Plan du site' : $this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT),
'metaDescription' => $this->getInput('localeMetaDescription', helper::FILTER_STRING_LONG, true), 'metaDescription' => $this->getInput('localeMetaDescription', helper::FILTER_STRING_LONG, true),
'title' => $this->getInput('localeTitle', helper::FILTER_STRING_SHORT, true), 'title' => $this->getInput('localeTitle', helper::FILTER_STRING_SHORT, true),
'cookies' => [ 'cookies' => [
// Les champs sont obligatoires si l'option consentement des cookies est active // Les champs sont obligatoires si l'option consentement des cookies est active
'mainLabel' => $this->getInput('localeCookiesZwiiText', helper::FILTER_STRING_LONG, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)), 'mainLabel' => $this->getInput('localeCookiesZwiiText', helper::FILTER_STRING_LONG, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
'titleLabel' => $this->getInput('localeCookiesTitleText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)), 'titleLabel' => $this->getInput('localeCookiesTitleText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
'linkLegalLabel' => $this->getInput('localeCookiesLinkMlText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)), 'linkLegalLabel' => $this->getInput('localeCookiesLinkMlText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
'cookiesFooterText' => $this->getInput('localeCookiesFooterText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)), 'cookiesFooterText' => $this->getInput('localeCookiesFooterText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
'buttonValidLabel' => $this->getInput('localeCookiesButtonText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)) 'buttonValidLabel' => $this->getInput('localeCookiesButtonText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN))
] ]
] ]
@ -385,7 +392,7 @@ class translate extends common
// La locale est-elle celle de la langue de l'UI ? // La locale est-elle celle de la langue de l'UI ?
if ($lang === self::$i18nUI) { if ($lang === self::$i18nUI) {
self::$locales[$lang]['locale'] = $this->getData(['locale']); self::$locales[$lang]['locale'] = $this->getData(['locale']);
} else { } else {
// Lire les locales sans passer par les méthodes // Lire les locales sans passer par les méthodes
self::$locales[$lang] = json_decode(file_get_contents(self::DATA_DIR . $lang . '/locale.json'), true); self::$locales[$lang] = json_decode(file_get_contents(self::DATA_DIR . $lang . '/locale.json'), true);
@ -402,7 +409,7 @@ class translate extends common
} }
} }
self::$orphansList = $this->getData(['page']); self::$orphansList = $this->getData(['page']);
foreach (self::$orphansList as $page => $pageId) { foreach (self::$orphansList as $page => $pageId) {
if ( if (
$this->getData(['page', $page, 'block']) === 'bar' || $this->getData(['page', $page, 'block']) === 'bar' ||
@ -425,14 +432,14 @@ class translate extends common
*/ */
public function edit() public function edit()
{ {
$lang = $this->getUrl(2); $lang = $this->getUrl(2);
// Jeton incorrect ou URl avec le code langue incorrecte // Jeton incorrect ou URl avec le code langue incorrecte
if ( if (
array_key_exists($lang, self::$languages) === false array_key_exists($lang, self::$languages) === false
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'translate',
'state' => false, 'state' => false,
'notification' => helper::translate('Action interdite') 'notification' => helper::translate('Action interdite')
]); ]);
@ -451,10 +458,14 @@ class translate extends common
file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX); file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
// Mettre à jour le descripteur // Mettre à jour le descripteur
$this->setData(['languages', $lang, [ $this->setData([
'version' => $this->getInput('translateEditVersion'), 'languages',
'date' => $this->getInput('translateEditDate', helper::FILTER_DATETIME), $lang,
]]); [
'version' => $this->getInput('translateEditVersion'),
'date' => $this->getInput('translateEditDate', helper::FILTER_DATETIME),
]
]);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
@ -493,7 +504,7 @@ class translate extends common
// Articles en fonction de la pagination // Articles en fonction de la pagination
for ($i = $pagination['first']; $i < $pagination['last']; $i++) { for ($i = $pagination['first']; $i < $pagination['last']; $i++) {
self::$dialogues[$i] = $dialogues[$i]; self::$dialogues[$i] = $dialogues[$i];
} }
// Valeurs en sortie // Valeurs en sortie
@ -520,13 +531,14 @@ class translate extends common
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'translate',
'state' => false, 'state' => false,
'notification' => helper::translate('Action interdite') 'notification' => helper::translate('Action interdite')
]); ]);
} }
switch ($target) { switch ($target) {
case 'locale': case 'locale':
$success = false;
// Effacement d'une site dans une langue // Effacement d'une site dans une langue
if (is_dir(self::DATA_DIR . $lang) === true) { if (is_dir(self::DATA_DIR . $lang) === true) {
$success = $this->removeDir(self::DATA_DIR . $lang); $success = $this->removeDir(self::DATA_DIR . $lang);
@ -534,22 +546,23 @@ class translate extends common
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'translate',
'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'), 'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'),
'state' => $success 'state' => $success
]); ]);
break; break;
case 'ui': case 'ui':
$success = false;
// Effacement d'une langue de l'interface // Effacement d'une langue de l'interface
if (file_exists(self::I18N_DIR . $lang . '.json') === true) { if (file_exists(self::I18N_DIR . $lang . '.json') === true) {
$this->deleteData(['languages', $lang]);
$success = unlink(self::I18N_DIR . $lang . '.json'); $success = unlink(self::I18N_DIR . $lang . '.json');
} }
// Effacer la langue dans la base // Effacer la langue dans la base
$this->deleteData(['languages', $lang]);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'translate',
'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'), 'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'),
'state' => $success 'state' => $success
]); ]);
break; break;
@ -574,11 +587,12 @@ class translate extends common
* déjà initialisée * déjà initialisée
* fait partie des lnagues installées * fait partie des lnagues installées
*/ */
if ( $this->getInput('ZWII_CONTENT') !== $lang if (
$this->getInput('ZWII_CONTENT') !== $lang
&& &&
is_dir(self::DATA_DIR . $lang) is_dir(self::DATA_DIR . $lang)
&& &&
array_key_exists($lang, self::$languages) === true array_key_exists($lang, self::$languages) === true
) { ) {
// Nettoyer le cookie // Nettoyer le cookie
@ -589,7 +603,7 @@ class translate extends common
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . $this->getData(['locale', $this->getUrl(2), 'homePageId']) 'redirect' => helper::baseUrl() . $this->getData(['locale', $this->getUrl(2), 'homePageId'])
]); ]);
} }
@ -623,4 +637,4 @@ class translate extends common
} }
return ($enums); return ($enums);
} }
} }

View File

@ -9,12 +9,12 @@
</div> </div>
<div class="col1"> <div class="col1">
<?php /**echo template::button('translateHelp', [ <?php /**echo template::button('translateHelp', [
'href' => 'https://doc.zwiicms.fr/prise-en-charge-des-langues-etrangeres', 'href' => 'https://doc.zwiicms.fr/prise-en-charge-des-langues-etrangeres',
'target' => '_blank', 'target' => '_blank',
'value' => template::ico('help'), 'value' => template::ico('help'),
'class' => 'buttonHelp', 'class' => 'buttonHelp',
'help' => 'Consulter l\'aide en ligne' 'help' => 'Consulter l\'aide en ligne'
]);*/ ?> ]);*/?>
</div> </div>
</div> </div>
@ -34,22 +34,24 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Langues installées'); ?> <h4>
<?php echo helper::translate('Langues installées'); ?>
</h4> </h4>
<?php if ($module::$languagesUiInstalled) : ?> <?php if ($module::$languagesUiInstalled): ?>
<?php echo template::table([2, 1, 1, 4, 1, 1, 1], $module::$languagesUiInstalled, ['Langues', 'Version', 'Date', '', '', '', '']); ?> <?php echo template::table([2, 1, 1, 4, 1, 1, 1], $module::$languagesUiInstalled, ['Langues', 'Version', 'Date', '', '', '', '']); ?>
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
<div class="row"> </div>
<div class="col12"> <div class="row">
<div class="block"> <div class="col12">
<h4><?php echo helper::translate('Catalogue'); ?> <div class="block">
</h4> <h4>
<?php if ($module::$languagesStore) : ?> <?php echo helper::translate('Catalogue'); ?>
<?php echo template::table([2, 1, 2, 6, 1], $module::$languagesStore, ['Langues', 'Version', 'Date', '', '']); ?> </h4>
<?php endif; ?> <?php if ($module::$languagesStore): ?>
</div> <?php echo template::table([2, 1, 2, 6, 1], $module::$languagesStore, ['Langues', 'Version', 'Date', '', '']); ?>
<?php endif; ?>
</div> </div>
</div> </div>
</div> </div>
@ -64,7 +66,7 @@
<div class="col4 offset2"> <div class="col4 offset2">
<?php echo template::button('translateButtonCopyContent', [ <?php echo template::button('translateButtonCopyContent', [
'href' => helper::baseUrl() . 'translate/copy', 'href' => helper::baseUrl() . 'translate/copy',
'ico' =>'docs', 'ico' => 'docs',
'disabled' => $module::$siteCopy, 'disabled' => $module::$siteCopy,
'value' => 'Copie de contenus localisés' 'value' => 'Copie de contenus localisés'
]); ?> ]); ?>
@ -86,11 +88,12 @@
<h4> <h4>
<?php echo helper::translate('Langues installées'); ?> <?php echo helper::translate('Langues installées'); ?>
</h4> </h4>
<?php if ($module::$languagesInstalled) : ?> <?php if ($module::$languagesInstalled): ?>
<?php echo template::table([2, 6, 1, 1], $module::$languagesInstalled, ['Langues', '', '', '']); ?> <?php echo template::table([2, 6, 1, 1], $module::$languagesInstalled, ['Langues', '', '', '']); ?>
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<?php echo template::formClose(); ?> <?php echo template::formClose(); ?>