full rework (in progress) see changelog

This commit is contained in:
Jean-Christian Denis 2021-09-25 01:58:59 +02:00
parent bdb4b6d865
commit 174e7a4090
Signed by: JcDenis
GPG key ID: 1B5B8C5B90B6C951
16 changed files with 1962 additions and 3647 deletions

View file

@ -1,9 +1,13 @@
2021.09.02.1 - dev
- [ ] help translation
- [ ] source translation
- [ ] fix constante for official modules
- [ ] fix third-party API (all are broken)
- [ ] add dashboard icon
- [ ] fix third-party API (temp remoed)
- [ ] add support for plural (.po ok)
- add dashboard icon
- fix constante for official modules
- fix superadmin permissions
- remove modules list tab and add button to existing lists
- remove multi-modules import/export
2021.09.02
- clean up code and fix typo

View file

@ -15,21 +15,16 @@ if (!defined('DC_CONTEXT_ADMIN')) {
return;
}
$core->blog->settings->addNamespace('translater');
$core->addBehavior('adminModulesListGetActions', ['translaterAdminBehaviors', 'adminModulesGetActions']);
$core->addBehavior('adminModulesListDoActions', ['translaterAdminBehaviors', 'adminModulesDoActions']);
$core->addBehavior('adminDashboardFavorites', ['translaterAdminBehaviors', 'adminDashboardFavorites']);
$core->addBehavior('addTranslaterProposalTool', ['translaterAdminBehaviors', 'addGoogleProposalTool']);
$core->addBehavior('addTranslaterProposalTool', ['translaterAdminBehaviors', 'addYahooProposalTool']);
$core->addBehavior('addTranslaterProposalTool', ['translaterAdminBehaviors', 'addMicrosoftProposalTool']);
$core->rest->addFunction('getProposal', ['translaterRest', 'getProposal']);
$_menu['Plugins']->addItem(
__('Translater'),
$core->adminurl->get('admin.plugin.translater'),
$core->adminurl->get('translater'),
dcPage::getPF('translater/icon.png'),
preg_match(
'/' . preg_quote($core->adminurl->get('admin.plugin.translater')) . '(&.*)?$/',
'/' . preg_quote($core->adminurl->get('translater')) . '(&.*)?$/',
$_SERVER['REQUEST_URI']
),
$core->auth->isSuperAdmin()
@ -37,6 +32,23 @@ $_menu['Plugins']->addItem(
class translaterAdminBehaviors
{
/** @var dcTranlsater dcTranslater instance */
private static $translater = null;
/**
* Create instance of dcTranslater once
*
* @param dCore $core dcCore instance
* @return dctranslater dcTranslater instance
*/
private static function translater($core)
{
if (!(self::$translater instanceof dcTranslater)) {
self::$translater = new dcTranslater($core);
}
return self::$translater;
}
/**
* Add button to go to module translation
*
@ -48,7 +60,7 @@ class translaterAdminBehaviors
public static function adminModulesGetActions(adminModulesList $list, string $id, array $prop): ?string
{
if ($list->getList() != $prop['type'] . '-activate'
|| !$list->core->blog->settings->translater->get('translater_' . $prop['type'] . '_menu')
|| !self::translater($list->core)->getSetting($prop['type'] . '_menu')
|| !$list->core->auth->isSuperAdmin()
) {
return null;
@ -74,7 +86,7 @@ class translaterAdminBehaviors
}
$list->core->adminurl->redirect(
'admin.plugin.translater',
'translater',
['part' => 'module', 'type' => $type, 'module' => key($_POST['translater'])],
'#module-lang'
);
@ -90,40 +102,10 @@ class translaterAdminBehaviors
{
$favs->register('translater', [
'title' => __('Translater'),
'url' => $core->adminurl->get('admin.plugin.translater'),
'url' => $core->adminurl->get('translater'),
'small-icon' => urldecode(dcPage::getPF('translater/icon.png')),
'large-icon' => urldecode(dcPage::getPF('translater/icon-big.png')),
'permissions' => $core->auth->isSuperAdmin()
]);
}
/**
* Register Google Translater tools in translate
*
* @param translaterProposals $proposal translaterProposals instance
*/
public static function addGoogleProposalTool(translaterProposals $proposal)
{
$proposal->addTool('googleProposalTool');
}
/**
* Register Yahoo Babelfish tools in translater
*
* @param translaterProposals $proposal translaterProposals instance
*/
public static function addYahooProposalTool(translaterProposals $proposal)
{
$proposal->addTool('yahooProposalTool');
}
/**
* Register Microsoft Bing tools in translater
*
* @param translaterProposals $proposal translaterProposals instance
*/
public static function addMicrosoftProposalTool(translaterProposals $proposal)
{
$proposal->addTool('microsoftProposalTool');
}
}

View file

@ -15,148 +15,89 @@ if (!defined('DC_CONTEXT_MODULE')) {
return null;
}
$redir = empty($_REQUEST['redir']) ?
$list->getURL() . '#plugins' : $_REQUEST['redir'];
# -- Get settings --
$core->blog->settings->addNamespace('translater');
$s = $core->blog->settings->translater;
$translater = new dcTranslater($core);
$combo_backup_limit = [
5 => 5,
10 => 10,
15 => 15,
20 => 20,
40 => 40,
60 => 60
];
$combo_backup_folder = [
'module' => __('locales folders of each module'),
'plugin' => __('plugins folder root'),
'public' => __('public folder root'),
'cache' => __('cache folder of Dotclear'),
'translater' =>__('locales folder of translater')
];
$combo_start_page = [
'modules_plugin' => __('Plugins'),
'modules_theme' => __('Themes'),
'pack' => __('Import/Export')
];
# -- Set settings --
if (!empty($_POST['save'])) {
try {
if (empty($_POST['translater_write_po'])
&& empty($_POST['translater_write_langphp'])) {
throw new Exception('You must choose one file format at least');
}
foreach($translater->getDefaultSettings() as $k => $v) {
$translater->setSetting($k, (isset($_POST['translater_' . $k]) ? $_POST['translater_' . $k] : ''));
}
foreach($translater->proposal->getTools() AS $k => $v) {
$v->save();
}
dcPage::addSuccessNotice(
__('Configuration has been successfully updated.')
try {
if (empty($_POST['write_po']) && empty($_POST['write_langphp'])) {
throw new Exception(
__('You must at least choose one file format to write')
);
http::redirect(
$list->getURL('module=translater&conf=1&redir=' .
$list->getRedir())
);
} catch (Exception $e) {
$core->error->add(sprintf($errors[$action], $e->getMessage()));
}
}
# -- Display form --
echo '
<div class="fieldset">
<h4>' . __('Translation') . '</h4>
<p><label class="classic">' .
form::checkbox('translater_write_po', '1' ,$translater->write_po) . '
' . __('Write .po files') . '</label></p>
<p><label class="classic">' .
form::checkbox('translater_write_langphp', '1', $translater->write_langphp) . '
' . __('Write .lang.php files') . '</label></p>
<p><label class="classic">' .
form::checkbox('translater_scan_tpl', '1', $translater->scan_tpl) . '
' . __('Translate also strings of template files') . '</label></p>
<p><label class="classic">' .
form::checkbox('translater_parse_nodc', '1', $translater->parse_nodc) . '
' . __('Translate only unknow strings') . '</label></p>
<p><label class="classic">' .
form::checkbox('translater_hide_default', '1', $translater->hide_default) . '
' . __('Hide default modules of Dotclear') . '</label></p>
<p><label class="classic">' .
form::checkbox('translater_parse_comment', '1', $translater->parse_comment) . '
' . __('Write comments in files') . '</label></p>
<p><label class="classic">' .
form::checkbox('translater_parse_user', '1', $translater->parse_user) . '
' . __('Write informations about author in files') . '</label><br />
' . form::field('translater_parse_userinfo', 65, 255, $translater->parse_userinfo) . '</p>
</div>
<div class="fieldset">
<h4>' . __('Tools') . '</h4>
<p><label class="classic">' . __('Default language of l10n source:') . '<br />' .
form::combo('translater_proposal_lang',
array_flip($translater->getIsoCodes()), $translater->proposal_lang) . '</label></p>
<h4>' . __('Select and configure the tool to use to translate strings:') . '</h4>';
foreach($translater->proposal->getTools() AS $k => $v) {
$form = $v->form();
echo '
<dd>
<dt><label class="classic">' .
form::radio('translater_proposal_tool', $k, $k == $translater->proposal_tool) . '
' . $v->getDesc() . '</label></dt><dd>' .
(empty($form) ?
'<p>' . sprintf(__('Nothing to configure for %s tool . '), $v->getName()) . '</p>' :
$form
) . '</dd></dl>';
foreach($translater->getDefaultSettings() as $k => $v) {
$translater->setSetting($k, (isset($_POST[$k]) ? $_POST[$k] : ''));
}
dcPage::addSuccessNotice(
__('Configuration successfully updated.')
);
$core->adminurl->redirect(
'admin.plugins',
['module' => 'translater', 'conf' => 1, 'redir' => $list->getRedir()]
);
} catch (Exception $e) {
$core->error->add($e->getMessage());
}
}
echo '
<div class="fieldset"><h4>' . __('Translation') . '</h4>
<p><label for="write_po">' .
form::checkbox('write_po', '1' ,$translater->write_po) .
__('Write .po files') . '</label></p>
<p><label for="write_langphp">' .
form::checkbox('write_langphp', '1', $translater->write_langphp) .
__('Write .lang.php files') . '</label></p>
<p><label for="scan_tpl">' .
form::checkbox('scan_tpl', '1', $translater->scan_tpl) .
__('Translate also strings of template files') . '</label></p>
<p><label for="parse_nodc">' .
form::checkbox('parse_nodc', '1', $translater->parse_nodc) .
__('Translate only unknow strings') . '</label></p>
<p><label for="hide_default">' .
form::checkbox('hide_default', '1', $translater->hide_default) .
__('Hide default modules of Dotclear') . '</label></p>
<p><label for="parse_comment">' .
form::checkbox('parse_comment', '1', $translater->parse_comment) .
__('Write comments in files') . '</label></p>
<p><label for="parse_user">' .
form::checkbox('parse_user', '1', $translater->parse_user) .
__('Write informations about author in files') . '</label></p>
<p><label for="parse_userinfo">' . __('User info:') . '</label>' .
form::field('parse_userinfo', 65, 255, $translater->parse_userinfo) . '</p>
<p class="form-note">' . sprintf(
__('Following informations can be used: %s '), implode(', ', $translater::$allowed_user_informations)) . '
</p>
</div>
<div class="fieldset">
<h4>' . __('Import/Export') . '</h4>
<p><label class="classic">' .
form::checkbox('translater_import_overwrite', '1', $translater->import_overwrite) . '
' . __('Overwrite existing languages') . '</label></p>
<p><label class="classic">' . __('Name of exported package') . '<br />
' . form::field('translater_export_filename', 65, 255, $translater->export_filename) . '</label></p>
<div class="fieldset"><h4>' . __('Import/Export') . '</h4>
<p><label for="import_overwrite">' .
form::checkbox('import_overwrite', '1', $translater->import_overwrite) .
__('Overwrite existing languages') . '</label></p>
<p><label for="export_filename">' . __('Name of exported package:') . '</label>' .
form::field('export_filename', 65, 255, $translater->export_filename) . '</p>
</div>
<div class="fieldset">
<h4>' . __('Backups') . '</h4>
<p><label class="classic">' .
form::checkbox('translater_backup_auto', '1', $translater->backup_auto) . '
' . __('Make backups when changes are made') . '</label></p>
<p><label class="classic">' . sprintf(__('Limit backups to %s files per module'),
form::combo('translater_backup_limit',
array_flip($combo_backup_limit), $translater->backup_limit)) . '</label></p>
<p><label class="classic">' . sprintf(__('Store backups in %s'),
form::combo('translater_backup_folder',
array_flip($combo_backup_folder), $translater->backup_folder)) . '</label></p>
<div class="fieldset"><h4>' . __('Backups') . '</h4>
<p><label for="backup_auto">' .
form::checkbox('backup_auto', '1', $translater->backup_auto) .
__('Make backups when changes are made') . '</label></p>
<p><label for="backup_limit" class="classic">' . sprintf(__('Limit backups to %s files per module'),
form::number('backup_limit', ['min' => 0, 'max' => 50, 'default' => $translater->backup_limit])) . '</label></p>
<p><label for="backup_folder">' . __('Store backups in:') . '</label>' .
form::combo('backup_folder', $translater::$allowed_backup_folders, $translater->backup_folder) . '</p>
</div>
<div class="fieldset">
<h4>' . __('Behaviors') . '</h4>
<p><label class="classic">' . __('Default start menu:') . '<br />' .
form::combo('translater_start_page',
array_flip($combo_start_page), $translater->start_page) . '</label></p>
<p><label class="classic">' .
form::checkbox('translater_plugin_menu', '1', $translater->plugin_menu) . '
' . __('Enable menu on extensions page') . '</label></p>
<p><label class="classic">' .
form::checkbox('translater_theme_menu', '1', $translater->theme_menu) . '
' . __('Enable menu on themes page') . '</label></p>
</div>
';
<div class="fieldset"><h4>' . __('Behaviors') . '</h4>
<p><label for="start_page">' . __('Default start menu:') . '</label>' .
form::combo('start_page',[
__('Plugins') => 'plugin',
__('Themes') => 'theme',
__('Home') => '-'
], $translater->start_page) . '</p>
<p><label for="plugin_menu">' .
form::checkbox('plugin_menu', '1', $translater->plugin_menu) .
__('Enable menu on extensions page') . '</label></p>
<p><label for="theme_menu">' .
form::checkbox('theme_menu', '1', $translater->theme_menu) .
__('Enable menu on themes page') . '</label></p>
</div>';

View file

@ -15,36 +15,19 @@ if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
$s = [
['translater_plugin_menu', 0, 'boolean', 'Put a link in plugins page'],
['translater_theme_menu', 0,'boolean', 'Put a link in themes page'],
['translater_backup_auto', 1,'boolean', 'Make a backup of languages old files when there are modified'],
['translater_backup_limit', 20,'string', 'Maximum backups per module'],
['translater_backup_folder', 'module',' string', 'In which folder to store backups'],
['translater_start_page', 'setting,', 'string', 'Page to start on'],
['translater_write_po', 1, 'boolean', 'Write .po languages files'],
['translater_write_langphp', 1, 'boolean', 'Write .lang.php languages files'],
['translater_scan_tpl', 0, 'boolean', 'Translate strings of templates files'],
['translater_parse_nodc', 1, 'boolean', 'Translate only untranslated strings of Dotclear'],
['translater_hide_default', 1, 'boolean', 'Hide default modules of Dotclear'],
['translater_parse_comment', 1, 'boolean', 'Write comments and strings informations in lang files'],
['translater_parse_user', 1,'boolean', 'Write inforamtions about author in lang files'],
['translater_parse_userinfo', 'displayname, email', 'string','Type of informations about user to write'],
['translater_import_overwrite', 0, 'boolean', 'Overwrite existing languages when import packages'],
['translater_export_filename', 'type-module-l10n-timestamp', 'string','Name of files of exported package'],
['translater_proposal_tool', 'google', 'string', 'Id of default tool for proposed translation'],
['translater_proposal_lang', 'en', 'string', 'Default source language for proposed translation']
];
try {
if (version_compare($core->getVersion($id), $this->moduleInfo($id, 'version'), '>=')) {
return null;
}
$core->blog->settings->addNamespace('translater');
$t = new dcTranslater($core);
$s = $t->getDefaultSettings();
foreach($s as $v) {
$core->blog->settings->translater->put($v[0], $v[1], $v[2], $v[3], false, true);
$t->setSetting($v[0], $v[1], false);
}
$core->setVersion($id, $this->moduleInfo($id, 'version'));
return true;
} catch (Exception $e) {
$core->error->add($e->getMessage());

View file

@ -17,10 +17,9 @@ if (!defined('DC_RC_PATH')) {
$d = dirname(__FILE__) . '/inc/';
$__autoload['dcTranslater'] = $d . 'class.dc.translater.php';
$__autoload['translaterRest'] = $d . 'class.translater.rest.php';
$__autoload['translaterProposals'] = $d . 'class.translater.proposals.php';
$__autoload['dcTranslater'] = $d . 'class.dc.translater.php';
$__autoload['dcTranslaterModule'] = $d . 'class.dc.translater.module.php';
$__autoload['dcTranslaterLang'] = $d . 'class.dc.translater.lang.php';
$__autoload['translaterRest'] = $d . 'class.translater.rest.php';
$__autoload['translaterProposalTool'] = $d . 'lib.translater.proposal.php';
$__autoload['googleProposalTool'] = $d . 'lib.translater.google.php';
$__autoload['microsoftProposalTool'] = $d . 'lib.translater.microsoft.php';
$core->adminurl->register('translater', 'plugin.php', ['p' => 'translater']);

1
css/translater.css Normal file
View file

@ -0,0 +1 @@
.addfield, .togglelist { border: none; }

View file

Before

Width:  |  Height:  |  Size: 321 B

After

Width:  |  Height:  |  Size: 321 B

View file

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 209 B

View file

@ -0,0 +1,221 @@
<?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
*/
class dcTranslaterLang
{
/** @var dCore dcCore instance */
public $core = null;
/** @var dcTranslater dcTranslater instance */
public $translater = null;
/** @var dcTranslaterModule dcTranslaterModule instance */
public $module = null;
/** @var array Lang properies */
private $prop = [];
public function __construct(dcTranslaterModule $module, string $lang)
{
$this->core = $module->core;
$this->translater = $module->translater;
$this->module = $module;
$this->prop['code'] = $lang;
$this->prop['name'] = l10n::getLanguageName($lang);
$this->prop['plural'] = explode(':', l10n::getLanguagePluralExpression($lang));
}
/**
* Get a lang property
*
* @param string $key The lang property key
* @return mixed The lang property value or null
*/
public function get(string $key)
{
return array_key_exists($key, $this->prop) ? $this->prop[$key] : null;
}
/**
* Magic get
*/
public function __get($key)
{
return $this->get($key);
}
/**
* Get a lang messages
*
* @return array The messages ids and translations
*/
public function getMessages(): array
{
$res = [];
$m_msgids = $this->getMsgIds();
$m_msgstrs = $this->getMsgStrs();
foreach($this->translater->getModules() as $module) {
if ($module->id != $this->module->id) {
$m_o_msgstrs[$module->id] = $this->translater->getlang($module, $this->code)->getMsgStrs();
}
}
$dc_module = new dcTranslaterModule($this->translater, ['id' => 'dotclear', 'root' => DC_ROOT]);
$dc_lang = new dctranslaterLang($dc_module, $this->code);
$m_o_msgstrs['dotclear'] = $dc_lang->getMsgStrs();
# From id list
foreach($m_msgids as $rs) {
$res[$rs['msgid']]['files'][] = [trim($rs['file'],'/'), $rs['line']];
$res[$rs['msgid']]['group'] = 'main';
$res[$rs['msgid']]['plural'] = $rs['msgid_plural'];
$res[$rs['msgid']]['msgstr'] = [''];
$res[$rs['msgid']]['in_dc'] = false;
$res[$rs['msgid']]['o_msgstrs'] = [];
}
# From str list
foreach($m_msgstrs as $rs) {
if (!isset($res[$rs['msgid']])) {
$res[$rs['msgid']]['files'][] = [];
$res[$rs['msgid']]['in_dc'] = false;
$res[$rs['msgid']]['o_msgstrs'] = [];
}
$res[$rs['msgid']]['group'] = $rs['group'];
$res[$rs['msgid']]['plural'] = $rs['msgid_plural'];
$res[$rs['msgid']]['msgstr'] = is_array($rs['msgstr']) ? $rs['msgstr'] : [$rs['msgstr']];
$res[$rs['msgid']]['in_dc'] = false;
}
# From others str list
foreach($m_o_msgstrs as $o_module => $o_msgstrs) {
foreach($o_msgstrs as $rs) {
if (!isset($res[$rs['msgid']])) {
continue;
}
$res[$rs['msgid']]['o_msgstrs'][] = [
'msgstr' => is_array($rs['msgstr']) ? $rs['msgstr'] : [$rs['msgstr']],
'module' => $o_module,
'file' => $rs['file']
];
if ($o_module == 'dotclear') {
$res[$rs['msgid']]['in_dc'] = true;
}
}
}
return $res;
}
/**
* Get messages ids
*
* @return array The messages ids
*/
public function getMsgIds(): array
{
$res = [];
$files = dcTranslater::scandir($this->module->root);
$scan_ext = ['php'];
if ($this->translater->scan_tpl) {
// $scan_ext[] = 'html';
}
foreach($files AS $file) {
if (is_dir($this->module->root . '/' . $file)
|| !in_array(files::getExtension($file), $scan_ext)) {
continue;
}
$contents = file_get_contents($this->module->root . '/' . $file);
# php files
$msgs = dcTranslater::extractPhpMsgs($contents);
foreach($msgs as $msg) {
$res[] = [
'msgid' => dcTranslater::encodeMsg($msg[0][0]),
'msgid_plural' => empty($msg[0][1]) ? '' : dcTranslater::encodeMsg($msg[0][1]),
'file' => $file,
'line' => $msg[1]
];
}
unset($contents);
}
return $res;
}
/**
* Get messages translations
*
* @return array The messages translations
*/
public function getMsgStrs(): array
{
$res = $scanned = [];
$langs = $this->module->getLangs(true);
if (!isset($langs[$this->code])) {
return $res;
}
foreach($langs[$this->code] as $file) {
if (in_array($file, $scanned)) {
continue;
}
$scanned[] = $file;
$path = path::clean($this->module->locales . '/' . $file);
if (dcTranslater::isPoFile($file)) {
$po = l10n::parsePoFile($path);
if (!is_array($po)) {
continue;
}
$entries = $po[1];
foreach($entries as $entry) {
$res[] = array(
'msgid' => $entry['msgid'],
'msgid_plural' => $entry['msgid_plural'] ?? '',
'msgstr' => is_array($entry['msgstr']) ? $entry['msgstr'] : [$entry['msgstr']],
'lang' => $this->code,
'type' => 'po',
'path' => $path,
'file' => basename($file),
'group'=> str_replace('.po', '', basename($file))
);
}
/*
# .lang.php files
} elseif (self::isLangphpFile($file)) {
$php = self::getLangphpFile($path);
foreach($php AS $id => $str) {
# Don't overwrite .po
if (isset($is_po[$requested_lang][$id])) {
continue;
}
$res[] = array(
'msgid' => self::encodeMsg($id),
'msgstr' => self::encodeMsg($str),
'lang' => $requested_lang,
'type' => 'php',
'path' => $path,
'file' => basename($file),
'group'=> str_replace('.lang.php', '', basename($file))
);
}
*/
}
}
return $res;
}
}

View file

@ -0,0 +1,749 @@
<?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
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return;
}
/**
* Translater tools.
*/
class dcTranslaterModule
{
/** @var dCore dcCore instance */
public $core = null;
/** @var dcTranslater dcTranslater instance */
public $translater = null;
/** @var array Module properies */
private $prop = [];
/** @var string Backup file regexp */
private $backup_file_regexp = '/^l10n-%s-(.*?)-[0-9]*?\.bck\.zip$/';
/** @var string Locales file regexp */
private $locales_file_regexp = '/^(.*?)\/locales\/(.*?)\/(.*?)(.po|.lang.php)$/';
public function __construct(dcTranslater $translater, array $module)
{
$this->core = $translater->core;
$this->translater = $translater;
$this->prop = $module;
$this->prop['root'] = path::real($this->prop['root']);
$i = path::info($this->prop['root']);
$this->prop['basename'] = $i['basename'];
$this->prop['locales'] = $this->prop['root'] . '/locales';
}
/**
* Get a module property
*
* @param string $key The module property key
* @return mixed The module property value or null
*/
public function get(string $key)
{
return array_key_exists($key, $this->prop) ? $this->prop[$key] : null;
}
/**
* Magic get
*/
public function __get($key)
{
return $this->get($key);
}
/// @name backup methods
//@{
/**
* Find backup folder of a module
*
* @param boolean $throw Silently failed
* @return mixed The backup folder directory or false
*/
public function getBackupRoot(bool $throw = false)
{
$dir = false;
switch($this->translater->backup_folder) {
case 'module':
if ($this->prop['root_writable']) {
$dir = $this->prop['locales'];
}
break;
case 'plugin':
$tmp = path::real(array_pop(explode(PATH_SEPARATOR, DC_PLUGINS_ROOT)));
if ($tmp && is_writable($tmp)) {
$dir = $tmp;
}
break;
case 'public':
$tmp = path::real($this->core->blog->public_path);
if ($tmp && is_writable($tmp)) {
$dir = $tmp;
}
break;
case 'cache':
$tmp = path::real(DC_TPL_CACHE);
if ($tmp && is_writable($tmp)) {
@mkDir($tmp . '/l10n');
$dir = $tmp . '/l10n';
}
break;
case 'translater':
$tmp = path::real($this->core->plugins->moduleRoot('translater'));
if ($tmp && is_writable($tmp)) {
@mkDir($tmp . '/locales');
$dir = $tmp . '/locales';
}
break;
}
if (!$dir && $throw) {
throw new Exception(sprintf(
__('Cannot find backups folder for module %s'), $id
));
}
return $dir;
}
/**
* Get a list of available backups
*
* @param boolean $return_filename Return only filenames
* @return array The module backups info
*/
public function getBackups(bool $return_filename = false): array
{
$backup = $this->getBackupRoot();
if (!$backup) {
return [];
}
$res = [];
$files = dcTranslater::scandir($backup);
foreach($files AS $file) {
$is_backup = preg_match(sprintf($this->backup_file_regexp, preg_quote($this->prop['id'])), $file, $m);
if (is_dir($backup . '/' . $file)
|| !$is_backup
|| !l10n::isCode($m[1])
) {
continue;
}
if ($return_filename) {
$res[] = $file;
} else {
$res[$m[1]][$file]['code'] = $m[1];
$res[$m[1]][$file]['name'] = l10n::getLanguageName($m[1]);
$res[$m[1]][$file]['path'] = path::info($backup . '/' . $file);
$res[$m[1]][$file]['time'] = filemtime($backup . '/' . $file);
$res[$m[1]][$file]['size'] = filesize($backup . '/' . $file);
$res[$m[1]][$file]['module'] = $this->prop['id'];
}
}
return $res;
}
/**
* Create a backup
*
* @param string $lang The backup lang
* @return boolean True on success
*/
public function createBackup(string $lang): bool
{
$backup = $this->getBackupRoot(true);
if (!is_dir($this->prop['locales'] . '/' . $lang)) {
throw new Exception(sprintf(
__('Cannot find language folder %s for module %s') ,$lang, $this->prop['id']
));
}
$res = [];
$files = dcTranslater::scandir($this->prop['locales'] . '/' . $lang);
foreach($files as $file) {
if (!is_dir($this->prop['locales'] . '/' . $lang . '/' . $file)
&& (dcTranslater::isLangphpFile($file) || dcTranslater::isPoFile($file))
) {
$res[$this->prop['locales'] . '/' . $lang . '/' .$file] =
$this->prop['id'] . '/locales/' . $lang . '/' . $file;
}
}
if (!empty($res)) {
dcTranslater::isBackupLimit($backup, $this->translater->backup_limit, true);
@set_time_limit(300);
$fp = fopen($backup . '/l10n-' . $this->prop['id'] . '-' . $lang . '-' . time() . '.bck.zip', 'wb');
$zip = new fileZip($fp);
foreach($res AS $from => $to) {
$zip->addFile($from, $to);
}
$zip->write();
$zip->close();
unset($zip);
return true;
}
}
/**
* Retore a backup
*
* @param string $file The backup filename
* @return boolean True on success
*/
public function restoreBackup(string $file): bool
{
$backup = self::getBackupRoot(true);
if (!file_exists($backup . '/' . $file)) {
throw new Exception(sprintf(
__('Cannot find backup file %s'), $file
));
}
$zip = new fileUnzip($backup . '/' . $file);
$zip_files = $zip->getFilesList();
foreach($zip_files AS $zip_file) {
$f = $this->parseZipFilename($zip_file, true);
$zip->unzip($zip_file, $this->prop['locales'] . '/' . $f['lang'] . '/' . $f['group'] . $f['ext']);
$done = true;
}
$zip->close();
unset($zip);
return true;
}
/**
* Delete a module backup
*
* @param string $file The backup filename
* @return boolean True on success
*/
public function deleteBackup(string $file): bool
{
$backup = $this->getBackupRoot(true);
$is_backup = preg_match(sprintf($this->backup_file_regexp, preg_quote($this->prop['id'])), $file, $m);
if (!file_exists($backup . '/' . $file)
|| !$is_backup
|| !l10n::isCode($m[1])
) {
return false;
}
if (!files::isDeletable($backup . '/' . $file)) {
throw new Exception(sprintf(
__('Cannot delete backup file %s'), $file
));
}
unlink($backup . '/' . $file);
return true;
}
/**
* Import a language pack
*
* @param array $zip_file The uploaded file info
* @return boolean True on success
*/
public function importPack(array $zip_file): bool
{
files::uploadStatus($zip_file);
$imported = false;
$not_overwrited = [];
$res = [];
# Load Unzip object
$zip = new fileUnzip($zip_file['tmp_name']);
$files = $zip->getFilesList();
foreach($files AS $file) {
$f = $this->parseZipFilename($file, true);
if (!$this->translater->import_overwrite
&& file_exists($this->prop['locales'] . '/' . $f['lang'] . '/' . $f['group'] . $f['ext'])
) {
$not_overwrited[] = implode('-', [$f['lang'], $f['group'], $f['ext']]);
continue;
}
$res[] = [
'from' => $file,
'root' => $this->prop['locales'] . '/' . $f['lang'],
'to' => $this->prop['locales'] . '/' . $f['lang'] . '/' . $f['group'] . $f['ext']
];
}
foreach ($res AS $rs) {
if (!is_dir($rs['root'])) {
files::makeDir($rs['root'], true);
}
$zip->unzip($rs['from'], $rs['to']);
$imported = true;
}
$zip->close();
unlink($zip_file['tmp_name']);
if (!empty($not_overwrited)) {
throw new Exception(sprintf(
__('Some languages has not been overwrited %s'), implode(', ', $not_overwrited)
));
} elseif (!$done) {
throw new Exception(sprintf(
__('Nothing to import for these modules in pack %s'), $zip_file['name']
));
}
return true;
}
/**
* Export (to output) language pack
*
* @param array $modules The modules to work on
* @param array $langs Langs to export
*/
public function exportPack(array $langs)
{
if (empty($langs)) {
throw new Exception(
__('Wrong export query')
);
}
$filename = files::tidyFileName($this->translater->export_filename);
if (empty($filename)) {
throw new Exception(
__('Export mask is not set in plugin configuration')
);
}
$res = [];
foreach($langs AS $lang) {
if (!is_dir($this->prop['locales'] . '/' . $lang)) {
continue;
}
$files = dcTranslater::scandir($this->prop['locales'] . '/' . $lang);
foreach($files as $file) {
if (is_dir($this->prop['locales'] . '/' . $lang . '/' . $file)
|| !dcTranslater::isLangphpFile($file)
&& !dcTranslater::isPoFile($file)
) {
continue;
}
$res[$this->prop['locales'] . '/' . $lang . '/' . $file] =
$this->prop['id'] . '/locales/' . $lang . '/' . $file;
}
}
if (empty($res)) {
throw new Exception(
__('Nothing to export')
);
}
@set_time_limit(300);
$fp = fopen('php://output', 'wb');
$zip = new fileZip($fp);
foreach($res as $from => $to) {
$zip->addFile($from, $to);
}
$filename = files::tidyFileName(dt::str(str_replace(
['timestamp', 'module', 'type', 'version'],
[time(), $this->prop['id'], $this->prop['type'], $this->prop['version']],
$this->translater->export_filename
)));
header('Content-Disposition: attachment;filename=' . $filename . '.zip');
header('Content-Type: application/x-zip');
$zip->write();
unset($zip);
exit;
}
/**
* Parse zip filename to module, lang info
*
* @param string $file The zip filename
* @param boolean $throw Silently failed
* @return mixed Array of file info or false
*/
public function parseZipFilename(string $file = '', bool $throw = false)
{
$is_file = preg_match('/^(.*?)\/locales\/(.*?)\/(.*?)(.po|.lang.php)$/', $file, $f);
if ($is_file) {
$module = $f[1] == $this->prop['id'] ?$f[1] : false;
$lang = l10n::isCode($f[2]) ? $f[2] : false;
$group = in_array($f[3], dctranslater::$allowed_l10n_groups) ? $f[3] : false;
$ext = dctranslater::isLangphpFile($f[4]) || dctranslater::isPoFile($f[4]) ? $f[4] : false;
}
if (!$is_file || !$module || !$lang || !$group || !$ext) {
if ($throw) {
throw new Exception(sprintf(
__('Zip file %s is not in translater format'), $file
));
}
return false;
}
return [
'module' => $module,
'lang' => $lang,
'group' => $group,
'ext' => $ext
];
}
//@}
/// @name lang methods
//@{
/**
* List available langs of a module
*
* @param boolean $return_path Return path or name
* @return array The lang list
*/
public function getLangs(bool $return_path = false)
{
$res = [];
$prefix = preg_match('/(locales(.*))$/', $this->prop['locales']) ? 'locales' : '';
$files = dcTranslater::scandir($this->prop['locales']);
foreach($files as $file) {
if (!preg_match('/.*?locales\/([^\/]*?)\/([^\/]*?)(.lang.php|.po)$/', $prefix . $file, $m)) {
continue;
}
if (!l10n::isCode($m[1])) {
continue;
}
if ($return_path) {
$res[$m[1]][] = $file; // Path
} else {
$res[$m[1]] = l10n::getLanguageName($m[1]); // Lang name
}
}
return $res;
}
/**
* List of used langs of a module
*
* @return array The list of iso names and codes
*/
public function getUsedLangs()
{
return array_flip($this->getLangs());
}
/**
* List of unsused langs of a module
*
* @return array The list of iso names and codes
*/
public function getUnusedLangs()
{
return array_diff(l10n::getISOcodes(true, false), $this->getUsedLangs());
}
/**
* Add a lang to a module
*
* @param string $lang The lang id
* @param string $from_lang The lang to copy from
* @return boolean True on success
*/
public function addLang(string $lang, string $from_lang = '')
{
if (!l10n::isCode($lang)) {
throw new Exception(sprintf(
__('Wrong language %s'), $lang
));
}
$langs = $this->getLangs();
if (isset($langs[$lang])) {
throw new Exception(sprintf(
__('Language %s already exists'), $lang
));
}
files::makeDir($this->prop['locales'] . '/' . $lang, true);
if (!empty($from_lang) && !isset($langs[$from_lang])) {
throw new Exception(sprintf(
__('Cannot copy file from language %s'), $from_lang
));
}
if (!empty($from_lang) && isset($langs[$from_lang])) {
$files = dcTranslater::scandir($this->prop['locales'] . '/' . $from_lang);
foreach($files as $file) {
if (is_dir($this->prop['locales'] . '/' . $from_lang . '/' . $file)
|| !dcTranslater::isLangphpFile($file)
&& !dcTranslater::isPoFile($file)
) {
continue;
}
files::putContent($this->prop['locales'] . '/' . $lang . '/' . $file,
file_get_contents($this->prop['locales'] . '/' . $from_lang . '/' . $file)
);
}
} else {
//$this->setLangphpFile($lang, 'main', []);
$this->setPoContent($lang, 'main', []);
}
}
/**
* Update an existing lang
*
* @param string $lang The lang
* @param array $msgs The messages
*/
public function updLang(string $lang, array $msgs)
{
if (!l10n::isCode($lang)) {
throw new Exception(sprintf(
__('Wrong language %s'), $lang
));
}
$langs = $this->getLangs();
if (!isset($langs[$lang])) {
throw new Exception(sprintf(
__('Failed to find language %s'), $lang
));
}
if ($this->translater->backup_auto) {
$this->createBackup($lang);
}
$rs = [];
foreach($msgs as $msg) {
if (empty($msg['msgstr'][0])) {
continue;
}
$rs[$msg['group']][] = $msg;
}
foreach(dcTranslater::$allowed_l10n_groups as $group) {
if (isset($rs[$group])) {
continue;
}
$po_file = $this->prop['locales'] . '/' . $lang . '/' . $group . '.po';
$langphp_file = $this->prop['locales'] . '/' . $lang . '/' . $group . '.lang.php';
if (file_exists($po_file)) {
unlink($po_file);
}
if (file_exists($langphp_file)) {
unlink($langphp_file);
}
}
if (empty($rs)) {
throw new Exception(sprintf(
__('No string to write, language %s deleted for module %s'),
$lang, $id
));
}
foreach($rs as $group => $msgs) {
$this->setPoContent($lang, $group, $msgs);
//$this->setLangphpFile($lang, $group, $msgs);
}
}
/**
* Delete a lang
*
* @param string $lang The lang code
* @param boolean $del_empty_dir Also remove empty locales dir
* @return boolean True on success
*/
public function delLang(string $lang, bool $del_empty_dir = true): bool
{
# Path is right formed
if (!l10n::isCode($lang)) {
throw new Exception(sprintf(
__('Wrong language %s'), $lang
));
}
$files = $this->getLangs(true);
if (!isset($files[$lang])) {
throw new Exception(sprintf(
__('Cannot find language folder %s'), $lang
));
}
foreach($files[$lang] as $file) {
unlink($this->prop['locales'] . '/' . $file);
}
$dir = dcTranslater::scandir($this->prop['locales'] . '/' . $lang);
if (empty($dir)) {
rmdir($this->prop['locales'] . '/' . $lang);
}
$loc = dcTranslater::scandir($this->prop['locales']);
if (empty($loc)) {
rmdir($this->prop['locales']);
}
return true;
}
/**
* Write a lang file
*
* @param string $file The full file path
* @param string $content The file content
* @param boolean $throw Silently failed
* @return boolean True on success
*/
private function writeLang(string $file, string $content, bool $throw = false)
{
$path = path::info($file);
if (is_dir($path['dirname']) && !is_writable($path['dirname'])
|| file_exists($file) && !is_writable($file)) {
throw new Exception(sprintf(
__('Cannot grant write acces on lang file %s'), $file
));
}
# -- BEHAVIOR -- dcTranslaterBeforeWriteLangFile
$this->core->callBehavior('dcTranslaterBeforeWriteLangFile', $file, $content, $throw);
$f = @files::putContent($file,$content);
if (!$f && $throw) {
throw new Exception(sprintf(
__('Cannot write lang file %s'), $file
));
}
# -- BEHAVIOR -- dcTranslaterAfterWriteLangFile
$this->core->callBehavior('dcTranslaterAfterWriteLangFile', $f, $file, $content, $throw);
return $f;
}
/**
* Construct and parse a .po file
*
* @param string $lang The lang code
* @param string $group The lang group
* @param array $msgs The strings
*/
private function setPoContent(string $lang, string $group, array $msgs)
{
if (!$this->translater->write_po) {
return null;
}
$lang = new dcTranslaterLang($this, $lang);
$l = '';
if ($this->translater->parse_comment) {
$l .=
'# Language: ' . $lang->name . "\n" .
'# Module: ' . $this->prop['id'] . " - " . $this->prop['version'] . "\n" .
'# Date: ' . dt::str('%Y-%m-%d %H:%M:%S') . "\n";
if ($this->translater->parse_user && !empty($this->translater->parse_userinfo)) {
$search = dctranslater::$allowed_user_informations;
foreach($search AS $n) {
$replace[] = $this->core->auth->getInfo('user_' . $n);
}
$info = trim(str_replace($search, $replace, $this->translater->parse_userinfo));
if (!empty($info)) {
$l .= '# Author: ' . html::escapeHTML($info) . "\n";
}
}
$l .=
'# Translated with translater ' . $this->core->plugins->moduleInfo('translater', 'version') . "\n";
}
$l .=
"\n".
"msgid \"\"\n" .
"msgstr \"\"\n" .
'"Content-Type: text/plain; charset=UTF-8\n"' . "\n" .
'"Project-Id-Version: ' . $this->prop['id'] . ' ' . $this->prop['version'] . '\n"' . "\n" .
'"POT-Creation-Date: \n"' . "\n" .
'"PO-Revision-Date: ' . date('c') . '\n"' . "\n" .
'"Last-Translator: ' . $this->core->auth->getInfo('user_cn') . '\n"' . "\n" .
'"Language-Team: \n"' . "\n" .
'"MIME-Version: 1.0\n"' . "\n" .
'"Content-Transfer-Encoding: 8bit\n"' . "\n" .
'"Plural-Forms: nplurals=2; plural=(n > 1);\n"' . "\n\n";
$comments = [];
if ($this->translater->parse_comment) {
$msgids = $lang->getMsgids();
foreach($msgids as $msg) {
$comments[$msg['msgid']] = (isset($comments[$msg['msgid']]) ?
$comments[$msg['msgid']] : '') .
'#: '.trim($msg['file'],'/') . ':' . $msg['line'] . "\n";
}
}
$content = '';
foreach($msgs as $msg) {
if (empty($msg['msgstr'][0])) {
continue;
}
if ($this->translater->parse_comment && isset($comments[$msg['msgid']])) {
$content .= $comments[$msg['msgid']];
}
$content .= 'msgid "' . dcTranslater::poString($msg['msgid'], true) . '"' . "\n";
if (empty($msg['msgid_plural'])) {
$content .= 'msgstr "' . dcTranslater::poString($msg['msgstr'][0], true) . '"' . "\n";
} else {
$content .= 'msgid_plural "' . dcTranslater::poString($msg['msgid_plural'], true) . '"' . "\n";
foreach($msg['msgstr'] as $i => $plural) {
$content .= 'msgstr[' . $i . '] "' . dcTranslater::poString(($msg['msgstr'][$i] ?: ''), true) . '"' . "\n";
}
}
$content .= "\n";
}
self::writeLang($this->locales . '/' . $lang->code . '/' . $group . '.po', $content, true);
}
//@}
}

File diff suppressed because it is too large Load diff

1580
index.php

File diff suppressed because it is too large Load diff

View file

@ -1,91 +0,0 @@
/* -- BEGIN LICENSE BLOCK ----------------------------------
*
* This file is part of translater, a plugin for Dotclear 2.
*
* Copyright (c) 2009-2013 Jean-Christian Denis and contributors
* contact@jcdenis.fr
*
* Licensed under the GPL version 2.0 license.
* A copy of this license is available in LICENSE file or at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* -- END LICENSE BLOCK ------------------------------------*/
;if(window.jQuery) (function($){
$.fn.translater = function(options){
var opts = $.extend({}, $.fn.translater.defaults, options);
return this.each(function(){
var img = '<img src="index.php?pf=translater/inc/img/field.png" alt="" />';
var tog = '<img src="index.php?pf=translater/inc/img/toggle.png" alt="" />';
var line = this;
var msgid = $(line).children('.translatermsgid');
var msgfile = $(line).children('.translatermsgfile');
var msgstr = $(line).children('.translatermsgstr');
var target = $(line).children('.translatertarget');
$('.strlist').hide();
var img_go = $('<a class="addfield" title="'+opts.title_go+'">'+img+'</a>').css('cursor','pointer');
$(msgid).prepend(' ').prepend(img_go);
$(img_go).click(function(){
var txt = $(msgid).text();
$(img_go).css('cursor','wait');
$.get(opts.url,{f:opts.func,langFrom:opts.from,langTo:opts.to,langTool:opts.tool,langStr:txt},function(data){
data=$(data);
if(data.find('rsp').attr('status')=='ok' && $(data).find('proposal').attr('str_to')){
var resp = $(data).find('proposal').attr('str_to');
if (confirm(opts.title+'\n'+resp)){
addText(target,resp);
$(img_go).css('cursor','pointer');
}
else{
$(img_go).css('cursor','pointer');
}
}else{
alert(opts.failed);
$(img_go).css('cursor','pointer');
}
});
});
$(msgstr).children('.subtranslatermsgstr').each(function(){
var img_str = $('<a class="togglelist" title="detail">'+tog+'</a>').css('cursor','pointer');
$(this).children('strong').each(function(){
var txt = $(this).text();
var img_add = $('<a class="addfield" title="'+opts.title_add+'">'+img+'</a>').css('cursor','pointer');
$(this).prepend(' ').prepend(img_add);
$(img_add).click(function(){addText(target,txt);});
$(this).append(' ').append(img_str);
var strlist=$(this).siblings('.strlist');
$(strlist).click(function(){$(strlist).toggle();});
$(img_str).click(function(){$(strlist).toggle();});
});
});
var img_file = $('<a class="togglelist" title="detail">'+tog+'</a>').css('cursor','pointer');
$(msgfile).children('strong').each(function(){
$(this).append(' ').append(img_file);
var strlist=$(this).siblings('.strlist');
$(strlist).click(function(){$(strlist).toggle();});
$(img_file).click(function(){$(strlist).toggle();});
});
});
};
function addText(target,text){
$(target).children(':text').val(text);
}
$.fn.translater.defaults = {
url: '',
func: '',
from: 'en',
to: 'fr',
tool: 'google',
failed: 'Failed to translate this',
title: 'Copy translation to field:',
title_go: 'Find translation',
title_add: 'Add this translation'
};
})(jQuery);

64
js/translater.js Normal file
View file

@ -0,0 +1,64 @@
/*global $, dotclear */
'use strict';
$(function () {
$('#module-backup-create-form .checkboxes-helpers').each(function () {
dotclear.checkboxesHelpers(this, undefined, '#module-backup-create-form td input[type=checkbox]', '#module-backup-create-form #do-action');
});
$('#module-backup-create-form td input[type=checkbox]').enableShiftClick();
dotclear.condSubmit('#module-backup-create-form td input[type=checkbox]', '#module-backup-create-form #do-action');
$('#module-backup-edit-form .checkboxes-helpers').each(function () {
dotclear.checkboxesHelpers(this, undefined, '#module-backup-edit-form td input[type=checkbox]', '#module-backup-edit-form #do-action');
});
$('#module-backup-edit-form td input[type=checkbox]').enableShiftClick();
dotclear.condSubmit('#module-backup-edit-form td input[type=checkbox]', '#module-backup-edit-form #do-action');
$('#module-pack-export-form .checkboxes-helpers').each(function () {
dotclear.checkboxesHelpers(this, undefined, '#module-pack-export-form td input[type=checkbox]', '#module-pack-export-form #do-action');
});
$('#module-pack-export-form td input[type=checkbox]').enableShiftClick();
dotclear.condSubmit('#module-pack-export-form td input[type=checkbox]', '#module-pack-export-form #do-action');
$('#lang-edit-form .checkboxes-helpers').each(function () {
dotclear.checkboxesHelpers(this, undefined, '#lang-edit-form td input[type=checkbox]', undefined);
});
$('#lang-edit-form td input[type=checkbox]').enableShiftClick();
const dctranslater = dotclear.getData('translater');
$('.translaterline').each(function(){
var line = this;
var msgfile = $(line).children('.translatermsgfile');
var msgstr = $(line).children('.translatermsgstr');
var target = $(line).children('.translatertarget');
var img = '<img src="'+dctranslater.image_field+'" alt="" />';
var tog = '<img src="'+dctranslater.image_toggle+'" alt="" />';
$('.strlist').hide();
$(msgstr).children('.subtranslater').each(function(){
var img_str = $('<a class="togglelist" title="detail">'+tog+'</a>').css('cursor','pointer');
$(this).children('strong').each(function(){
var txt = $(this).text();
var img_add = $('<a class="addfield" title="'+dctranslater.title_add+'">'+img+'</a>').css('cursor','pointer');
$(this).prepend(' ').prepend(img_add);
$(img_add).click(function(){$(target).children(':text').val(txt)});
$(this).append(' ').append(img_str);
var strlist=$(this).siblings('.strlist');
$(strlist).click(function(){$(strlist).toggle();});
$(img_str).click(function(){$(strlist).toggle();});
});
});
$(msgfile).children('.subtranslater').each(function(){
var img_file = $('<a class="togglelist" title="detail">'+tog+'</a>').css('cursor','pointer');
$(this).children('strong').each(function(){
$(this).append(' ').append(img_file);
var strlist=$(this).siblings('.strlist');
$(strlist).click(function(){$(strlist).toggle();});
$(img_file).click(function(){$(strlist).toggle();});
});
});
});
});

View file

@ -1,419 +0,0 @@
<?php
// Language: Français
// Module: translater - 2018.02.14
// Date: 2018-10-18 09:43:01
// Translated with dcTranslater - 2018.02.14
#_admin.php:25
#_admin.php:112
#index.php:536
#index.php:569
#index.php:1383
$GLOBALS['__l10n']['Translater'] = 'Traducteur';
#_admin.php:43
$GLOBALS['__l10n']['Translate plugins'] = 'Traduire les plugins';
#_admin.php:61
$GLOBALS['__l10n']['Translate this plugin'] = 'Traduire ce plugin';
#_admin.php:84
$GLOBALS['__l10n']['Translate this theme'] = 'Traduire ce thème';
#_uninstall.php:20
$GLOBALS['__l10n']['delete all settings'] = 'effacer tous les paramètres';
#_uninstall.php:27
$GLOBALS['__l10n']['delete plugin files'] = 'effacer les fichiers du plugin';
#_uninstall.php:34
$GLOBALS['__l10n']['delete the version number'] = 'effacer le n° de version';
#_uninstall.php:42
$GLOBALS['__l10n']['delete all %s settings'] = 'effacer tous les paramètres de %s';
#_uninstall.php:49
$GLOBALS['__l10n']['delete %s plugin files'] = 'effacer les fichiers du plugin %s';
#_uninstall.php:56
$GLOBALS['__l10n']['delete %s version number'] = 'effacer la version de %s';
#inc/class.dc.translater.php:359
$GLOBALS['__l10n']['Cannot find module %s'] = 'Impossible de trouver le module %s';
#inc/class.dc.translater.php:437
$GLOBALS['__l10n']['Cannot find backups folder for module %s'] = 'Impossible de trouver le dossier de sauvegarde du module %s';
#inc/class.dc.translater.php:453
$GLOBALS['__l10n']['Cannot find languages folder for module %s'] = 'Impossible de trouver le dossier de langue du module %s';
#inc/class.dc.translater.php:473
$GLOBALS['__l10n']['Cannot find root folder for module %s'] = 'Impossible de trouver le dossier racine du module %s';
#inc/class.dc.translater.php:502
$GLOBALS['__l10n']['Limit of %s backups for module %s exceed'] = 'La limite de %s sauvegardes pour le module % est dépassée';
#inc/class.dc.translater.php:564
#inc/class.dc.translater.php:954
#inc/class.dc.translater.php:1031
$GLOBALS['__l10n']['Cannot find language folder %s for module %s'] = 'Impossible de trouver le dossier de langue %s pour le module %s';
#inc/class.dc.translater.php:619
$GLOBALS['__l10n']['Cannot delete backup file %s'] = 'Impossible d\'effacer le fichier de sauvegarde %s';
#inc/class.dc.translater.php:637
$GLOBALS['__l10n']['Cannot find backup file %s'] = 'Impossible de trouver le fichier de sauvegarde %s';
#inc/class.dc.translater.php:663
$GLOBALS['__l10n']['Wrong export query'] = 'Mauvaise requète d\'exportation';
#inc/class.dc.translater.php:674
$GLOBALS['__l10n']['Cannot use export mask %s'] = 'Impossible d\'utiliser le masque d\'exportation %s';
#inc/class.dc.translater.php:762
$GLOBALS['__l10n']['Wrong import query'] = 'Mauvaise requète d\'importation';
#inc/class.dc.translater.php:811
$GLOBALS['__l10n']['Nothing to import for these modules in pack %s'] = 'Rien à importer pour ces modules dans le paquetage %s';
#inc/class.dc.translater.php:840
$GLOBALS['__l10n']['Zip file %s is not in translater format'] = 'Le fichier zip n\'est pas au format de translater';
#inc/class.dc.translater.php:900
$GLOBALS['__l10n']['Language %s already exists for module %s'] = 'La langue %s existe dèjà pour le module %s';
#inc/class.dc.translater.php:911
$GLOBALS['__l10n']['Cannot copy file from language %s for module %s'] = 'Impossible de copier le fichier depuis le langage %s pour le module %s';
#inc/class.dc.translater.php:1003
$GLOBALS['__l10n']['No string to write, language %s deleted for module %s'] = 'Aucune chaine à écrire, la langue %s a été effacée pour le module %s';
#inc/class.dc.translater.php:1267
$GLOBALS['__l10n']['Cannot grant write acces on lang file %s'] = 'Impossible d\'avoir les droits en écriture sur le fichier de langue %s';
#inc/class.dc.translater.php:1278
$GLOBALS['__l10n']['Cannot write lang file %s'] = 'Impossible d\'écrire le fichier de langue %s';
#inc/class.dc.translater.php:1583
$GLOBALS['__l10n']['Cannot find language for code %s'] = 'Impossible de trouver de langue pour le code %s';
#inc/class.translater.rest.php:41
$GLOBALS['__l10n']['Missing params'] = 'Paramètres manquants';
#inc/class.translater.rest.php:50
$GLOBALS['__l10n']['Failed to get translation tool'] = 'Impossible de trouver l\'outil de traduction';
#inc/class.translater.rest.php:54
$GLOBALS['__l10n']['Translation tool is not configured'] = 'L\'outil de traduction n\'est pas configuré';
#inc/lib.translater.google.php:43
$GLOBALS['__l10n']['You must have on Google API console:'] = 'Vous devez avoir sur la console des API Google :';
#inc/lib.translater.google.php:46
$GLOBALS['__l10n']['Activate the "translate API" service'] = 'Activer le service "translate API"';
#inc/lib.translater.google.php:79
$GLOBALS['__l10n']['Failed to query service.'] = 'Impossible d\'interroger le service.';
#inc/lib.translater.microsoft.php:48
$GLOBALS['__l10n']['You must have:'] = 'Vous devez avoir :';
#index.php:25
#index.php:525
#index.php:1381
$GLOBALS['__l10n']['Settings'] = 'Paramètres';
#index.php:27
#index.php:426
#index.php:462
#index.php:500
#index.php:571
$GLOBALS['__l10n']['Themes'] = 'Thèmes';
#index.php:41
$GLOBALS['__l10n']['locales folders of each module'] = 'le répertoire locales de chaque module';
#index.php:42
$GLOBALS['__l10n']['plugins folder root'] = 'le répertoire racine des plugins';
#index.php:43
$GLOBALS['__l10n']['public folder root'] = 'le répertoire public du blog';
#index.php:44
$GLOBALS['__l10n']['cache folder of Dotclear'] = 'le répertoire cache de Dotclear';
#index.php:45
$GLOBALS['__l10n']['locales folder of translater'] = 'le répertoire locales du plugin translater';
#index.php:50
$GLOBALS['__l10n']['Translation successfully updated'] = 'Traduction mise à jour avec succès';
#index.php:51
$GLOBALS['__l10n']['Translation successfully created'] = 'Traduction créée avec succès';
#index.php:52
$GLOBALS['__l10n']['Translation successfully deleted'] = 'Traduction effacée avec succès';
#index.php:53
$GLOBALS['__l10n']['Backups successfully create'] = 'Sauvegardes créées avec succès';
#index.php:54
$GLOBALS['__l10n']['Backups successfully restored'] = 'Sauvegardes effectuées avec succès';
#index.php:55
$GLOBALS['__l10n']['Backups successfully deleted'] = 'Sauvegardes effacées avec succès';
#index.php:56
$GLOBALS['__l10n']['Package successfully imported'] = 'Paquetage importé avec succès';
#index.php:57
$GLOBALS['__l10n']['Package successfully exported'] = 'Paquetage exporté avec succès';
#index.php:61
$GLOBALS['__l10n']['Failed to update settings: %s'] = 'Impossible de mettre à jour les paramètres : %s';
#index.php:62
$GLOBALS['__l10n']['Failed to update translation: %s'] = 'Impossible de mettre à jour la traduction : %s';
#index.php:63
$GLOBALS['__l10n']['Failed to create translation: %s'] = 'Impossible de créer la traduction : %s';
#index.php:64
$GLOBALS['__l10n']['Failed to delete translation: %s'] = 'Impossible d\'effacer la traduction : %s';
#index.php:65
$GLOBALS['__l10n']['Failed to create backups: %s'] = 'Impossible de créer les sauvegardes : %s';
#index.php:66
$GLOBALS['__l10n']['Failed to restore backups: %s'] = 'Impossible de restaurer les sauvegardes : %s';
#index.php:67
$GLOBALS['__l10n']['Failed to delete backups: %s'] = 'Impossible d\'effacer les sauvegardes : %s';
#index.php:68
$GLOBALS['__l10n']['Failed to import package: %s'] = 'Impossible d\'importer le paquetage : %s';
#index.php:69
$GLOBALS['__l10n']['Failed to export package: %s'] = 'Impossible d\'exporter le paquetage : %s';
#index.php:111
$GLOBALS['__l10n']['No lang to create'] = 'Pas de langue à créer';
#index.php:133
$GLOBALS['__l10n']['No lang to delete'] = 'Pas de langue à effacer';
#index.php:155
$GLOBALS['__l10n']['No lang to backup'] = 'Pas de langue à sauvegarder';
#index.php:188
$GLOBALS['__l10n']['No blackup to restore'] = 'Pas de langue à restaurer';
#index.php:207
$GLOBALS['__l10n']['No bakcup to to restore'] = 'Pas de sauvegarde à restaurer';
#index.php:228
#index.php:246
$GLOBALS['__l10n']['No backup to delete'] = 'Pas de sauvegarde à effacer';
#index.php:289
#index.php:363
$GLOBALS['__l10n']['Nothing to export'] = 'Rien à exporter';
#index.php:311
$GLOBALS['__l10n']['No language to update'] = 'Pas de langue à mettre à jour';
#index.php:442
#index.php:489
$GLOBALS['__l10n']['Failed to launch translater: %s'] = 'Impossible de démarrer translater : %s';
#index.php:555
$GLOBALS['__l10n']['Use this %s translation:'] = 'Utiliser la traduction de %s :';
#index.php:556
$GLOBALS['__l10n']['Translate this text with %s'] = 'Traduire ce texte avec %s';
#index.php:557
$GLOBALS['__l10n']['Use this text'] = 'Utiliser ce texte';
#index.php:605
$GLOBALS['__l10n']['Translate theme "%s" (by %s)'] = 'Traduire le thème "%s" (de %s)';
#index.php:606
$GLOBALS['__l10n']['Translate plugin "%s" (by %s)'] = 'Traduire le plugin "%s" (de %s)';
#index.php:626
#index.php:740
$GLOBALS['__l10n']['Edit translation'] = 'Modifier la traduction';
#index.php:638
$GLOBALS['__l10n']['Id'] = 'Id';
#index.php:648
$GLOBALS['__l10n']['There is no editable modules'] = 'Il n\'y a pas de modules modifiables.';
#index.php:664
$GLOBALS['__l10n']['Summary'] = 'Résumé';
#index.php:665
$GLOBALS['__l10n']['Module'] = 'Module';
#index.php:667
$GLOBALS['__l10n']['About'] = 'À propos';
#index.php:677
$GLOBALS['__l10n']['Root'] = 'Racine';
#index.php:679
#index.php:693
#index.php:810
#index.php:1341
$GLOBALS['__l10n']['Backups'] = 'Sauvegardes';
#index.php:694
$GLOBALS['__l10n']['Last backup'] = 'Dernière sauvegarde';
#index.php:721
$GLOBALS['__l10n']['no backup'] = 'Aucune sauvegarde';
#index.php:736
$GLOBALS['__l10n']['Edit language'] = 'Modifier une langue';
#index.php:756
$GLOBALS['__l10n']['Add language'] = 'Ajouter une langue';
#index.php:763
$GLOBALS['__l10n']['Copy from language:'] = 'Copier depuis la langue :';
#index.php:765
$GLOBALS['__l10n']['Optionnal'] = 'Optionnel';
#index.php:772
$GLOBALS['__l10n']['Add translation'] = 'Ajouter la traduction';
#index.php:789
$GLOBALS['__l10n']['Delete language'] = 'Effacer une langue';
#index.php:793
$GLOBALS['__l10n']['Delete translation'] = 'Effacer la traduction';
#index.php:815
$GLOBALS['__l10n']['Create backups'] = 'Créer une sauvegarde';
#index.php:817
$GLOBALS['__l10n']['Choose languages to backup'] = 'Choisir la langue à sauvegarder';
#index.php:855
$GLOBALS['__l10n']['List of backups'] = 'Liste des sauvegardes';
#index.php:859
#index.php:1065
$GLOBALS['__l10n']['File'] = 'Fichier';
#index.php:886
$GLOBALS['__l10n']['Selected backups action:'] = 'Action sur les sauvegardes sélectionnées :';
#index.php:888
$GLOBALS['__l10n']['Restore backups'] = 'Restaurer les sauvegardes';
#index.php:889
$GLOBALS['__l10n']['Delete backups'] = 'Effacer les sauvegardes';
#index.php:915
#index.php:1182
$GLOBALS['__l10n']['Choose language package to import'] = 'Choisir le paquetage de langue à importer';
#index.php:937
#index.php:1239
$GLOBALS['__l10n']['Choose languages to export'] = 'Choisir les langues à exporter';
#index.php:1058
$GLOBALS['__l10n']['Group'] = 'Groupe';
#index.php:1060
$GLOBALS['__l10n']['String'] = 'Chaîne';
#index.php:1062
#index.php:1283
$GLOBALS['__l10n']['Translation'] = 'Traduction';
#index.php:1063
$GLOBALS['__l10n']['Existing'] = 'Existant';
#index.php:1126
$GLOBALS['__l10n']['%s occurrences'] = '%s occurrences';
#index.php:1152
$GLOBALS['__l10n']['Total of %s strings.'] = 'Total de %s chaînes.';
#index.php:1154
$GLOBALS['__l10n']['Change the group of the selected entries to:'] = 'Changer le groupe des entrées sélectionnées vers :';
#index.php:1211
$GLOBALS['__l10n']['Choose modules to export'] = 'Choisir les modules à exporter';
#index.php:1213
$GLOBALS['__l10n']['Modules'] = 'Modules';
#index.php:1286
$GLOBALS['__l10n']['Write .po files'] = 'Écrire les fichiers .po';
#index.php:1289
$GLOBALS['__l10n']['Write .lang.php files'] = 'Écrire les fichiers .lang.php';
#index.php:1292
$GLOBALS['__l10n']['Translate also strings of template files'] = 'Traduire également les chaînes des fichiers de template';
#index.php:1295
$GLOBALS['__l10n']['Translate only unknow strings'] = 'Traduire uniquement les chaînes inconnues';
#index.php:1298
$GLOBALS['__l10n']['Hide default modules of Dotclear'] = 'Cacher les modules d\'origine de Dotclear';
#index.php:1301
$GLOBALS['__l10n']['Write comments in files'] = 'Écrire les commentaires dans les fichiers';
#index.php:1304
$GLOBALS['__l10n']['Write informations about author in files'] = 'Écrire les informations à propos de l\'auteur dans les fichiers';
#index.php:1308
$GLOBALS['__l10n']['Tools'] = 'Outils';
#index.php:1309
$GLOBALS['__l10n']['Default language of l10n source:'] = 'Langue par défaut des sources l10n :';
#index.php:1313
$GLOBALS['__l10n']['Select and configure the tool to use to translate strings:'] = 'Sélectionner et configurer un outil de traduction :';
#index.php:1325
$GLOBALS['__l10n']['Nothing to configure for %s tool.'] = 'Rien à configurer pour l\'outil %s.';
#index.php:1336
$GLOBALS['__l10n']['Overwrite existing languages'] = 'Écraser les langages existants';
#index.php:1337
$GLOBALS['__l10n']['Name of exported package'] = 'Nom du paquetage exporté';
#index.php:1344
$GLOBALS['__l10n']['Make backups when changes are made'] = 'Faire des sauvegardes lors des modifications';
#index.php:1345
$GLOBALS['__l10n']['Limit backups to %s files per module'] = 'Limiter les sauvegardes à %s fichiers par module';
#index.php:1348
$GLOBALS['__l10n']['Store backups in %s'] = 'Stocker les sauvegardes dans %s';
#index.php:1353
$GLOBALS['__l10n']['Behaviors'] = 'Comportements';
#index.php:1354
$GLOBALS['__l10n']['Default start menu:'] = 'Menu de départ par défaut :';
#index.php:1359
$GLOBALS['__l10n']['Enable menu on extensions page'] = 'Activer le menu sur la page des plugins';
#index.php:1362
$GLOBALS['__l10n']['Enable menu on themes page'] = 'Activer le menu sur la page des thèmes';
$GLOBALS['__l10n']['translater'] = 'Traducteur';
$GLOBALS['__l10n']['Translate your Dotclear plugins and themes'] = 'Traduire vos plugins et thèmes pour Dotclear';

View file

@ -1,562 +0,0 @@
# Language: Français
# Module: translater - 2018.02.14
# Date: 2018-10-18 09:43:01
# Translated with translater 2018.02.14
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: translater 2018.02.14\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2018-10-18T09:43:01+00:00\n"
"Last-Translator: brol\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: _admin.php:25
#: _admin.php:112
#: index.php:536
#: index.php:569
#: index.php:1383
msgid "Translater"
msgstr "Traducteur"
#: _admin.php:43
msgid "Translate plugins"
msgstr "Traduire les plugins"
#: _admin.php:61
msgid "Translate this plugin"
msgstr "Traduire ce plugin"
#: _admin.php:84
msgid "Translate this theme"
msgstr "Traduire ce thème"
#: _uninstall.php:20
msgid "delete all settings"
msgstr "effacer tous les paramètres"
#: _uninstall.php:27
msgid "delete plugin files"
msgstr "effacer les fichiers du plugin"
#: _uninstall.php:34
msgid "delete the version number"
msgstr "effacer le n° de version"
#: _uninstall.php:42
msgid "delete all %s settings"
msgstr "effacer tous les paramètres de %s"
#: _uninstall.php:49
msgid "delete %s plugin files"
msgstr "effacer les fichiers du plugin %s"
#: _uninstall.php:56
msgid "delete %s version number"
msgstr "effacer la version de %s"
#: inc/class.dc.translater.php:359
msgid "Cannot find module %s"
msgstr "Impossible de trouver le module %s"
#: inc/class.dc.translater.php:437
msgid "Cannot find backups folder for module %s"
msgstr "Impossible de trouver le dossier de sauvegarde du module %s"
#: inc/class.dc.translater.php:453
msgid "Cannot find languages folder for module %s"
msgstr "Impossible de trouver le dossier de langue du module %s"
#: inc/class.dc.translater.php:473
msgid "Cannot find root folder for module %s"
msgstr "Impossible de trouver le dossier racine du module %s"
#: inc/class.dc.translater.php:502
msgid "Limit of %s backups for module %s exceed"
msgstr "La limite de %s sauvegardes pour le module % est dépassée"
#: inc/class.dc.translater.php:564
#: inc/class.dc.translater.php:954
#: inc/class.dc.translater.php:1031
msgid "Cannot find language folder %s for module %s"
msgstr "Impossible de trouver le dossier de langue %s pour le module %s"
#: inc/class.dc.translater.php:619
msgid "Cannot delete backup file %s"
msgstr "Impossible d'effacer le fichier de sauvegarde %s"
#: inc/class.dc.translater.php:637
msgid "Cannot find backup file %s"
msgstr "Impossible de trouver le fichier de sauvegarde %s"
#: inc/class.dc.translater.php:663
msgid "Wrong export query"
msgstr "Mauvaise requète d'exportation"
#: inc/class.dc.translater.php:674
msgid "Cannot use export mask %s"
msgstr "Impossible d'utiliser le masque d'exportation %s"
#: inc/class.dc.translater.php:762
msgid "Wrong import query"
msgstr "Mauvaise requète d'importation"
#: inc/class.dc.translater.php:811
msgid "Nothing to import for these modules in pack %s"
msgstr "Rien à importer pour ces modules dans le paquetage %s"
#: inc/class.dc.translater.php:840
msgid "Zip file %s is not in translater format"
msgstr "Le fichier zip n'est pas au format de translater"
#: inc/class.dc.translater.php:900
msgid "Language %s already exists for module %s"
msgstr "La langue %s existe dèjà pour le module %s"
#: inc/class.dc.translater.php:911
msgid "Cannot copy file from language %s for module %s"
msgstr "Impossible de copier le fichier depuis le langage %s pour le module %s"
#: inc/class.dc.translater.php:1003
msgid "No string to write, language %s deleted for module %s"
msgstr "Aucune chaine à écrire, la langue %s a été effacée pour le module %s"
#: inc/class.dc.translater.php:1267
msgid "Cannot grant write acces on lang file %s"
msgstr "Impossible d'avoir les droits en écriture sur le fichier de langue %s"
#: inc/class.dc.translater.php:1278
msgid "Cannot write lang file %s"
msgstr "Impossible d'écrire le fichier de langue %s"
#: inc/class.dc.translater.php:1583
msgid "Cannot find language for code %s"
msgstr "Impossible de trouver de langue pour le code %s"
#: inc/class.translater.rest.php:41
msgid "Missing params"
msgstr "Paramètres manquants"
#: inc/class.translater.rest.php:50
msgid "Failed to get translation tool"
msgstr "Impossible de trouver l'outil de traduction"
#: inc/class.translater.rest.php:54
msgid "Translation tool is not configured"
msgstr "L'outil de traduction n'est pas configuré"
#: inc/lib.translater.google.php:43
msgid "You must have on Google API console:"
msgstr "Vous devez avoir sur la console des API Google :"
#: inc/lib.translater.google.php:46
msgid "Activate the \"translate API\" service"
msgstr "Activer le service \"translate API\""
#: inc/lib.translater.google.php:79
msgid "Failed to query service."
msgstr "Impossible d'interroger le service."
#: inc/lib.translater.microsoft.php:48
msgid "You must have:"
msgstr "Vous devez avoir :"
#: index.php:25
#: index.php:525
#: index.php:1381
msgid "Settings"
msgstr "Paramètres"
#: index.php:27
#: index.php:426
#: index.php:462
#: index.php:500
#: index.php:571
msgid "Themes"
msgstr "Thèmes"
#: index.php:41
msgid "locales folders of each module"
msgstr "le répertoire locales de chaque module"
#: index.php:42
msgid "plugins folder root"
msgstr "le répertoire racine des plugins"
#: index.php:43
msgid "public folder root"
msgstr "le répertoire public du blog"
#: index.php:44
msgid "cache folder of Dotclear"
msgstr "le répertoire cache de Dotclear"
#: index.php:45
msgid "locales folder of translater"
msgstr "le répertoire locales du plugin translater"
#: index.php:50
msgid "Translation successfully updated"
msgstr "Traduction mise à jour avec succès"
#: index.php:51
msgid "Translation successfully created"
msgstr "Traduction créée avec succès"
#: index.php:52
msgid "Translation successfully deleted"
msgstr "Traduction effacée avec succès"
#: index.php:53
msgid "Backups successfully create"
msgstr "Sauvegardes créées avec succès"
#: index.php:54
msgid "Backups successfully restored"
msgstr "Sauvegardes effectuées avec succès"
#: index.php:55
msgid "Backups successfully deleted"
msgstr "Sauvegardes effacées avec succès"
#: index.php:56
msgid "Package successfully imported"
msgstr "Paquetage importé avec succès"
#: index.php:57
msgid "Package successfully exported"
msgstr "Paquetage exporté avec succès"
#: index.php:61
msgid "Failed to update settings: %s"
msgstr "Impossible de mettre à jour les paramètres : %s"
#: index.php:62
msgid "Failed to update translation: %s"
msgstr "Impossible de mettre à jour la traduction : %s"
#: index.php:63
msgid "Failed to create translation: %s"
msgstr "Impossible de créer la traduction : %s"
#: index.php:64
msgid "Failed to delete translation: %s"
msgstr "Impossible d'effacer la traduction : %s"
#: index.php:65
msgid "Failed to create backups: %s"
msgstr "Impossible de créer les sauvegardes : %s"
#: index.php:66
msgid "Failed to restore backups: %s"
msgstr "Impossible de restaurer les sauvegardes : %s"
#: index.php:67
msgid "Failed to delete backups: %s"
msgstr "Impossible d'effacer les sauvegardes : %s"
#: index.php:68
msgid "Failed to import package: %s"
msgstr "Impossible d'importer le paquetage : %s"
#: index.php:69
msgid "Failed to export package: %s"
msgstr "Impossible d'exporter le paquetage : %s"
#: index.php:111
msgid "No lang to create"
msgstr "Pas de langue à créer"
#: index.php:133
msgid "No lang to delete"
msgstr "Pas de langue à effacer"
#: index.php:155
msgid "No lang to backup"
msgstr "Pas de langue à sauvegarder"
#: index.php:188
msgid "No blackup to restore"
msgstr "Pas de langue à restaurer"
#: index.php:207
msgid "No bakcup to to restore"
msgstr "Pas de sauvegarde à restaurer"
#: index.php:228
#: index.php:246
msgid "No backup to delete"
msgstr "Pas de sauvegarde à effacer"
#: index.php:289
#: index.php:363
msgid "Nothing to export"
msgstr "Rien à exporter"
#: index.php:311
msgid "No language to update"
msgstr "Pas de langue à mettre à jour"
#: index.php:442
#: index.php:489
msgid "Failed to launch translater: %s"
msgstr "Impossible de démarrer translater : %s"
#: index.php:555
msgid "Use this %s translation:"
msgstr "Utiliser la traduction de %s :"
#: index.php:556
msgid "Translate this text with %s"
msgstr "Traduire ce texte avec %s"
#: index.php:557
msgid "Use this text"
msgstr "Utiliser ce texte"
#: index.php:605
msgid "Translate theme \"%s\" (by %s)"
msgstr "Traduire le thème \"%s\" (de %s)"
#: index.php:606
msgid "Translate plugin \"%s\" (by %s)"
msgstr "Traduire le plugin \"%s\" (de %s)"
#: index.php:626
#: index.php:740
msgid "Edit translation"
msgstr "Modifier la traduction"
#: index.php:638
msgid "Id"
msgstr "Id"
#: index.php:648
msgid "There is no editable modules"
msgstr "Il n'y a pas de modules modifiables."
#: index.php:664
msgid "Summary"
msgstr "Résumé"
#: index.php:665
msgid "Module"
msgstr "Module"
#: index.php:667
msgid "About"
msgstr "À propos"
#: index.php:677
msgid "Root"
msgstr "Racine"
#: index.php:679
#: index.php:693
#: index.php:810
#: index.php:1341
msgid "Backups"
msgstr "Sauvegardes"
#: index.php:694
msgid "Last backup"
msgstr "Dernière sauvegarde"
#: index.php:721
msgid "no backup"
msgstr "Aucune sauvegarde"
#: index.php:736
msgid "Edit language"
msgstr "Modifier une langue"
#: index.php:756
msgid "Add language"
msgstr "Ajouter une langue"
#: index.php:763
msgid "Copy from language:"
msgstr "Copier depuis la langue :"
#: index.php:765
msgid "Optionnal"
msgstr "Optionnel"
#: index.php:772
msgid "Add translation"
msgstr "Ajouter la traduction"
#: index.php:789
msgid "Delete language"
msgstr "Effacer une langue"
#: index.php:793
msgid "Delete translation"
msgstr "Effacer la traduction"
#: index.php:815
msgid "Create backups"
msgstr "Créer une sauvegarde"
#: index.php:817
msgid "Choose languages to backup"
msgstr "Choisir la langue à sauvegarder"
#: index.php:855
msgid "List of backups"
msgstr "Liste des sauvegardes"
#: index.php:859
#: index.php:1065
msgid "File"
msgstr "Fichier"
#: index.php:886
msgid "Selected backups action:"
msgstr "Action sur les sauvegardes sélectionnées :"
#: index.php:888
msgid "Restore backups"
msgstr "Restaurer les sauvegardes"
#: index.php:889
msgid "Delete backups"
msgstr "Effacer les sauvegardes"
#: index.php:915
#: index.php:1182
msgid "Choose language package to import"
msgstr "Choisir le paquetage de langue à importer"
#: index.php:937
#: index.php:1239
msgid "Choose languages to export"
msgstr "Choisir les langues à exporter"
#: index.php:1058
msgid "Group"
msgstr "Groupe"
#: index.php:1060
msgid "String"
msgstr "Chaîne"
#: index.php:1062
#: index.php:1283
msgid "Translation"
msgstr "Traduction"
#: index.php:1063
msgid "Existing"
msgstr "Existant"
#: index.php:1126
msgid "%s occurrences"
msgstr "%s occurrences"
#: index.php:1152
msgid "Total of %s strings."
msgstr "Total de %s chaînes."
#: index.php:1154
msgid "Change the group of the selected entries to:"
msgstr "Changer le groupe des entrées sélectionnées vers :"
#: index.php:1211
msgid "Choose modules to export"
msgstr "Choisir les modules à exporter"
#: index.php:1213
msgid "Modules"
msgstr "Modules"
#: index.php:1286
msgid "Write .po files"
msgstr "Écrire les fichiers .po"
#: index.php:1289
msgid "Write .lang.php files"
msgstr "Écrire les fichiers .lang.php"
#: index.php:1292
msgid "Translate also strings of template files"
msgstr "Traduire également les chaînes des fichiers de template"
#: index.php:1295
msgid "Translate only unknow strings"
msgstr "Traduire uniquement les chaînes inconnues"
#: index.php:1298
msgid "Hide default modules of Dotclear"
msgstr "Cacher les modules d'origine de Dotclear"
#: index.php:1301
msgid "Write comments in files"
msgstr "Écrire les commentaires dans les fichiers"
#: index.php:1304
msgid "Write informations about author in files"
msgstr "Écrire les informations à propos de l'auteur dans les fichiers"
#: index.php:1308
msgid "Tools"
msgstr "Outils"
#: index.php:1309
msgid "Default language of l10n source:"
msgstr "Langue par défaut des sources l10n :"
#: index.php:1313
msgid "Select and configure the tool to use to translate strings:"
msgstr "Sélectionner et configurer un outil de traduction :"
#: index.php:1325
msgid "Nothing to configure for %s tool."
msgstr "Rien à configurer pour l'outil %s."
#: index.php:1336
msgid "Overwrite existing languages"
msgstr "Écraser les langages existants"
#: index.php:1337
msgid "Name of exported package"
msgstr "Nom du paquetage exporté"
#: index.php:1344
msgid "Make backups when changes are made"
msgstr "Faire des sauvegardes lors des modifications"
#: index.php:1345
msgid "Limit backups to %s files per module"
msgstr "Limiter les sauvegardes à %s fichiers par module"
#: index.php:1348
msgid "Store backups in %s"
msgstr "Stocker les sauvegardes dans %s"
#: index.php:1353
msgid "Behaviors"
msgstr "Comportements"
#: index.php:1354
msgid "Default start menu:"
msgstr "Menu de départ par défaut :"
#: index.php:1359
msgid "Enable menu on extensions page"
msgstr "Activer le menu sur la page des plugins"
#: index.php:1362
msgid "Enable menu on themes page"
msgstr "Activer le menu sur la page des thèmes"
msgid "translater"
msgstr "Traducteur"
msgid "Translate your Dotclear plugins and themes"
msgstr "Traduire vos plugins et thèmes pour Dotclear"