From 12266213d098a53c5f005b9afcbbe62771fd580c Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Tue, 9 May 2017 18:12:15 +0200 Subject: [PATCH] Shaarli's translation * translation system and unit tests * Translations everywhere Dont use translation merge It is not available with PHP builtin gettext, so it would have lead to inconsistency. --- Makefile | 2 +- application/ApplicationUtils.php | 19 +- application/Cache.php | 2 +- application/FeedBuilder.php | 4 +- application/History.php | 4 +- application/Languages.php | 153 +- application/LinkDB.php | 20 +- application/LinkFilter.php | 8 +- application/NetscapeBookmarkUtils.php | 16 +- application/PageBuilder.php | 7 +- application/PluginManager.php | 7 +- application/Updater.php | 8 +- application/Utils.php | 17 +- application/config/ConfigJson.php | 15 +- application/config/ConfigManager.php | 6 +- application/config/ConfigPhp.php | 4 +- .../exception/MissingFieldConfigException.php | 2 +- .../exception/PluginConfigOrderException.php | 2 +- .../exception/UnauthorizedConfigException.php | 2 +- application/exceptions/IOException.php | 2 +- composer.json | 3 +- composer.lock | 217 ++- inc/languages/fr/LC_MESSAGES/shaarli.mo | Bin 0 -> 22943 bytes inc/languages/fr/LC_MESSAGES/shaarli.po | 1243 +++++++++++++++++ index.php | 78 +- plugins/TODO.md | 28 - plugins/addlink_toolbar/addlink_toolbar.php | 13 +- plugins/archiveorg/archiveorg.html | 6 +- plugins/archiveorg/archiveorg.php | 11 +- plugins/demo_plugin/demo_plugin.php | 9 + plugins/isso/isso.php | 17 +- plugins/markdown/help.html | 6 +- plugins/markdown/markdown.php | 21 +- plugins/piwik/piwik.php | 15 +- plugins/playvideos/playvideos.php | 13 +- plugins/pubsubhubbub/pubsubhubbub.php | 16 +- plugins/qrcode/qrcode.meta | 2 +- plugins/qrcode/qrcode.php | 9 + plugins/wallabag/wallabag.html | 6 +- plugins/wallabag/wallabag.php | 20 +- tests/LanguagesTest.php | 184 ++- tests/UtilsTest.php | 30 +- tests/bootstrap.php | 6 + tests/languages/bootstrap.php | 7 +- tests/languages/fr/LanguagesFrTest.php | 173 +++ tests/utils/languages/fr/LC_MESSAGES/test.mo | Bin 0 -> 456 bytes tests/utils/languages/fr/LC_MESSAGES/test.po | 19 + tpl/default/import.html | 8 +- tpl/default/linklist.html | 30 +- tpl/default/page.footer.html | 4 +- tpl/default/pluginsadmin.html | 4 +- 51 files changed, 2252 insertions(+), 246 deletions(-) create mode 100644 inc/languages/fr/LC_MESSAGES/shaarli.mo create mode 100644 inc/languages/fr/LC_MESSAGES/shaarli.po delete mode 100644 plugins/TODO.md create mode 100644 tests/bootstrap.php create mode 100644 tests/languages/fr/LanguagesFrTest.php create mode 100644 tests/utils/languages/fr/LC_MESSAGES/test.mo create mode 100644 tests/utils/languages/fr/LC_MESSAGES/test.po diff --git a/Makefile b/Makefile index 656c27b0..300f1d7f 100644 --- a/Makefile +++ b/Makefile @@ -135,7 +135,7 @@ test: @echo "PHPUNIT" @echo "-------" @mkdir -p sandbox coverage - @$(BIN)/phpunit --coverage-php coverage/main.cov --testsuite unit-tests + @$(BIN)/phpunit --coverage-php coverage/main.cov --bootstrap tests/bootstrap.php --testsuite unit-tests locale_test_%: @UT_LOCALE=$*.utf8 \ diff --git a/application/ApplicationUtils.php b/application/ApplicationUtils.php index 5643f4a0..911873a0 100644 --- a/application/ApplicationUtils.php +++ b/application/ApplicationUtils.php @@ -149,12 +149,13 @@ class ApplicationUtils public static function checkPHPVersion($minVersion, $curVersion) { if (version_compare($curVersion, $minVersion) < 0) { - throw new Exception( + $msg = t( 'Your PHP version is obsolete!' - .' Shaarli requires at least PHP '.$minVersion.', and thus cannot run.' - .' Your PHP version has known security vulnerabilities and should be' - .' updated as soon as possible.' + . ' Shaarli requires at least PHP %s, and thus cannot run.' + . ' Your PHP version has known security vulnerabilities and should be' + . ' updated as soon as possible.' ); + throw new Exception(sprintf($msg, $minVersion)); } } @@ -179,7 +180,7 @@ class ApplicationUtils $rainTplDir.'/'.$conf->get('resource.theme'), ) as $path) { if (! is_readable(realpath($path))) { - $errors[] = '"'.$path.'" directory is not readable'; + $errors[] = '"'.$path.'" '. t('directory is not readable'); } } @@ -191,10 +192,10 @@ class ApplicationUtils $conf->get('resource.raintpl_tmp'), ) as $path) { if (! is_readable(realpath($path))) { - $errors[] = '"'.$path.'" directory is not readable'; + $errors[] = '"'.$path.'" '. t('directory is not readable'); } if (! is_writable(realpath($path))) { - $errors[] = '"'.$path.'" directory is not writable'; + $errors[] = '"'.$path.'" '. t('directory is not writable'); } } @@ -212,10 +213,10 @@ class ApplicationUtils } if (! is_readable(realpath($path))) { - $errors[] = '"'.$path.'" file is not readable'; + $errors[] = '"'.$path.'" '. t('file is not readable'); } if (! is_writable(realpath($path))) { - $errors[] = '"'.$path.'" file is not writable'; + $errors[] = '"'.$path.'" '. t('file is not writable'); } } diff --git a/application/Cache.php b/application/Cache.php index 5d050165..e5d43e61 100644 --- a/application/Cache.php +++ b/application/Cache.php @@ -13,7 +13,7 @@ function purgeCachedPages($pageCacheDir) { if (! is_dir($pageCacheDir)) { - $error = 'Cannot purge '.$pageCacheDir.': no directory'; + $error = sprintf(t('Cannot purge %s: no directory'), $pageCacheDir); error_log($error); return $error; } diff --git a/application/FeedBuilder.php b/application/FeedBuilder.php index 7377bcec..3cfaafb4 100644 --- a/application/FeedBuilder.php +++ b/application/FeedBuilder.php @@ -148,9 +148,9 @@ class FeedBuilder $link['url'] = $pageaddr . $link['url']; } if ($this->usePermalinks === true) { - $permalink = 'Direct link'; + $permalink = ''. t('Direct link') .''; } else { - $permalink = 'Permalink'; + $permalink = ''. t('Permalink') .''; } $link['description'] = format_description($link['description'], '', $pageaddr); $link['description'] .= PHP_EOL .'
— '. $permalink; diff --git a/application/History.php b/application/History.php index 5e3b1b72..35ec016a 100644 --- a/application/History.php +++ b/application/History.php @@ -171,7 +171,7 @@ class History } if (! is_writable($this->historyFilePath)) { - throw new Exception('History file isn\'t readable or writable'); + throw new Exception(t('History file isn\'t readable or writable')); } } @@ -182,7 +182,7 @@ class History { $this->history = FileUtils::readFlatDB($this->historyFilePath, []); if ($this->history === false) { - throw new Exception('Could not parse history file'); + throw new Exception(t('Could not parse history file')); } } diff --git a/application/Languages.php b/application/Languages.php index c8b0a25a..4ba32f29 100644 --- a/application/Languages.php +++ b/application/Languages.php @@ -1,21 +1,150 @@ //LC_MESSAGES/.[po|mo] * - * @param string $text Text to translate. - * @param string $nText The plural message ID. - * @param int $nb The number of items for plural forms. + * Pros/cons: + * - gettext extension is faster + * - gettext is very system dependent (PHP extension, the locale must be installed, and web server reloaded) * - * @return String Text translated. + * Settings: + * - translation.mode: + * - auto: use default setting (PHP implementation) + * - php: use PHP implementation + * - gettext: use gettext wrapper + * - translation.language: + * - auto: use autoLocale() and the language change according to user HTTP headers + * - fixed language: e.g. 'fr' + * - translation.extensions: + * - domain => translation_path: allow plugins and themes to extend the defaut extension + * The domain must be unique, and translation path must be relative, and contains the tree mentioned above. + * + * @package Shaarli */ -function t($text, $nText = '', $nb = 0) { - if (empty($nText)) { - return $text; +class Languages +{ + /** + * Core translations domain + */ + const DEFAULT_DOMAIN = 'shaarli'; + + /** + * @var TranslatorInterface + */ + protected $translator; + + /** + * @var string + */ + protected $language; + + /** + * @var ConfigManager + */ + protected $conf; + + /** + * Languages constructor. + * + * @param string $language lang determined by autoLocale(), can be override. + * @param ConfigManager $conf instance. + */ + public function __construct($language, $conf) + { + $this->conf = $conf; + $confLanguage = $this->conf->get('translation.language', 'auto'); + if ($confLanguage === 'auto' || ! $this->isValidLanguage($confLanguage)) { + $this->language = substr($language, 0, 5); + } else { + $this->language = $confLanguage; + } + + if (! extension_loaded('gettext') + || in_array($this->conf->get('translation.mode', 'auto'), ['auto', 'php']) + ) { + $this->initPhpTranslator(); + } else { + $this->initGettextTranslator(); + } + + // Register default functions (e.g. '__()') to use our Translator + $this->translator->register(); + } + + /** + * Initialize the translator using php gettext extension (gettext dependency act as a wrapper). + */ + protected function initGettextTranslator () + { + $this->translator = new GettextTranslator(); + $this->translator->setLanguage($this->language); + $this->translator->loadDomain(self::DEFAULT_DOMAIN, 'inc/languages'); + + foreach ($this->conf->get('translation.extensions', []) as $domain => $translationPath) { + if ($domain !== self::DEFAULT_DOMAIN) { + $this->translator->loadDomain($domain, $translationPath, false); + } + } + } + + /** + * Initialize the translator using a PHP implementation of gettext. + * + * Note that if language po file doesn't exist, errors are ignored (e.g. not installed language). + */ + protected function initPhpTranslator() + { + $this->translator = new Translator(); + $translations = new Translations(); + // Core translations + try { + /** @var Translations $translations */ + $translations = $translations->addFromPoFile('inc/languages/'. $this->language .'/LC_MESSAGES/shaarli.po'); + $translations->setDomain('shaarli'); + $this->translator->loadTranslations($translations); + } catch (\InvalidArgumentException $e) {} + + + // Extension translations (plugins, themes, etc.). + foreach ($this->conf->get('translation.extensions', []) as $domain => $translationPath) { + if ($domain === self::DEFAULT_DOMAIN) { + continue; + } + + try { + /** @var Translations $extension */ + $extension = Translations::fromPoFile($translationPath . $this->language .'/LC_MESSAGES/'. $domain .'.po'); + $extension->setDomain($domain); + $this->translator->loadTranslations($extension); + } catch (\InvalidArgumentException $e) {} + } + } + + /** + * Checks if a language string is valid. + * + * @param string $language e.g. 'fr' or 'en_US' + * + * @return bool true if valid, false otherwise + */ + protected function isValidLanguage($language) + { + return preg_match('/^[a-z]{2}(_[A-Z]{2})?/', $language) === 1; } - $actualForm = $nb > 1 ? $nText : $text; - return sprintf($actualForm, $nb); } diff --git a/application/LinkDB.php b/application/LinkDB.php index 22c1f0ab..f026a041 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php @@ -133,16 +133,16 @@ class LinkDB implements Iterator, Countable, ArrayAccess { // TODO: use exceptions instead of "die" if (!$this->loggedIn) { - die('You are not authorized to add a link.'); + die(t('You are not authorized to add a link.')); } if (!isset($value['id']) || empty($value['url'])) { - die('Internal Error: A link should always have an id and URL.'); + die(t('Internal Error: A link should always have an id and URL.')); } if (($offset !== null && ! is_int($offset)) || ! is_int($value['id'])) { - die('You must specify an integer as a key.'); + die(t('You must specify an integer as a key.')); } if ($offset !== null && $offset !== $value['id']) { - die('Array offset and link ID must be equal.'); + die(t('Array offset and link ID must be equal.')); } // If the link exists, we reuse the real offset, otherwise new entry @@ -248,13 +248,13 @@ class LinkDB implements Iterator, Countable, ArrayAccess $this->links = array(); $link = array( 'id' => 1, - 'title'=>' Shaarli: the personal, minimalist, super-fast, no-database delicious clone', + 'title'=> t('The personal, minimalist, super-fast, database free, bookmarking service'), 'url'=>'https://shaarli.readthedocs.io', - 'description'=>'Welcome to Shaarli! This is your first public bookmark. To edit or delete me, you must first login. + 'description'=>t('Welcome to Shaarli! This is your first public bookmark. To edit or delete me, you must first login. -To learn how to use Shaarli, consult the link "Help/documentation" at the bottom of this page. +To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page. -You use the community supported version of the original Shaarli project, by Sebastien Sauvage.', +You use the community supported version of the original Shaarli project, by Sebastien Sauvage.'), 'private'=>0, 'created'=> new DateTime(), 'tags'=>'opensource software' @@ -264,9 +264,9 @@ You use the community supported version of the original Shaarli project, by Seba $link = array( 'id' => 0, - 'title'=>'My secret stuff... - Pastebin.com', + 'title'=> t('My secret stuff... - Pastebin.com'), 'url'=>'http://sebsauvage.net/paste/?8434b27936c09649#bR7XsXhoTiLcqCpQbmOpBi3rq2zzQUC5hBI7ZT1O3x8=', - 'description'=>'Shhhh! I\'m a private link only YOU can see. You can delete me too.', + 'description'=> t('Shhhh! I\'m a private link only YOU can see. You can delete me too.'), 'private'=>1, 'created'=> new DateTime('1 minute ago'), 'tags'=>'secretstuff', diff --git a/application/LinkFilter.php b/application/LinkFilter.php index 99ecd1e2..12376e27 100644 --- a/application/LinkFilter.php +++ b/application/LinkFilter.php @@ -444,5 +444,11 @@ class LinkFilter class LinkNotFoundException extends Exception { - protected $message = 'The link you are trying to reach does not exist or has been deleted.'; + /** + * LinkNotFoundException constructor. + */ + public function __construct() + { + $this->message = t('The link you are trying to reach does not exist or has been deleted.'); + } } diff --git a/application/NetscapeBookmarkUtils.php b/application/NetscapeBookmarkUtils.php index 31796367..31a14537 100644 --- a/application/NetscapeBookmarkUtils.php +++ b/application/NetscapeBookmarkUtils.php @@ -32,11 +32,11 @@ class NetscapeBookmarkUtils { // see tpl/export.html for possible values if (! in_array($selection, array('all', 'public', 'private'))) { - throw new Exception('Invalid export selection: "'.$selection.'"'); + throw new Exception(t('Invalid export selection:') .' "'.$selection.'"'); } $bookmarkLinks = array(); - +7 foreach ($linkDb as $link) { if ($link['private'] != 0 && $selection == 'public') { continue; @@ -79,14 +79,14 @@ class NetscapeBookmarkUtils $duration=0 ) { - $status = 'File '.$filename.' ('.$filesize.' bytes) '; + $status = sprintf(t('File %s (%d bytes) '), $filename, $filesize); if ($importCount == 0 && $overwriteCount == 0 && $skipCount == 0) { - $status .= 'has an unknown file format. Nothing was imported.'; + $status .= t('has an unknown file format. Nothing was imported.'); } else { - $status .= 'was successfully processed in '. $duration .' seconds: '; - $status .= $importCount.' links imported, '; - $status .= $overwriteCount.' links overwritten, '; - $status .= $skipCount.' links skipped.'; + $status .= vsprintf( + t('was successfully processed in %d seconds: %d links imported, %d links overwritten, %d links skipped.'), + [$duration, $importCount, $overwriteCount, $skipCount] + ); } return $status; } diff --git a/application/PageBuilder.php b/application/PageBuilder.php index 291860ad..af290671 100644 --- a/application/PageBuilder.php +++ b/application/PageBuilder.php @@ -159,9 +159,12 @@ class PageBuilder * * @param string $message A messate to display what is not found */ - public function render404($message = 'The page you are trying to reach does not exist or has been deleted.') + public function render404($message = '') { - header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found'); + if (empty($message)) { + $message = t('The page you are trying to reach does not exist or has been deleted.'); + } + header($_SERVER['SERVER_PROTOCOL'] .' '. t('404 Not Found')); $this->tpl->assign('error_message', $message); $this->renderPage('404'); } diff --git a/application/PluginManager.php b/application/PluginManager.php index 59ece4fa..cf603845 100644 --- a/application/PluginManager.php +++ b/application/PluginManager.php @@ -188,6 +188,9 @@ class PluginManager $metaData[$plugin] = parse_ini_file($metaFile); $metaData[$plugin]['order'] = array_search($plugin, $this->authorizedPlugins); + if (isset($metaData[$plugin]['description'])) { + $metaData[$plugin]['description'] = t($metaData[$plugin]['description']); + } // Read parameters and format them into an array. if (isset($metaData[$plugin]['parameters'])) { $params = explode(';', $metaData[$plugin]['parameters']); @@ -203,7 +206,7 @@ class PluginManager $metaData[$plugin]['parameters'][$param]['value'] = ''; // Optional parameter description in parameter.PARAM_NAME= if (isset($metaData[$plugin]['parameter.'. $param])) { - $metaData[$plugin]['parameters'][$param]['desc'] = $metaData[$plugin]['parameter.'. $param]; + $metaData[$plugin]['parameters'][$param]['desc'] = t($metaData[$plugin]['parameter.'. $param]); } } } @@ -237,6 +240,6 @@ class PluginFileNotFoundException extends Exception */ public function __construct($pluginName) { - $this->message = 'Plugin "'. $pluginName .'" files not found.'; + $this->message = sprintf(t('Plugin "%s" files not found.'), $pluginName); } } diff --git a/application/Updater.php b/application/Updater.php index 72b2def0..723a7a81 100644 --- a/application/Updater.php +++ b/application/Updater.php @@ -73,7 +73,7 @@ class Updater } if ($this->methods === null) { - throw new UpdaterException('Couldn\'t retrieve Updater class methods.'); + throw new UpdaterException(t('Couldn\'t retrieve Updater class methods.')); } foreach ($this->methods as $method) { @@ -482,7 +482,7 @@ class UpdaterException extends Exception } if (! empty($this->method)) { - $out .= 'An error occurred while running the update '. $this->method . PHP_EOL; + $out .= t('An error occurred while running the update ') . $this->method . PHP_EOL; } if (! empty($this->previous)) { @@ -522,11 +522,11 @@ function read_updates_file($updatesFilepath) function write_updates_file($updatesFilepath, $updates) { if (empty($updatesFilepath)) { - throw new Exception('Updates file path is not set, can\'t write updates.'); + throw new Exception(t('Updates file path is not set, can\'t write updates.')); } $res = file_put_contents($updatesFilepath, implode(';', $updates)); if ($res === false) { - throw new Exception('Unable to write updates in '. $updatesFilepath . '.'); + throw new Exception(t('Unable to write updates in '. $updatesFilepath . '.')); } } diff --git a/application/Utils.php b/application/Utils.php index 4a2f5561..27eaafc5 100644 --- a/application/Utils.php +++ b/application/Utils.php @@ -452,7 +452,7 @@ function get_max_upload_size($limitPost, $limitUpload, $format = true) */ function alphabetical_sort(&$data, $reverse = false, $byKeys = false) { - $callback = function($a, $b) use ($reverse) { + $callback = function ($a, $b) use ($reverse) { // Collator is part of PHP intl. if (class_exists('Collator')) { $collator = new Collator(setlocale(LC_COLLATE, 0)); @@ -470,3 +470,18 @@ function alphabetical_sort(&$data, $reverse = false, $byKeys = false) usort($data, $callback); } } + +/** + * Wrapper function for translation which match the API + * of gettext()/_() and ngettext(). + * + * @param string $text Text to translate. + * @param string $nText The plural message ID. + * @param int $nb The number of items for plural forms. + * @param string $domain The domain where the translation is stored (default: shaarli). + * + * @return String Text translated. + */ +function t($text, $nText = '', $nb = 1, $domain = 'shaarli') { + return dn__($domain, $text, $nText, $nb); +} diff --git a/application/config/ConfigJson.php b/application/config/ConfigJson.php index 9ef2ef56..8c8d5610 100644 --- a/application/config/ConfigJson.php +++ b/application/config/ConfigJson.php @@ -22,10 +22,15 @@ class ConfigJson implements ConfigIO $data = json_decode($data, true); if ($data === null) { $errorCode = json_last_error(); - $error = 'An error occurred while parsing JSON configuration file ('. $filepath .'): error code #'; - $error .= $errorCode. '
➜ ' . json_last_error_msg() .''; + $error = sprintf( + 'An error occurred while parsing JSON configuration file (%s): error code #%d', + $filepath, + $errorCode + ); + $error .= '
➜ ' . json_last_error_msg() .''; if ($errorCode === JSON_ERROR_SYNTAX) { - $error .= '
Please check your JSON syntax (without PHP comment tags) using a JSON lint tool such as '; + $error .= '
'; + $error .= 'Please check your JSON syntax (without PHP comment tags) using a JSON lint tool such as '; $error .= 'jsonlint.com.'; } throw new \Exception($error); @@ -44,8 +49,8 @@ class ConfigJson implements ConfigIO if (!file_put_contents($filepath, $data)) { throw new \IOException( $filepath, - 'Shaarli could not create the config file. - Please make sure Shaarli has the right to write in the folder is it installed in.' + t('Shaarli could not create the config file. '. + 'Please make sure Shaarli has the right to write in the folder is it installed in.') ); } } diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php index 7ff2fe67..9e4c9f63 100644 --- a/application/config/ConfigManager.php +++ b/application/config/ConfigManager.php @@ -132,7 +132,7 @@ class ConfigManager public function set($setting, $value, $write = false, $isLoggedIn = false) { if (empty($setting) || ! is_string($setting)) { - throw new \Exception('Invalid setting key parameter. String expected, got: '. gettype($setting)); + throw new \Exception(t('Invalid setting key parameter. String expected, got: '). gettype($setting)); } // During the ConfigIO transition, map legacy settings to the new ones. @@ -339,6 +339,10 @@ class ConfigManager $this->setEmpty('redirector.url', ''); $this->setEmpty('redirector.encode_url', true); + $this->setEmpty('translation.language', 'auto'); + $this->setEmpty('translation.mode', 'php'); + $this->setEmpty('translation.extensions', []); + $this->setEmpty('plugins', array()); } diff --git a/application/config/ConfigPhp.php b/application/config/ConfigPhp.php index 2633824d..2f66e8e0 100644 --- a/application/config/ConfigPhp.php +++ b/application/config/ConfigPhp.php @@ -118,8 +118,8 @@ class ConfigPhp implements ConfigIO ) { throw new \IOException( $filepath, - 'Shaarli could not create the config file. - Please make sure Shaarli has the right to write in the folder is it installed in.' + t('Shaarli could not create the config file. '. + 'Please make sure Shaarli has the right to write in the folder is it installed in.') ); } } diff --git a/application/config/exception/MissingFieldConfigException.php b/application/config/exception/MissingFieldConfigException.php index 6346c6a9..9e0a9359 100644 --- a/application/config/exception/MissingFieldConfigException.php +++ b/application/config/exception/MissingFieldConfigException.php @@ -18,6 +18,6 @@ class MissingFieldConfigException extends \Exception public function __construct($field) { $this->field = $field; - $this->message = 'Configuration value is required for '. $this->field; + $this->message = sprintf(t('Configuration value is required for %s'), $this->field); } } diff --git a/application/config/exception/PluginConfigOrderException.php b/application/config/exception/PluginConfigOrderException.php index f9d68750..f82ec26e 100644 --- a/application/config/exception/PluginConfigOrderException.php +++ b/application/config/exception/PluginConfigOrderException.php @@ -12,6 +12,6 @@ class PluginConfigOrderException extends \Exception */ public function __construct() { - $this->message = 'An error occurred while trying to save plugins loading order.'; + $this->message = t('An error occurred while trying to save plugins loading order.'); } } diff --git a/application/config/exception/UnauthorizedConfigException.php b/application/config/exception/UnauthorizedConfigException.php index 79672c1b..72311fae 100644 --- a/application/config/exception/UnauthorizedConfigException.php +++ b/application/config/exception/UnauthorizedConfigException.php @@ -13,6 +13,6 @@ class UnauthorizedConfigException extends \Exception */ public function __construct() { - $this->message = 'You are not authorized to alter config.'; + $this->message = t('You are not authorized to alter config.'); } } diff --git a/application/exceptions/IOException.php b/application/exceptions/IOException.php index b563b23d..18e46b77 100644 --- a/application/exceptions/IOException.php +++ b/application/exceptions/IOException.php @@ -16,7 +16,7 @@ class IOException extends Exception public function __construct($path, $message = '') { $this->path = $path; - $this->message = empty($message) ? 'Error accessing' : $message; + $this->message = empty($message) ? t('Error accessing') : $message; $this->message .= ' "' . $this->path .'"'; } } diff --git a/composer.json b/composer.json index afb8aca4..f331d6ca 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,8 @@ "shaarli/netscape-bookmark-parser": "^2.0", "erusev/parsedown": "1.6", "slim/slim": "^3.0", - "pubsubhubbub/publisher": "dev-master" + "pubsubhubbub/publisher": "dev-master", + "gettext/gettext": "^4.4" }, "require-dev": { "phpmd/phpmd" : "@stable", diff --git a/composer.lock b/composer.lock index 435d6a88..ea20025d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "68beedbfa104c788029b079800cfd6e8", + "content-hash": "13b7e1e474fe9264b098ba86face0feb", "packages": [ { "name": "container-interop/container-interop", @@ -76,6 +76,129 @@ ], "time": "2015-10-04T16:44:32+00:00" }, + { + "name": "gettext/gettext", + "version": "v4.4.3", + "source": { + "type": "git", + "url": "https://github.com/oscarotero/Gettext.git", + "reference": "4f57f004635cc6311a20815ebfdc0757cb337113" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/oscarotero/Gettext/zipball/4f57f004635cc6311a20815ebfdc0757cb337113", + "reference": "4f57f004635cc6311a20815ebfdc0757cb337113", + "shasum": "" + }, + "require": { + "gettext/languages": "^2.3", + "php": ">=5.4.0" + }, + "require-dev": { + "illuminate/view": "*", + "phpunit/phpunit": "^4.8|^5.7", + "squizlabs/php_codesniffer": "^3.0", + "symfony/yaml": "~2", + "twig/extensions": "*", + "twig/twig": "^1.31|^2.0" + }, + "suggest": { + "illuminate/view": "Is necessary if you want to use the Blade extractor", + "symfony/yaml": "Is necessary if you want to use the Yaml extractor/generator", + "twig/extensions": "Is necessary if you want to use the Twig extractor", + "twig/twig": "Is necessary if you want to use the Twig extractor" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gettext\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "description": "PHP gettext manager", + "homepage": "https://github.com/oscarotero/Gettext", + "keywords": [ + "JS", + "gettext", + "i18n", + "mo", + "po", + "translation" + ], + "time": "2017-08-09T16:59:46+00:00" + }, + { + "name": "gettext/languages", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/mlocati/cldr-to-gettext-plural-rules.git", + "reference": "49c39e51569963cc917a924b489e7025bfb9d8c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mlocati/cldr-to-gettext-plural-rules/zipball/49c39e51569963cc917a924b489e7025bfb9d8c7", + "reference": "49c39e51569963cc917a924b489e7025bfb9d8c7", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^4" + }, + "bin": [ + "bin/export-plural-rules", + "bin/export-plural-rules.php" + ], + "type": "library", + "autoload": { + "psr-4": { + "Gettext\\Languages\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michele Locati", + "email": "mlocati@gmail.com", + "role": "Developer" + } + ], + "description": "gettext languages with plural rules", + "homepage": "https://github.com/mlocati/cldr-to-gettext-plural-rules", + "keywords": [ + "cldr", + "i18n", + "internationalization", + "l10n", + "language", + "languages", + "localization", + "php", + "plural", + "plural rules", + "plurals", + "translate", + "translations", + "unicode" + ], + "time": "2017-03-23T17:02:28+00:00" + }, { "name": "katzgrau/klogger", "version": "1.2.1", @@ -686,16 +809,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.2.1", + "version": "3.2.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "183824db76118b9dddffc7e522b91fa175f75119" + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/183824db76118b9dddffc7e522b91fa175f75119", - "reference": "183824db76118b9dddffc7e522b91fa175f75119", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157", + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157", "shasum": "" }, "require": { @@ -727,7 +850,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-08-04T20:55:59+00:00" + "time": "2017-08-08T06:39:58+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -1875,20 +1998,20 @@ }, { "name": "symfony/config", - "version": "v3.3.6", + "version": "v3.3.8", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "54ee12b0dd60f294132cabae6f5da9573d2e5297" + "reference": "6ac0cc1f047c1dbc058fc25b7a4d91b068ed4488" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/54ee12b0dd60f294132cabae6f5da9573d2e5297", - "reference": "54ee12b0dd60f294132cabae6f5da9573d2e5297", + "url": "https://api.github.com/repos/symfony/config/zipball/6ac0cc1f047c1dbc058fc25b7a4d91b068ed4488", + "reference": "6ac0cc1f047c1dbc058fc25b7a4d91b068ed4488", "shasum": "" }, "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/filesystem": "~2.8|~3.0" }, "conflict": { @@ -1933,20 +2056,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2017-07-19T07:37:29+00:00" + "time": "2017-08-03T08:59:45+00:00" }, { "name": "symfony/console", - "version": "v2.8.26", + "version": "v2.8.27", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "32a3c6b3398de5db8ed381f4ef92970c59c2fcdd" + "reference": "c0807a2ca978e64d8945d373a9221a5c35d1a253" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/32a3c6b3398de5db8ed381f4ef92970c59c2fcdd", - "reference": "32a3c6b3398de5db8ed381f4ef92970c59c2fcdd", + "url": "https://api.github.com/repos/symfony/console/zipball/c0807a2ca978e64d8945d373a9221a5c35d1a253", + "reference": "c0807a2ca978e64d8945d373a9221a5c35d1a253", "shasum": "" }, "require": { @@ -1994,7 +2117,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-07-29T21:26:04+00:00" + "time": "2017-08-27T14:29:03+00:00" }, { "name": "symfony/debug", @@ -2055,20 +2178,20 @@ }, { "name": "symfony/dependency-injection", - "version": "v3.3.6", + "version": "v3.3.8", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "8d70987f991481e809c63681ffe8ce3f3fde68a0" + "reference": "2ac658972626c75cbde7b0067c84b988170a6907" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/8d70987f991481e809c63681ffe8ce3f3fde68a0", - "reference": "8d70987f991481e809c63681ffe8ce3f3fde68a0", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2ac658972626c75cbde7b0067c84b988170a6907", + "reference": "2ac658972626c75cbde7b0067c84b988170a6907", "shasum": "" }, "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "psr/container": "^1.0" }, "conflict": { @@ -2121,24 +2244,24 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2017-07-28T15:27:31+00:00" + "time": "2017-08-28T22:20:37+00:00" }, { "name": "symfony/filesystem", - "version": "v3.3.6", + "version": "v3.3.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "427987eb4eed764c3b6e38d52a0f87989e010676" + "reference": "b32a0e5f928d0fa3d1dd03c78d020777e50c10cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/427987eb4eed764c3b6e38d52a0f87989e010676", - "reference": "427987eb4eed764c3b6e38d52a0f87989e010676", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b32a0e5f928d0fa3d1dd03c78d020777e50c10cb", + "reference": "b32a0e5f928d0fa3d1dd03c78d020777e50c10cb", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "type": "library", "extra": { @@ -2170,24 +2293,24 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-07-11T07:17:58+00:00" + "time": "2017-07-29T21:54:42+00:00" }, { "name": "symfony/finder", - "version": "v3.3.6", + "version": "v3.3.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4" + "reference": "b2260dbc80f3c4198f903215f91a1ac7fe9fe09e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/baea7f66d30854ad32988c11a09d7ffd485810c4", - "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4", + "url": "https://api.github.com/repos/symfony/finder/zipball/b2260dbc80f3c4198f903215f91a1ac7fe9fe09e", + "reference": "b2260dbc80f3c4198f903215f91a1ac7fe9fe09e", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "type": "library", "extra": { @@ -2219,20 +2342,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-06-01T21:01:25+00:00" + "time": "2017-07-29T21:54:42+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.4.0", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937" + "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7c8fae0ac1d216eb54349e6a8baa57d515fe8803", + "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803", "shasum": "" }, "require": { @@ -2244,7 +2367,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.5-dev" } }, "autoload": { @@ -2278,24 +2401,24 @@ "portable", "shim" ], - "time": "2017-06-09T14:24:12+00:00" + "time": "2017-06-14T15:44:48+00:00" }, { "name": "symfony/yaml", - "version": "v3.3.6", + "version": "v3.3.8", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed" + "reference": "1d8c2a99c80862bdc3af94c1781bf70f86bccac0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/ddc23324e6cfe066f3dd34a37ff494fa80b617ed", - "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed", + "url": "https://api.github.com/repos/symfony/yaml/zipball/1d8c2a99c80862bdc3af94c1781bf70f86bccac0", + "reference": "1d8c2a99c80862bdc3af94c1781bf70f86bccac0", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { "symfony/console": "~2.8|~3.0" @@ -2333,7 +2456,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-07-23T12:43:26+00:00" + "time": "2017-07-29T21:54:42+00:00" }, { "name": "theseer/fdomdocument", diff --git a/inc/languages/fr/LC_MESSAGES/shaarli.mo b/inc/languages/fr/LC_MESSAGES/shaarli.mo new file mode 100644 index 0000000000000000000000000000000000000000..d6b195da781c5e93bc2f2db138f449939003614a GIT binary patch literal 22943 zcmdU%3zTJ5dFK!E5KDRa;Gx1C8k_2ts@o4hp=er)epXY}T~t+f3sLaYy{D=UeeXS& zbIz^qY89d;K4wfbW{epWMU#xQ5tPv+7*Quw2I8pEn1_!z1R3HaIx%Y;6XPTq=lB2i zKIh)*ZXT|zm9^$BcKy$DpS{2Rz4zBV^4yc&9q{`e?Zvd>nL%*n2|@71({(inKK{HQ zcs_U^$bZ2@{CO7mP4EGpdmNnN{DUtDf-Aruf&<|2*+FnBcm;SRI0~K#zSduVJ9rA` z?*@m!_kkyZp9e1nzXZMn{2{m%Jnx(!cn)|II1U~FF9GiduLd6n2f!p!&TN)OUXk)Oha$pAFs* zUI_laKmQKMk_A5iMUVdjs-KHr6a*W=mxJo(7Vy>JA@F+e&%hhNH4q8X1#bj3zdJy! z+Xp~>_ij+@@G($y`V&y&e%zlAKwORYg`n<-;KSg0Q1AbPzy1^OCeF{ez&+OnMaSDf zjqhEc=yDgR`TQ2B@q7l;h0zK?_Aljr=KAUF#=6V&xppy<8}ycC=P_5HVk8rM6( zec%T`{tNz|KXetG9Xh_c9MpHO1@-(ckfjT51g`)Ke|`^mIp+_9uLl1aya@am2Dt;g z9lR2J7!<#qu*%WrOi<%F8`L_U59&K>K}Zu^2_ibdeo*skf#RQALCx!}pw{JGpy=^l z(CFi@KL|=bzTnTl4vN0t2A>Q59jNh~%3!sA=YU$bt3j4B*aE8m*MRz70;<2<!E5Wls&GQye{oV>{UcU%xeSaMkJwFAi{~v&&`%gg0&oddE z-VZ^IXAl%WuLq@9MnQdV+@HS^)bn+ap#-;p8&BYS;7OeS-o@_yhd@2|HBj$A0&1S$ z1+@-81ogd>V5U>R(?Idp^Fcj-G5A_=BdB@b3u;^sfY*Xw0`>lxYux&s2de+`L0umN z#c%6D(Pa;)@ijqx=T`7`@J--W@Wi#y0Ne@cJOOut_kt&bKLYFEKZB=&(M#R+TRe8a z6S=0c-qGzc+$fr#dKp>VN~_&w-l%J3#U8 zUEnPES?~hrf8mf@_iKjT`};taB&dUsDtH@sHFzI*9r(BY{#7Vt$!P@Y{{7%5z`qAY zzmKeQeDZlv^7)v@e*#69v)4O5d$Gq2py;q2+yL(K*Ix%}Uccn;zaJDmJ_KrAJ_?Et z?gLS&!TsRr;2-B)Zj_be zd>NE{d=uRE4CnziIlug6jt(CJpU3&5;F;hLLGi=MFL(U38`O9YfLfmn)VN*`YMj3d z!s5Z_K!zH82bBIl2Vp!7ycL`SZwJNC-vM`lYf)w#1_j8lgL^>n&&NRV%NIb6TgLL4 zzze`@!1F=z`Ar^Q3*N~2uYxy#{~J_46IVHUC7_;9{rTI$kn?we;+s!^n%6hLv%$wf zt=B(-uugC?lNBFc3c`B9^`Q9YHc)hX0Mzqe0i_SW>CgWL)Vll#l>Ru8mqd?2P}eU9 zxfP6p=YqF^F9qKN>bVEO1K?M{*MOT~0^yyY`uo42g6uxzjy)Ogw; zED^i`6g@uyYCZn|Tnl~~d<^_CsQ$injgzmx1UsDnqd#wsI(~a2cm~(+1kVHS0rlO7 zJ$@M!AAAjzJv)^}e+IZ2)I3MQ9pH_i==UK|eDK?#zW=wN^!h)5`u^!#+&bOv@i#!t z>kFXh{s?#u_*dYIKq)mo9lRL40K5qlKffM)9rzIV5^&2lXJ;3{>vSEI96oou>-R!X za(oG>`Cb8PygNbh&8t9t?~ULy!1sgagC7Ld&*wmm?+?L?z^{WRg8u|+{Y3=L^Esft zvkKIB*MTntcY|kw35ZArhryG<`#^o?cR;=Or=Y&`m_PrY9)Ild6ej-`?mrJyfA0m) z0zV3N!Owzv|FSXX-)siee+Ir7d?$Dfcn_%ezYm@Q{sh$epMo$y6AZyq!8M@fu>sUP zCqcdUDo}K3fqL$Bpy=}R;OGfKa0Jxz-(xYDF@-sQcG~8poK& z32+VP*MmdgVenbthrtGTAE^G$zTU}C9n`wM4^;p6f|B>ofSTu5LDB6Ia25D>;2Xem zr--wl{~h2k=YKQp=>4J@7sp%zN~(rK0a>zO8T>MM#y+>c ze*uc0Pu%bNy8v9z`2;9>-UhxDd=sd7-s`XbIjHeG3cdh5{grNBF99WQmx7|l%RtfZ z8h^e66#rZgiVg?-{llQX_Xbeod^3p12VVsxSLfc~?8pV6=(Ggt{da_r z_MM!;aZJ;@KTErZ1}Upwi=+QcYtrte{af0bX&<3|k_KDYya4l?9sxf~)77{1xv{{eoCCf=;ko=9^p({)!j% z)0*5xyOfsGE~ot$ntpGiJw*E|?M&K#qv>}s?PWCajec_uEY8;99sc|rP(1cH?NhY> zNLxoMf0Co$rJYE-vAhTl`{S+PFVbKYvt1{Fe?+^Db_?w?nt1Ur?M<|=)AW0ccB>t^ z*zlMAaor;(H~2%^pZoIi{Ky74*2uG1pkV**`Iej zei?kbKi&d<#vcog(7r|cE!u;$chdBe?q9Mamxu9(2G8*)e+_<`_6>h7dpJY8iFP|} zg0`1-J+1s*z`-xkE~K6AFa9TRmi8*zLE3&=LeuYeXc_JEv@g)Eq`iywFipR!9hj}y z#qlQECukp~y@mE)Y44>?()xd||2!DdcGLcXR{o^__W6_Z!QY^L zoc165wM#q-=4sFN=c~crraeG=EA6|qh^F7`X;;t=(f*Y7A=;nNMrryzN_!*iS7?7m z)9)(Uf2XabJ(qSr?M_;k_UknL{=EaUxhco5rG1Fr!8AJ% z*3&GD>qT=ZOxxj7+ReC~Eyh`G(`>eRB03OM~uXkRC`NMv-RGJoHGzxhQGY!u>Ie zQcqj0n7KXiFp^?05633MsL@~zbA5Vyx5?zL??%mJE{PlA*0dEtwA~EVW*LlzjkuMD zoo08Q>-CgX(F~(zGh|2%OyioPry_23nh|tt#CbB`h9X93|6(IvjGHOEk=N+bU$j+V zFnKtc983;`MHbZ$sP}r>u-Q#7L{ZjE;G_9iFHVlJzV$3Fg3(4J+?^J&9Yo=5wFw zQP=6d!;0`7UDTCkk{32OdTTb->@t*{<1t7PEon?qm@^7^R`ak&!*+boKN`W1LP85vi~AARkIfF@oFXii3KZ*@*Ndaq_MvmWQo$HsKplr_)U8QGu}0NoOINjSJ2h zT|11kjFn33#@3DS;DTO2NHx50*Yuv81`^CJyH^q)F?v(47re=fRe!Ew$6>W(dyed;}#FHWF!_G+W{>ujFw% zPl{wQ4z?^r?fDXVgpP}Xf$?sU6wP=DXvK$F=bNWos^vrX#TBAHSeb#p|uEXgI zsH$YnRM0&0Y9u-8sm*ARL6*qf%KC-1ZetQ_6>*!st8P3yxXFZjr^aEqyoezNT!_TA zkZoh$a4wD;P{Lkyi^ExhhTa0lFsKv>TneLkGyt<{rd{S>O0(pL#i-ehrDZdS4)Gc$ z`J(QM#}2}cTG9r+_!|(jJaXF6bFVH#RCFvy-DbmVgE*3fL%3KQW5WKMXiW{(zFNJ} zokbQGbbYcrJKde#*`1y3&W==1wFe6ZU1SM*DBNp|nT7QxOBJ?aG;ITgu*E6+-U4n# zxh@4;y^gTSbJmPeJ6q$to+TZVvcBW+V1f>SDX|)GF9ebv54IYk8Rv4G%YKyz*O_4~ zb^Ahci&ui34Ex z>_g!+!&VH4sVI1acObV{p-|8mb{139iZXgFwJB_wCG!i#aNW2ianiWzTK`};Bc2{- zAgcoF-FVzs@2Bna*e;)Tk3*84;|#ODkfu!Xcs+NWzQl~pq6LtewuC6y)<_Eb6E{Y} zU|ZW3&A|#DGpRza7z3gnYW~@9YTNWoh{^KjLlScHT%^S6l{7e8nER)COT10GI^MQder&**2uz}2}v=zldmUibC!X2z0gz8!+ z;u&wB#UOYzQMcrvBnTheR$BJvPSQxu{)Rv4T%srFB#Kdk#!sgOLL*W)? z*g_-kLGwk>Jce15w42vzwY6pUm?ihQ?Xqupv};y3u)Rf`uMGpP70ee?j8jmal?K}6 z%wNod?P;^YpDc_cMx}c=fp`^Bc>UBCxiAUKTs!U)?Qk@!FJNnGX*Tbl+mT!w?8G^7 z%v5(m&6S=SM5>)4iyFpBd|JM%vF1)WqZ&hilN2Q|?e0Cb@CJNb`3$p|KPY968q3(? z;dW6Accfu-Fj}ewV@694z4dUH!zWx16n$(-!pWZt7ZsErTjvCp*9Df@F6g448?g9h& zEa3|BibjA)ZEOG++?3JWO{bsLrMrWVA{QY%5EC&(8D2D>s)f@S9?ts! zrC=N%W--Bgf+JlVV&N5WoIH3`D@wI;MRGHWp~lCXX1TZry>Pk4Q^E}WCH4s>qPB%O za?U5PMUC_zLDv#C?9kEYL`nVTZ6Z39w7M<)?!$P*a;4GY!2|*}k;>n8W;BczvG686 z6Y?rBoQ+_@TT>mlV1sxIPC|i%!{KCvYc-31#4H0vNx^PBc|~@1P`P=#<3o6Lgu%P3 z753^Mr>J)=HnU=vFqg2%T-t5B(`0T5*90FuRsf-RA%owfkj?*!8cV?*dC0*YLNXV@ z#)sem^-^iffblwKbh2~=gUO^`D4O06U8<9V?nF_TjGv3gJa-+JH7CdRk6m}OyiJLR zJDVPx*@k2OG!ZMC+j&*ZV%@eV>#I1T*@vsZ%74W*?ZLK#k zkqcu`4RR9GCW!+V9nrBOSP$W<)%hy(ES;O=$?l#(hxdz9`AW(0&VicD%;L()f}cv_ zde%1Ar?k0d6x;Qf*xN{(#fvgX#vPL`@C!UTmERu*;>}9qDZR2C@7)f(r|;C?R9r?e z!BpIeTeC7{0}&M(rs zB8%g7EeUtF&V4H9)P4J+g`(9Qb{;+BTD5s<+vwJbZJX9bn`^-|agP0w|05~FvzQO2 z;|TNafz-&Mf@5zjIC47NrNMN^#g%~#hTcqPdZE|ClvjGkT6QE@vu`#c?kctV*4lMrFnIarx9VvJ&@VhV^ z8*DN7ewT^6WSMT*v)5cVQh&}dkss%o5za(h`2rpt{67-RKt&ocn!->WDcNEN3NJI` zZ|`)h_JgSP-4?T(XSm{K9?U=`i|ax^8M|VM4z!K=O1-=Up#jMVk%C}s7PedpXA=S{ z++m_|bTe5*ll6n~thcn9lQM9f!V)LdDwJJezzE2jbWvaE60|X9MkE@VsfD5n!j1h? zW+}(Akzzo_ET-Qj!CJuC7{lPGhrv)MtXmbkYRr1YXI9+<5|4lJSI~8NiuW{x__Y(} z!mZ7-O{E$5+$xR z4+Oa)jDanXTY?>R)8j6CVT}Zg3~gSl6*rsJs8-kKXo4B#Y=RkVLLTg$8l#P?iJX`m zbS3%A0;eB)EnfhWtMuYtGtfO5@o5vOP3|?57AC9_xP$_EP?t|D7E1Ett__Lj$v!v} z?cc8jdokpeQQ)mIRaFHv>PNAQPfjuCS<1X5s%Tg_UnxPYS}7dl+CK~&qgw)ePGnJ!6q zTqkz_==k{PwWB-aG5l0s?EbjPx=TBh0()UNW7)IZEwuAh9f2x()WVrG#4=ixTd9~K zV}8pUy0^%Vpwhm`Jgl+qp1W#inS+~r7aEmv^har?JE>H3tFZo zL+vt<7}mUOEpwtOdCQ8{2<@bv(T|aWF!xj&&q-r+TQw{6L#PdnuykT}&df|sS1ycR zaZ86Xo$IzO7l*zpj_TGq@!>9_3FqPT(ZdVIQ8{gfo>`KlTzx)}&gQB7vJ0!F_eoZ! zLX?JAT-YnCwbO*ljVps2<+9oYXl7AYb}B1zplvZzOvYb)x7cm6GZUG#lPR)}eB4Vy z#VIEOUedRzlmvD!C2A&JX@pda=E8}d1#;`&2$U~DKuWenW*w^srF+Uwh%-qTHOpQc zd#B1};2)4jGi`eGOZ^wC=kXf@%@z*8rrMP4Ij*-N(i~U`i>~B3luEW1cz%%3I!Qeb+=2%E-pz`WJjl&`^N`wVRo|d1~ACZByH(xP>{yfEV4IFvpbH@K|GbpR*++ zCC3a*?wJ|hB2N|zGfYA-9tk(D-|+I`^_LHCTpw<@bma2OE?K{E{dyi8o+5;jB|6S? zmyK-L;GP>tVuokPW#%Z1G#d#A#@W^BqBe(T;;7a8a(Q_KOMLV8sey^HiEX{{ZK$mu z*g~{Iq&YmZ)L~fiHV6_3U#^ncW3QsPdhg8k;VXL2>8oT-hqtxaF~egS39pzCge1~dgE0} zWpH@)ns&H3+_3hlUPsgDn0ma$jc+7$1FSxCUA&|{s(c*pjTwz>7}|K1#^*=j;+ILr zF}$9U3lNO@r-RYnJ|xjb5;K_Gl>&^Tc(m)` z>H$b|<%F%a5viSIr)HrNe2SB-yOaWST`j<9u0nvr;i3ZQTiJ_hM!kxF2Y=JLg)e$F z0pWw64r4T@_k-~|k*UV=5z=dHq&HY5`Xczlb;BXzqoiM*sVn!q$TVnw&%S1##n3D= zgeJ3SWNAWCKx1(E2)jYbs#r|Cg^Ylbf6I5PXR90_+$QT148lY^Lu4wO;@0LTDM#3}j{B}AVJ~Au2DM#FM;g}hkrtmW z^Phyqi%6g{K#WieMVSI*>K1spx!b$w$OPLOR^Mv-h6iKz1NQcdZ;ou}_%pCJU=?TnXqpP%JGo^qA#1eg$BU7;XG)B5YQW0Y`yz!5AX}q|=(c=+8x7e}^lc0E` zuJl`Tkkl=gw34J82o71B<&Q{nEFYO?A!Y&q!N@KpLBUQsPq0cH6WB(%VEz zu)V>)L}o zMM_2%yQK9q_E}Nx5y2pue#L#uNBRmsSVltB(wahjFR!}nD?jAc5aXa*Tpger8cb0c zp=oF1@p zk*a#6##T~~o4k1suJ5Kr(qQ$1eP~GpSN>3?frA9i=XYbpC=<2^G^HRadeD1Ir9#&mkHvpP4jl8bs_lTa{g#ixx>o z5d3zP2Q=0+pGp+TvEAq;{F%~V${Lh!JoxFL{1!f<4e$TI4~&bqQgVBuPdOyCV zV__U|pmLN>O|jDM067~8M*ZSDv~{-xp;vTXC74L`Gky6Ux?T>63RKEVWE)EcVD%t7 z3rw{v9<3Wm&wlhXjWMAy%r-NkPhzEDALkazFT?k6FCd1RC*M~23S}ppY$A}LwXWxhfY=Nql5PJC^WS3efe!UK89eCrBP7 z3g4wJj;g#^<6L}Kf53W`(|meW7b`wk4Fi2&s@c`95+>oFS)mJuC z3wESbZkm=77x^KXB;>MV<-7=xa5zvj8V>G<{5)lgT)nou54f}R@=!&bRRNu;UT0mJ z3T(P@(hPR**>_^95+k*Bw;~s&oS6=wmVPdbNdN6+1+w z@~}oq6``CiwhL8J+98V7@bWCYlXJ{UF5;Q!HZCl>OMwTflikGSBYx8rL3UEZSFBWr z{(Nv&`a4I6>xgm6`?U}^bopM#rgc0bT)exjlw}rIx{Hgc+;khSvKpz}1U^#+rdEJ6 z5>AwA22G)~g9Kh8Rk~OhxV{n}h3sYcXE7H6*@|)mWtgr@E~&mDCf zOjMk&qay3pnYI0c1=SxOQ$C~;A{P)VIa3|?M=8$=c1e}yUH*XpHPWMU##SUhN~_I) z$yFSEyEM@LRxgK#_i8&rK3pK!y|qj5u4@D~B8a>P1*6iIy(z2ah!}wK5)z=Q1~(0dRhFv`fQ$A~T`V3H^*%_{2#_T)m5D&yTbxmG5} zXQ%LaP-Lc~ED@;Zt*0Vxnq>AIFl?OmoGo!_{q}1gt8g+G3I$5l@1jC|<+Gkln@HTu z?JE^^f98Pny)@XN6|2tZv{5b{j0iUe{Zcla--POwJl@Zaq~OM$k?r@_jeTnm*r4sAdXeeBSq!nb1oE6-1M*9849D6 zG1Y@lT^hC5a)&7R-ujk`#)qpb!??-_uBeh4mB~I*8SaS1fIdr6*@U41c`ELfd?r)*A}C=tvzID1H?uadPi7NY|5vG$+SVp_ zi66!aP%u@dlu-$a3(GnK)pgQ* z82k3@o%W6@Yn{hbkl2nwLS?c!u`r2tG}t`Qj=p6mu;q-ALGUkTTmaxovMfg=kv6M4 z&T<;Vx-+}V#=B1kxxNU{c-;0DG3;a?S3X5q9YUyw#0I^`X0%_*vsFT+M~0qbUpXp1 zhb2SZUQEem88J!bs%XolJ2NTE3Ao^0y8IfphqqyJGulU(=3nf*CX+o3s{W^^=&^QD#ScLzL=R8?K$J~96< z{2HzUq{b{uHMQM7fYn~o@348H_-fdacD$nO%hIeaE2MwDp($3O%*?{_-4q{9iYLp| zju^JT(8~fk=OfCMfGH8aM&bn4?Tr|dmjbYTMUK}ANU%qC^Qe+8@}*>{m50Jo<7~@? z@`CMr95!7Pu9S&F?RRCE1{2&Bc~i%h!C2Euy_S!NPADfz-+WBiV@5u-B4ytTG`)rz zvf6{E{w6NHGd9k?Z{o`Nh=P(Hr2 z_4Qp!O;$UQ_@mle6nV92CW|_*f4%@Mo&OV<`Ou;sx0(!MRnCCYO{IztgMHq$gkmle zRozl$Syz>1K0RblREDkB#qs?>O}j6u+TT}m_S1(|*CKnw@8}54u+;4rhFd5$GBI@f z#uhq3QAbTLEVc-gev0qVsx8}w;34MLuVjZ@l%;=rg?<=}X4$WCm%PtHR(@c>dLcEa z0%Ta!$5h^3q*Fh%s!)x-SZ`B8gqAC6)oeGMT}JJODh6e5ZU85siedCB8|r>}e36<$ zAqcBG`gXUCUnYIchNQ|lRARTXW=)lgA))s%#cIbelo6yaSme% zG0yg&%eYwnrVQ1jIeO_OoBC5dUM-2us?X;=&Wm;I78CBhq7{|hgDl#?wq4JXK}=zD zOC~krU&h#|En(@bqDvJ;2=m>F5YrB?qkU|*eGtl0Ayg2Qxjm~s<0H4kZPfJVldN~g zKTb~J2ZUICaAd4vdwqT!M?Kj$<|n9tGtF7`>~_P-5)Hx`_+UlPrPtY43THj=$1*fM z5ank>fd=N0=4Qm?VjW6l*1;Cs?sHeX(UWr{0|x|m||nc3N{F4&75PB z>RPG(+7dZF@~)2hlDY6!fM^~ZqR%H(IVX2ZGN}|T9A74&++N5EtyGWMc1|IMvHtN=mrwU`Gj=Lg3F1Q}IrvEF>h?_5adV?j z=h0s0TKOOnJNjI<_V*xREu4~DBcI!egtJOwC1=-;%E1RmWgrfuWlbJA1)oi*OhnM< z{MvCZN1Y#Amk0IDbG5yKelG=@IE4n7(?& zdcCrpr|L%4daTdU6mmhf>i48Qe8ry9WhDvW{L+QC6m|py_g~|G%#q5Cs09@3X&Ov) QMYW!b;$eIh>=nWP17x~i3jhEB literal 0 HcmV?d00001 diff --git a/inc/languages/fr/LC_MESSAGES/shaarli.po b/inc/languages/fr/LC_MESSAGES/shaarli.po new file mode 100644 index 00000000..8763581b --- /dev/null +++ b/inc/languages/fr/LC_MESSAGES/shaarli.po @@ -0,0 +1,1243 @@ +msgid "" +msgstr "" +"Project-Id-Version: Shaarli\n" +"POT-Creation-Date: 2017-05-20 13:54+0200\n" +"PO-Revision-Date: 2017-05-20 14:11+0200\n" +"Last-Translator: \n" +"Language-Team: Shaarli\n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.1\n" +"X-Poedit-Basepath: ../../../..\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-KeywordsList: t:1,2;t\n" +"X-Poedit-SearchPath-0: .\n" + +#: application/ApplicationUtils.php:152 +#, php-format +msgid "" +"Your PHP version is obsolete! Shaarli requires at least PHP %s, and thus " +"cannot run. Your PHP version has known security vulnerabilities and should " +"be updated as soon as possible." +msgstr "" +"Votre version de PHP est obsolète ! Shaarli nécessite au moins PHP %s, et ne " +"peut donc pas fonctionner. Votre version de PHP a des failles de sécurités " +"connues et devrait être mise à jour au plus tôt." + +#: application/ApplicationUtils.php:180 application/ApplicationUtils.php:192 +msgid "directory is not readable" +msgstr "le répertoire n'est pas accessible en lecture" + +#: application/ApplicationUtils.php:195 +msgid "directory is not writable" +msgstr "le répertoire n'est pas accessible en écriture" + +#: application/ApplicationUtils.php:213 +msgid "file is not readable" +msgstr "le fichier n'est pas accessible en lecture" + +#: application/ApplicationUtils.php:216 +msgid "file is not writable" +msgstr "le fichier n'est pas accessible en écriture" + +#: application/Cache.php:16 +#, php-format +msgid "Cannot purge %s: no directory" +msgstr "Impossible de purger %s: le répertoire n'existe pas" + +#: application/FeedBuilder.php:146 +msgid "Direct link" +msgstr "Liens directs" + +#: application/FeedBuilder.php:148 +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:88 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:242 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:245 +#: tmp/paper.b91ef64efc3688266305ea9b42e5017e.rtpl.php:88 +msgid "Permalink" +msgstr "Permalien" + +#: application/History.php:158 +msgid "History file isn't readable or writable" +msgstr "Le fichier d'historique n'est pas accessible en lecture ou en écriture" + +#: application/History.php:169 +msgid "Could not parse history file" +msgstr "Format incorrect pour le fichier d'historique" + +#: application/LinkDB.php:136 +msgid "You are not authorized to add a link." +msgstr "Vous n'êtes pas autorisé à ajouter un lien." + +#: application/LinkDB.php:139 +msgid "Internal Error: A link should always have an id and URL." +msgstr "Erreur interne : un lien devrait toujours avoir un ID et une URL." + +#: application/LinkDB.php:142 +msgid "You must specify an integer as a key." +msgstr "Vous devez utiliser un entier comme clé." + +#: application/LinkDB.php:145 +msgid "Array offset and link ID must be equal." +msgstr "La clé du tableau et l'ID du lien doivent être égaux." + +#: application/LinkDB.php:251 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 +msgid "" +"The personal, minimalist, super-fast, database free, bookmarking service" +msgstr "" +"Le gestionnaire de marque-page personnel, minimaliste, et sans base de " +"données" + +#: application/LinkDB.php:253 +msgid "" +"Welcome to Shaarli! This is your first public bookmark. To edit or delete " +"me, you must first login.\n" +"\n" +"To learn how to use Shaarli, consult the link \"Documentation\" at the " +"bottom of this page.\n" +"\n" +"You use the community supported version of the original Shaarli project, by " +"Sebastien Sauvage." +msgstr "" +"Bienvenue sur Shaarli ! Ceci est votre premier marque-page public. Pour me " +"modifier ou me supprimer, vous devez d'abord vous connecter.\n" +"\n" +"Pour apprendre comment utiliser Shaarli, consultez le lien « Documentation » " +"en bas de page.\n" +"\n" +"Vous utilisez la version supportée par la communauté du projet original " +"Shaarli, de Sébastien Sauvage." + +#: application/LinkDB.php:267 +msgid "My secret stuff... - Pastebin.com" +msgstr "Mes trucs secrets... - Pastebin.com" + +#: application/LinkDB.php:269 +msgid "Shhhh! I'm a private link only YOU can see. You can delete me too." +msgstr "" +"Pssst ! Je suis un lien privé que VOUS êtes le seul à voir. Vous pouvez me " +"supprimer aussi." + +#: application/LinkFilter.php:376 +msgid "The link you are trying to reach does not exist or has been deleted." +msgstr "Le lien que vous essayez de consulter n'existe pas ou a été supprimé." + +#: application/NetscapeBookmarkUtils.php:35 +msgid "Invalid export selection:" +msgstr "Sélection d'export invalide :" + +#: application/NetscapeBookmarkUtils.php:80 +#, php-format +msgid "File %s (%d bytes) " +msgstr "Le fichier %s (%d octets) " + +#: application/NetscapeBookmarkUtils.php:82 +msgid "has an unknown file format. Nothing was imported." +msgstr "a un format inconnu. Rien n'a été importé." + +#: application/NetscapeBookmarkUtils.php:85 +#, php-format +msgid "" +"was successfully processed: %d links imported, %d links overwritten, %d " +"links skipped." +msgstr "" +"a été importé avec succès : %d liens importés, %d liens écrasés, %d liens " +"ignorés." + +#: application/PageBuilder.php:159 +msgid "The page you are trying to reach does not exist or has been deleted." +msgstr "La page que vous essayez de consulter n'existe pas ou a été supprimée." + +#: application/PageBuilder.php:161 +#, fuzzy +#| msgid " 404 Not Found" +msgid "404 Not Found" +msgstr "404 Introuvable" + +#: application/PluginManager.php:243 +#, php-format +msgid "Plugin \"%s\" files not found." +msgstr "Les fichiers de l'extension \"%s\" sont introuvables." + +#: application/Updater.php:76 +msgid "Couldn't retrieve Updater class methods." +msgstr "Impossible de récupérer les méthodes de la classe Updater." + +#: application/Updater.php:500 +msgid "An error occurred while running the update " +msgstr "Une erreur s'est produite lors de l'exécution de la mise à jour " + +#: application/Updater.php:540 +msgid "Updates file path is not set, can't write updates." +msgstr "" +"Le chemin vers le fichier de mise à jour n'est pas défini, impossible " +"d'écrire les mises à jour." + +#: application/Updater.php:545 +msgid "Unable to write updates in " +msgstr "Impossible d'écrire les mises à jour dans " + +#: application/Utils.php:402 tests/UtilsTest.php:398 +msgid "Setting not set" +msgstr "Paramètre non défini" + +#: application/Utils.php:409 tests/UtilsTest.php:396 tests/UtilsTest.php:397 +msgid "Unlimited" +msgstr "Illimité" + +#: application/Utils.php:412 tests/UtilsTest.php:393 tests/UtilsTest.php:394 +#: tests/UtilsTest.php:408 +msgid "B" +msgstr "o" + +#: application/Utils.php:412 tests/UtilsTest.php:387 tests/UtilsTest.php:388 +#: tests/UtilsTest.php:395 +msgid "kiB" +msgstr "ko" + +#: application/Utils.php:412 tests/UtilsTest.php:389 tests/UtilsTest.php:390 +#: tests/UtilsTest.php:406 tests/UtilsTest.php:407 +msgid "MiB" +msgstr "Mo" + +#: application/Utils.php:412 tests/UtilsTest.php:391 tests/UtilsTest.php:392 +msgid "GiB" +msgstr "Go" + +#: application/config/ConfigJson.php:26 +#, php-format +msgid "" +"An error occurred while parsing JSON configuration file (%s): error code #%d" +msgstr "" +"Une erreur s'est produite lors de la lecture du fichier de configuration " +"JSON (%s) : code d'erreur #%d" + +#: application/config/ConfigJson.php:33 +msgid "" +"Please check your JSON syntax (without PHP comment tags) using a JSON lint " +"tool such as " +msgstr "" +"Merci de vérifier la syntaxe JSON (sans les balises de commentaires PHP) en " +"utilisant un validateur de JSON tel que " + +#: application/config/ConfigJson.php:52 application/config/ConfigPhp.php:121 +msgid "" +"Shaarli could not create the config file. Please make sure Shaarli has the " +"right to write in the folder is it installed in." +msgstr "" +"Shaarli n'a pas pu créer le fichier de configuration. Merci de vérifier que " +"Shaarli a les droits d'écriture dans le dossier dans lequel il est installé." + +#: application/config/ConfigManager.php:135 +msgid "Invalid setting key parameter. String expected, got: " +msgstr "Clé de paramétrage invalide. Chaîne de caractères obtenue, attendu :" + +#: application/config/exception/MissingFieldConfigException.php:21 +#, php-format +msgid "Configuration value is required for %s" +msgstr "Le paramètre %s est obligatoire" + +#: application/config/exception/PluginConfigOrderException.php:15 +msgid "An error occurred while trying to save plugins loading order." +msgstr "" +"Une erreur s'est produite lors de la sauvegarde de l'ordre des extensions." + +#: application/config/exception/UnauthorizedConfigException.php:16 +msgid "You are not authorized to alter config." +msgstr "Vous n'êtes pas autorisé à modifier la configuration." + +#: application/exceptions/IOException.php:19 +msgid "Error accessing" +msgstr "Une erreur s'est produite en accédant à" + +#: index.php:48 +msgid "" +"Error: missing Composer dependencies\n" +"\n" +"If you installed Shaarli through Git or using the development branch,\n" +"please refer to the installation documentation to install PHP dependencies " +"using Composer:\n" +msgstr "" +"Erreur : les dépendances Composer sont manquantes\n" +"\n" +"Si vous avez installé Shaarli avec Git ou depuis la branche de " +"développement\n" +"merci de consulter la documentation d'installation pour installer les " +"dépendances Composer :\n" +"\n" + +#: index.php:137 +msgid "Shared links on " +msgstr "Liens partagés sur " + +#: index.php:168 +msgid "Insufficient permissions:" +msgstr "Permissions insuffisantes :" + +#: index.php:415 +msgid "I said: NO. You are banned for the moment. Go away." +msgstr "NON. Vous êtes banni pour le moment. Revenez plus tard." + +#: index.php:479 +msgid "Wrong login/password." +msgstr "Nom d'utilisateur ou mot de passe incorrects." + +#: index.php:1072 +msgid "You are not supposed to change a password on an Open Shaarli." +msgstr "" +"Vous n'êtes pas censé modifier le mot de passe d'un Shaarli en mode ouvert." + +#: index.php:1077 index.php:1118 index.php:1189 index.php:1243 index.php:1350 +msgid "Wrong token." +msgstr "Jeton invalide." + +#: index.php:1082 +msgid "The old password is not correct." +msgstr "L'ancien mot de passe est incorrect." + +#: index.php:1102 +msgid "Your password has been changed" +msgstr "Votre mot de passe a été modifié" + +#: index.php:1153 +msgid "Configuration was saved." +msgstr "La configuration a été sauvegardé." + +#: index.php:1206 +#, php-format +msgid "Tag was removed from %d links." +msgstr "Le tag a été supprimé de %d liens." + +#: index.php:1225 +#, php-format +msgid "Tag was renamed in %d links." +msgstr "Le tag a été renommé dans %d liens." + +#: index.php:1544 +#, php-format +msgid "" +"The file you are trying to upload is probably bigger than what this " +"webserver can accept (%s). Please upload in smaller chunks." +msgstr "" +"Le fichier que vous essayer d'envoyer est probablement plus lourd que ce que " +"le serveur web peut accepter (%s). Merci de l'envoyer en parties plus " +"légères." + +#: index.php:1941 +#, php-format +msgid "" +"
Sessions do not seem to work correctly on your server.
Make sure the " +"variable \"session.save_path\" is set correctly in your PHP config, and that " +"you have write access to it.
It currently points to %s.
On some " +"browsers, accessing your server via a hostname like 'localhost' or any " +"custom hostname without a dot causes cookie storage to fail. We recommend " +"accessing your server via it's IP address or Fully Qualified Domain Name.
" +msgstr "" +"
Les sesssions ne semble pas fonctionner sur ce serveur.
Assurez vous " +"que la variable « session.save_path » est correctement définie dans votre " +"fichier de configuration PHP, et que vous y avez les droits d'écriture." +"
Ce paramètre pointe actuellement sur %s.
Sur certains navigateurs, " +"accéder à votre serveur depuis un nom d'hôte comme « localhost » ou autre " +"nom personnalisé sans point '.' entraine l'échec de la sauvegarde des " +"cookies. Nous vous recommandons d'accéder à votre serveur depuis son adresse " +"IP ou un Fully Qualified Domain Name.
" + +#: index.php:1951 +msgid "Click to try again." +msgstr "Cliquer ici pour réessayer." + +#: plugins/addlink_toolbar/addlink_toolbar.php:29 +msgid "URI" +msgstr "URI" + +#: plugins/addlink_toolbar/addlink_toolbar.php:33 +#: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +msgid "Add link" +msgstr "Shaare" + +#: plugins/addlink_toolbar/addlink_toolbar.php:50 +msgid "Adds the addlink input on the linklist page." +msgstr "Ajout le formulaire d'ajout de liens sur la page principale." + +#: plugins/archiveorg/archiveorg.php:23 +msgid "View on archive.org" +msgstr "Voir sur archive.org" + +#: plugins/archiveorg/archiveorg.php:36 +msgid "For each link, add an Archive.org icon." +msgstr "Pour chaque lien, ajoute une icône pour Archive.org." + +#: plugins/demo_plugin/demo_plugin.php:443 +msgid "" +"A demo plugin covering all use cases for template designers and plugin " +"developers." +msgstr "" +"Une extension de démonstration couvrant tous les cas d'utilisation pour les " +"designers et les développeurs." + +#: plugins/isso/isso.php:20 +msgid "" +"Isso plugin error: Please define the \"ISSO_SERVER\" setting in the plugin " +"administration page." +msgstr "" +"Erreur de l'extension Isso : Merci de définir le paramètre « ISSO_SERVER » " +"dans la page d'administration des extensions." + +#: plugins/isso/isso.php:63 +msgid "Let visitor comment your shaares on permalinks with Isso." +msgstr "" +"Permet aux visiteurs de commenter vos shaares sur les permaliens avec Isso." + +#: plugins/isso/isso.php:64 +msgid "Isso server URL (without 'http://')" +msgstr "URL du serveur Isso (sans 'http://')" + +#: plugins/markdown/markdown.php:150 +msgid "Description will be rendered with" +msgstr "La description sera générée avec" + +#: plugins/markdown/markdown.php:151 +msgid "Markdown syntax documentation" +msgstr "Documentation sur la syntaxe Markdown" + +#: plugins/markdown/markdown.php:152 +msgid "Markdown syntax" +msgstr "la syntaxe Markdown" + +#: plugins/markdown/markdown.php:311 +msgid "" +"Render shaare description with Markdown syntax.
Warning:\n" +"If your shaared descriptions contained HTML tags before enabling the " +"markdown plugin,\n" +"enabling it might break your page.\n" +"See the README." +msgstr "" +"Utilise la syntaxe Markdown pour la description des liens." +"
Attention :\n" +"Si vous aviez des descriptions contenant du HTML avant d'activer cette " +"extension,\n" +"l'activer pourrait déformer vos pages.\n" +"Voir le README." + +#: plugins/piwik/piwik.php:21 +msgid "" +"Piwik plugin error: Please define PIWIK_URL and PIWIK_SITEID in the plugin " +"administration page." +msgstr "" +"Erreur de l'extension Piwik : Merci de définir les paramètres PIWIK_URL et " +"PIWIK_SITEID dans la page d'administration des extensions." + +#: plugins/piwik/piwik.php:70 +msgid "A plugin that adds Piwik tracking code to Shaarli pages." +msgstr "Ajoute le code de traçage de Piwik sur les pages de Shaarli." + +#: plugins/piwik/piwik.php:71 +msgid "Piwik URL" +msgstr "URL de Piwik" + +#: plugins/piwik/piwik.php:72 +msgid "Piwik site ID" +msgstr "Site ID de Piwik" + +#: plugins/playvideos/playvideos.php:22 +msgid "Video player" +msgstr "Lecteur vidéo" + +#: plugins/playvideos/playvideos.php:25 +msgid "Play Videos" +msgstr "Jouer les vidéos" + +#: plugins/playvideos/playvideos.php:56 +msgid "Add a button in the toolbar allowing to watch all videos." +msgstr "" +"Ajoute un bouton dans la barre de menu pour regarder toutes les vidéos." + +#: plugins/playvideos/youtube_playlist.js:214 +msgid "plugins/playvideos/jquery-1.11.2.min.js" +msgstr "" + +#: plugins/pubsubhubbub/pubsubhubbub.php:69 +#, php-format +msgid "Could not publish to PubSubHubbub: %s" +msgstr "Impossible de publier vers PubSubHubbub : %s" + +#: plugins/pubsubhubbub/pubsubhubbub.php:95 +#, php-format +msgid "Could not post to %s" +msgstr "Impossible de publier vers %s" + +#: plugins/pubsubhubbub/pubsubhubbub.php:99 +#, php-format +msgid "Bad response from the hub %s" +msgstr "Mauvaise réponse du hub %s" + +#: plugins/pubsubhubbub/pubsubhubbub.php:110 +msgid "Enable PubSubHubbub feed publishing." +msgstr "Active la publication de flux vers PubSubHubbub" + +#: plugins/qrcode/qrcode.php:69 plugins/wallabag/wallabag.php:68 +msgid "For each link, add a QRCode icon." +msgstr "Pour chaque liens, ajouter une icône de QRCode." + +#: plugins/wallabag/wallabag.php:21 +msgid "" +"Wallabag plugin error: Please define the \"WALLABAG_URL\" setting in the " +"plugin administration page." +msgstr "" +"Erreur de l'extension Wallabag : Merci de définir le paramètre « " +"WALLABAG_URL » dans la page d'administration des extensions." + +#: plugins/wallabag/wallabag.php:47 +msgid "Save to wallabag" +msgstr "Sauvegarder dans Wallabag" + +#: plugins/wallabag/wallabag.php:69 +msgid "Wallabag API URL" +msgstr "URL de l'API Wallabag " + +#: plugins/wallabag/wallabag.php:70 +msgid "Wallabag API version (1 or 2)" +msgstr "Version de l'API Wallabag (1 ou 2)" + +#: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 +msgid "Shaare a new link" +msgstr "Partager un nouveau lien" + +#: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "URL or leave empty to post a note" +msgstr "URL ou laisser vide pour créer une note" + +#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 +msgid "Change password" +msgstr "Modification du mot de passe" + +#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Current password" +msgstr "Mot de passe actuel" + +#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +msgid "New password" +msgstr "Nouveau mot de passe\t" + +#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23 +msgid "Change" +msgstr "Changer" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 +msgid "Manage tags" +msgstr "Gérer les tags" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:77 +msgid "Tag" +msgstr "Tag" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 +msgid "New name" +msgstr "Nouveau nom" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 +msgid "Case sensitive" +msgstr "Sensible à la casse" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 +msgid "Rename" +msgstr "Renommer" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35 +#: tmp/editlink.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:60 +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:71 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:288 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:313 +msgid "Delete" +msgstr "Supprimer" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 +msgid "Configure" +msgstr "Configurer" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 +msgid "title" +msgstr "titre" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 +msgid "Home link" +msgstr "Lien vers l'accueil" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 +msgid "Default value" +msgstr "Valeur par défaut" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58 +msgid "Theme" +msgstr "Thème" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:87 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:63 +msgid "Timezone" +msgstr "Fuseau horaire" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:88 +msgid "Continent" +msgstr "Continent" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:88 +msgid "City" +msgstr "Ville" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:134 +msgid "Redirector" +msgstr "Redirecteur" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:135 +msgid "e. g." +msgstr "ex :" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:135 +msgid "will mask the HTTP_REFERER" +msgstr "masque le HTTP_REFERER" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 +msgid "Disable session cookie hijacking protection" +msgstr "Désactiver la protection contre le détournement de cookies" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:152 +msgid "Check this if you get disconnected or if your IP address changes often" +msgstr "" +"Cocher cette case si vous êtes souvent déconnecté ou si votre adresse IP " +"change souvent" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 +msgid "Private links by default" +msgstr "Liens privés par défaut" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:170 +msgid "All new links are private by default" +msgstr "Tous les nouveaux liens sont privés par défaut" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:185 +msgid "RSS direct links" +msgstr "Liens directs dans le flux RSS" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:186 +msgid "Check this to use direct URL instead of permalink in feeds" +msgstr "" +"Cocher cette case pour utiliser des liens directs au lieu des permaliens " +"dans le flux RSS" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:201 +msgid "Hide public links" +msgstr "Cacher les liens publics" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:202 +msgid "Do not show any links if the user is not logged in" +msgstr "N'afficher aucun lien sans être connecté" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:217 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:95 +msgid "Check updates" +msgstr "Vérifier les mises à jour" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:218 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:97 +msgid "Notify me when a new release is ready" +msgstr "Me notifier lorsqu'une nouvelle version est disponible" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:233 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:114 +msgid "Enable REST API" +msgstr "Activer l'API REST" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:234 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:115 +msgid "Allow third party software to use Shaarli such as mobile application" +msgstr "" +"Permets aux applications tierces d'utiliser Shaarli, par exemple les " +"applications mobiles" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:249 +msgid "API secret" +msgstr "Clé d'API secrète" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:260 +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:66 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:192 +msgid "Save" +msgstr "Enregistrer" + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 +#: tmp/paper.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 +msgid "The Daily Shaarli" +msgstr "Le Quotidien Shaarli" + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 +#: tmp/paper.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 +msgid "1 RSS entry per day" +msgstr "1 entrée RSS par jour" + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:37 +#: tmp/paper.b91ef64efc3688266305ea9b42e5017e.rtpl.php:37 +msgid "Previous day" +msgstr "Jour précédent" + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 +#: tmp/paper.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 +msgid "All links of one day in a single page." +msgstr "Tous les liens d'un jour sur une page." + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:51 +#: tmp/paper.b91ef64efc3688266305ea9b42e5017e.rtpl.php:51 +msgid "Next day" +msgstr "Jour suivant" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:26 +msgid "Shaare" +msgstr "Shaare" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21 +msgid "URL" +msgstr "URL" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:27 +msgid "Title" +msgstr "Titre" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:33 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:75 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:99 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:124 +msgid "Description" +msgstr "Description" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:39 +msgid "Tags" +msgstr "Tags" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:52 +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:177 +msgid "Private" +msgstr "Privé" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Export Database" +msgstr "Exporter les données" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 +msgid "Selection" +msgstr "Choisir" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 +msgid "All" +msgstr "Tous" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 +msgid "Public" +msgstr "Publics" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:52 +msgid "Prepend note permalinks with this Shaarli instance's URL" +msgstr "Préfixer les liens de notes avec l'URL de l'instance de Shaarli" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:53 +msgid "Useful to import bookmarks in a web browser" +msgstr "Utile pour importer les marques-pages dans un navigateur" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65 +msgid "Export" +msgstr "Exporter" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Import Database" +msgstr "Importer des données" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23 +msgid "Maximum size allowed:" +msgstr "Taille maximum autorisée :" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 +msgid "Visibility" +msgstr "Visibilité" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 +msgid "Use values from the imported file, default to public" +msgstr "" +"Utiliser les valeurs présentes dans le fichier d'import, public par défaut" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 +msgid "Import all bookmarks as private" +msgstr "Importer tous les liens comme privés" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 +msgid "Import all bookmarks as public" +msgstr "Importer tous les liens comme publics" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:57 +msgid "Overwrite existing bookmarks" +msgstr "Remplacer les liens existants" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58 +msgid "Duplicates based on URL" +msgstr "Les doublons s'appuient sur les URL" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 +msgid "Add default tags" +msgstr "Ajouter des tags par défaut" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:83 +msgid "Import" +msgstr "Importer" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 +msgid "Install Shaarli" +msgstr "Installation de Shaarli" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:25 +msgid "It looks like it's the first time you run Shaarli. Please configure it." +msgstr "" +"Il semblerait que ça soit la première fois que vous lancez Shaarli. Merci de " +"le configurer." + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:33 +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:149 +msgid "Username" +msgstr "Nom d'utilisateur" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:150 +msgid "Password" +msgstr "Mot de passe" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:80 +msgid "Shaarli title" +msgstr "Titre du Shaarli" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 +msgid "My links" +msgstr "Mes liens" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:127 +msgid "Install" +msgstr "Installer" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:87 +msgid "shaare" +msgid_plural "shaares" +msgstr[0] "shaare" +msgstr[1] "shaares" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:18 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:91 +msgid "private link" +msgid_plural "private links" +msgstr[0] "lien privé" +msgstr[1] "liens privés" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:119 +msgid "Search text" +msgstr "Recherche texte" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:131 +msgid "Filter by tag" +msgstr "Filtrer par tag" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:118 +msgid "Nothing found." +msgstr "Aucun résultat." + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:126 +#, php-format +msgid "%s result" +msgid_plural "%s results" +msgstr[0] "%s résultat" +msgstr[1] "%s résultats" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:130 +msgid "for" +msgstr "pour" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:137 +msgid "tagged" +msgstr "taggé" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:141 +msgid "Remove tag" +msgstr "Retirer le tag" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 +msgid "with status" +msgstr "avec le statut" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:181 +msgid "Edit" +msgstr "Modifier" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:182 +msgid "Fold" +msgstr "Replier" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:245 +msgid "Edited: " +msgstr "Modifié :" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:257 +msgid "permalink" +msgstr "permalien" + +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:7 +msgid "Filters" +msgstr "Filtres" + +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:12 +msgid "Filter private links" +msgstr "Filtrer par liens privés" + +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:63 +msgid "Links per page" +msgstr "Liens par page" + +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 +msgid "" +"You have been banned after too many failed login attempts. Try again later." +msgstr "" +"Vous avez été banni après trop d'échec d'authentification. Merci de " +"réessayer plus tard." + +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:71 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:95 +msgid "Login" +msgstr "Connexion" + +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:39 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:153 +msgid "Remember me" +msgstr "Rester connecté" + +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 +msgid "by the Shaarli community" +msgstr "par la communauté Shaarli" + +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:15 +msgid "Documentation" +msgstr "Documentation" + +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:31 +msgid "Tools" +msgstr "Outils" + +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:36 +#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +#: tmp/tagcloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Tag cloud" +msgstr "Nuage de tags" + +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:39 +msgid "Picture wall" +msgstr "Mur d'images" + +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:42 +msgid "Daily" +msgstr "Quotidien" + +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:61 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:86 +msgid "RSS Feed" +msgstr "Flux RSS" + +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:66 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:102 +msgid "Logout" +msgstr "Déconnexion" + +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:81 +msgid "Search" +msgstr "Rechercher" + +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:171 +msgid "is available" +msgstr "est disponible" + +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:178 +msgid "Error" +msgstr "Erreur" + +#: tmp/picwall.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Picture Wall" +msgstr "Mur d'images" + +#: tmp/picwall.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "pics" +msgstr "images" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 +msgid "You need to enable Javascript to change plugin loading order." +msgstr "" +"Vous devez activer Javascript pour pouvoir modifier l'ordre des extensions." + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 +msgid "Plugin administration" +msgstr "Administration des extensions" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 +msgid "Enabled Plugins" +msgstr "Extensions activées" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:155 +msgid "No plugin enabled." +msgstr "Aucune extension activée." + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:40 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:73 +msgid "Disable" +msgstr "Désactiver" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:98 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:123 +msgid "Name" +msgstr "Nom" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76 +msgid "Order" +msgstr "Ordre" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 +msgid "Disabled Plugins" +msgstr "Extensions désactivées" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:91 +msgid "No plugin disabled." +msgstr "Aucune extension désactivée." + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:97 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:122 +msgid "Enable" +msgstr "Activer" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:134 +msgid "More plugins available" +msgstr "Plus d'extensions disponibles" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:136 +msgid "in the documentation" +msgstr "dans la documentation" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 +msgid "Plugin configuration" +msgstr "Configuration des extensions" + +#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +#: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +#: tmp/tagcloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "tags" +msgstr "tags" + +#: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +msgid "Tag list" +msgstr "List des tags" + +#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:3 +msgid "Sort by:" +msgstr "Trier par :" + +#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:5 +msgid "Cloud" +msgstr "Nuage" + +#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:6 +msgid "Most used" +msgstr "Plus utilisés" + +#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:7 +msgid "Alphabetical" +msgstr "Alphabétique" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 +msgid "Settings" +msgstr "Paramètres" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Change Shaarli settings: title, timezone, etc." +msgstr "Changer les paramètres de Shaarli : titre, fuseau horaire, etc." + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 +msgid "Configure your Shaarli" +msgstr "Conguration de Shaarli" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21 +msgid "Enable, disable and configure plugins" +msgstr "Activer, désactiver et configurer les extensions" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 +msgid "Change your password" +msgstr "Modification du mot de passe" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35 +msgid "Rename or delete a tag in all links" +msgstr "Rename or delete a tag in all links" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 +msgid "" +"Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, " +"delicious...)" +msgstr "" +"Importer des marques pages au format Netscape HTML (comme exportés depuis " +"Firefox, Chrome, Opera, delicious...)" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 +msgid "Import links" +msgstr "Importer des liens" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47 +msgid "" +"Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, " +"Opera, delicious...)" +msgstr "" +"Exporter les marques pages au format Netscape HTML (comme exportés depuis " +"Firefox, Chrome, Opera, delicious...)" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 +msgid "Export database" +msgstr "Exporter les données" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:71 +msgid "" +"Drag one of these button to your bookmarks toolbar or right-click it and " +"\"Bookmark This Link\"" +msgstr "" +"Glisser un de ces bouttons dans votre barre de favoris ou cliquer droit " +"dessus et « Ajouter aux favoris »" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 +msgid "then click on the bookmarklet in any page you want to share." +msgstr "" +"puis cliquer sur le marque page depuis un site que vous souhaitez partager." + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:95 +msgid "" +"Drag this link to your bookmarks toolbar or right-click it and Bookmark This " +"Link" +msgstr "" +"Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « " +"Ajouter aux favoris »" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:77 +msgid "then click ✚Shaare link button in any page you want to share" +msgstr "puis cliquer sur ✚Shaare depuis un site que vous souhaitez partager" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:91 +msgid "Shaare link" +msgstr "Shaare" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:96 +msgid "" +"Then click ✚Add Note button anytime to start composing a private Note (text " +"post) to your Shaarli" +msgstr "" +"Puis cliquer sur ✚Add Note pour commencer à rédiger une Note sur Shaarli" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:99 +msgid "Add Note" +msgstr "Ajouter une Note" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:111 +msgid "" +"You need to browse your Shaarli over HTTPS to use this " +"functionality." +msgstr "" +"Vous devez utiliser Shaarli en HTTPS pour utiliser cette " +"fonctionalité." + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:116 +msgid "Add to" +msgstr "Ajouter à" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:127 +msgid "3rd party" +msgstr "Applications tierces" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:129 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:135 +msgid "Plugin" +msgstr "Extension" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:130 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:136 +msgid "plugin" +msgstr "extension" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:157 +msgid "" +"Drag this link to your bookmarks toolbar, or right-click it and choose " +"Bookmark This Link" +msgstr "" +"Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « " +"Ajouter aux favoris »" + +#~ msgid "Sessions do not seem to work correctly on your server." +#~ msgstr "Les sessions ne semblent " + +#~ msgid "Tag was renamed in " +#~ msgstr "Le tag a été renommé dans " + +#, fuzzy +#~| msgid "My links" +#~ msgid " links" +#~ msgstr "Mes liens" + +#, fuzzy +#~| msgid "" +#~| "Error: missing Composer configuration\n" +#~| "\n" +#~ msgid "Error: missing Composer configuration" +#~ msgstr "" +#~ "Erreur : la configuration Composer est manquante\n" +#~ "\n" + +#, fuzzy +#~| msgid "" +#~| "Shaarli could not create the config file. Please make sure Shaarli has " +#~| "the right to write in the folder is it installed in." +#~ msgid "" +#~ "Shaarli could not create the config file. \n" +#~ " Please make sure Shaarli has the right to write in the " +#~ "folder is it installed in." +#~ msgstr "" +#~ "Shaarli n'a pas pu créer le fichier de configuration. Merci de vérifier " +#~ "que Shaarli a les droits d'écriture dans le dossier dans lequel il est " +#~ "installé." + +#, fuzzy +#~| msgid "Plugin" +#~ msgid "Plugin \"" +#~ msgstr "Extension" + +#~ msgid "Your PHP version is obsolete!" +#~ msgstr "Votre version de PHP est obsolète !" + +#~ msgid " Shaarli requires at least PHP " +#~ msgstr "Shaarli nécessite au moins PHP" diff --git a/index.php b/index.php index 4068a828..98171d78 100644 --- a/index.php +++ b/index.php @@ -64,7 +64,6 @@ require_once 'application/FeedBuilder.php'; require_once 'application/FileUtils.php'; require_once 'application/History.php'; require_once 'application/HttpUtils.php'; -require_once 'application/Languages.php'; require_once 'application/LinkDB.php'; require_once 'application/LinkFilter.php'; require_once 'application/LinkUtils.php'; @@ -76,6 +75,7 @@ require_once 'application/Utils.php'; require_once 'application/PluginManager.php'; require_once 'application/Router.php'; require_once 'application/Updater.php'; +use \Shaarli\Languages; use \Shaarli\ThemeUtils; use \Shaarli\Config\ConfigManager; @@ -121,8 +121,16 @@ if (isset($_COOKIE['shaarli']) && !is_session_id_valid($_COOKIE['shaarli'])) { } $conf = new ConfigManager(); + +// Sniff browser language and set date format accordingly. +if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + autoLocale($_SERVER['HTTP_ACCEPT_LANGUAGE']); +} + +new Languages(setlocale(LC_MESSAGES, 0), $conf); + $conf->setEmpty('general.timezone', date_default_timezone_get()); -$conf->setEmpty('general.title', 'Shared links on '. escape(index_url($_SERVER))); +$conf->setEmpty('general.title', t('Shared links on '). escape(index_url($_SERVER))); RainTPL::$tpl_dir = $conf->get('resource.raintpl_tpl').'/'.$conf->get('resource.theme').'/'; // template directory RainTPL::$cache_dir = $conf->get('resource.raintpl_tmp'); // cache directory @@ -144,7 +152,7 @@ if (! is_file($conf->getConfigFileExt())) { $errors = ApplicationUtils::checkResourcePermissions($conf); if ($errors != array()) { - $message = '

Insufficient permissions:

    '; + $message = '

    '. t('Insufficient permissions:') .'

      '; foreach ($errors as $error) { $message .= '
    • '.$error.'
    • '; @@ -163,11 +171,6 @@ if (! is_file($conf->getConfigFileExt())) { // a token depending of deployment salt, user password, and the current ip define('STAY_SIGNED_IN_TOKEN', sha1($conf->get('credentials.hash') . $_SERVER['REMOTE_ADDR'] . $conf->get('credentials.salt'))); -// Sniff browser language and set date format accordingly. -if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - autoLocale($_SERVER['HTTP_ACCEPT_LANGUAGE']); -} - /** * Checking session state (i.e. is the user still logged in) * @@ -376,7 +379,7 @@ function ban_canLogin($conf) // Process login form: Check if login/password is correct. if (isset($_POST['login'])) { - if (!ban_canLogin($conf)) die('I said: NO. You are banned for the moment. Go away.'); + if (!ban_canLogin($conf)) die(t('I said: NO. You are banned for the moment. Go away.')); if (isset($_POST['password']) && tokenOk($_POST['token']) && (check_auth($_POST['login'], $_POST['password'], $conf)) @@ -440,7 +443,8 @@ if (isset($_POST['login'])) } } } - echo ''; // Redirect to login screen. + // Redirect to login screen. + echo ''; exit; } } @@ -1100,16 +1104,19 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) if ($targetPage == Router::$PAGE_CHANGEPASSWORD) { if ($conf->get('security.open_shaarli')) { - die('You are not supposed to change a password on an Open Shaarli.'); + die(t('You are not supposed to change a password on an Open Shaarli.')); } if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) { - if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away! + if (!tokenOk($_POST['token'])) die(t('Wrong token.')); // Go away! // Make sure old password is correct. $oldhash = sha1($_POST['oldpassword'].$conf->get('credentials.login').$conf->get('credentials.salt')); - if ($oldhash!= $conf->get('credentials.hash')) { echo ''; exit; } + if ($oldhash!= $conf->get('credentials.hash')) { + echo ''; + exit; + } // Save new password // Salt renders rainbow-tables attacks useless. $conf->set('credentials.salt', sha1(uniqid('', true) .'_'. mt_rand())); @@ -1127,7 +1134,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) echo ''; exit; } - echo ''; + echo ''; exit; } else // show the change password form. @@ -1143,7 +1150,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) if (!empty($_POST['title']) ) { if (!tokenOk($_POST['token'])) { - die('Wrong token.'); // Go away! + die(t('Wrong token.')); // Go away! } $tz = 'UTC'; if (!empty($_POST['continent']) && !empty($_POST['city']) @@ -1178,7 +1185,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) echo ''; exit; } - echo ''; + echo ''; exit; } else // Show the configuration form. @@ -1215,7 +1222,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) } if (!tokenOk($_POST['token'])) { - die('Wrong token.'); + die(t('Wrong token.')); } $alteredLinks = $LINKSDB->renameTag(escape($_POST['fromtag']), escape($_POST['totag'])); @@ -1244,7 +1251,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) { // Go away! if (! tokenOk($_POST['token'])) { - die('Wrong token.'); + die(t('Wrong token.')); } // lf_id should only be present if the link exists. @@ -1344,7 +1351,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) if ($targetPage == Router::$PAGE_DELETELINK) { if (! tokenOk($_GET['token'])) { - die('Wrong token.'); + die(t('Wrong token.')); } $ids = trim($_GET['lf_linkdate']); @@ -1550,11 +1557,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history) // Import bookmarks from an uploaded file if (isset($_FILES['filetoupload']['size']) && $_FILES['filetoupload']['size'] == 0) { // The file is too big or some form field may be missing. - echo ''; + $msg = sprintf( + t( + 'The file you are trying to upload is probably bigger than what this webserver can accept' + .' (%s). Please upload in smaller chunks.' + ), + get_max_upload_size(ini_get('post_max_size'), ini_get('upload_max_filesize')) + ); + echo ''; exit; } if (! tokenOk($_POST['token'])) { @@ -1962,12 +1972,20 @@ function install($conf) // (Because on some hosts, session.save_path may not be set correctly, // or we may not have write access to it.) if (isset($_GET['test_session']) && ( !isset($_SESSION) || !isset($_SESSION['session_tested']) || $_SESSION['session_tested']!='Working')) - { // Step 2: Check if data in session is correct. - echo '
      Sessions do not seem to work correctly on your server.
      '; - echo 'Make sure the variable session.save_path is set correctly in your php config, and that you have write access to it.
      '; - echo 'It currently points to '.session_save_path().'
      '; - echo 'Check that the hostname used to access Shaarli contains a dot. On some browsers, accessing your server via a hostname like \'localhost\' or any custom hostname without a dot causes cookie storage to fail. We recommend accessing your server via it\'s IP address or Fully Qualified Domain Name.
      '; - echo '
      Click to try again.
      '; + { + // Step 2: Check if data in session is correct. + $msg = t( + '
      Sessions do not seem to work correctly on your server.
      '. + 'Make sure the variable "session.save_path" is set correctly in your PHP config, '. + 'and that you have write access to it.
      '. + 'It currently points to %s.
      '. + 'On some browsers, accessing your server via a hostname like \'localhost\' '. + 'or any custom hostname without a dot causes cookie storage to fail. '. + 'We recommend accessing your server via it\'s IP address or Fully Qualified Domain Name.
      ' + ); + $msg = sprintf($msg, session_save_path()); + echo $msg; + echo '
      '. t('Click to try again.') .'
      '; die; } if (!isset($_SESSION['session_tested'])) diff --git a/plugins/TODO.md b/plugins/TODO.md deleted file mode 100644 index e3313d67..00000000 --- a/plugins/TODO.md +++ /dev/null @@ -1,28 +0,0 @@ -https://github.com/shaarli/Shaarli/issues/181 - Add Disqus or Isso comments box on a permalink page - - * http://posativ.org/isso/ - * install debian package https://packages.debian.org/sid/isso - * configure server http://posativ.org/isso/docs/configuration/server/ - * configure client http://posativ.org/isso/docs/configuration/client/ - * http://posativ.org/isso/docs/quickstart/ and add `` to includes.html template; then add `
      ` in the linklist template where you want the comments (in the linklist_plugins loop for example) - - -Problem: by default, Isso thread ID is guessed from the current url (only one thread per page). -if we want multiple threads on a single page (shaarli linklist), we must use : the `data-isso-id` client config, -with data-isso-id being the permalink of an item. - -`
      ` -`data-isso-id: Set a custom thread id, defaults to current URI.` - -Problem: feature is currently broken https://github.com/posativ/isso/issues/27 - -Another option, only display isso threads when current URL is a permalink (`\?(A-Z|a-z|0-9|-){7}`) (only show thread -when displaying only this link), and just display a "comments" button on each linklist item. Optionally show the comment -count on each item using the API (http://posativ.org/isso/docs/extras/api/#get-comment-count). API requests can be done -by raintpl `{function` or client-side with js. The former should be faster if isso and shaarli are on ther same server. - -Showing all full isso threads in the linklist would destroy layout - ------------------------------------------------------------ - -http://www.git-attitude.fr/2014/11/04/git-rerere/ for the merge diff --git a/plugins/addlink_toolbar/addlink_toolbar.php b/plugins/addlink_toolbar/addlink_toolbar.php index ddf50aaf..8c05a231 100644 --- a/plugins/addlink_toolbar/addlink_toolbar.php +++ b/plugins/addlink_toolbar/addlink_toolbar.php @@ -26,11 +26,11 @@ function hook_addlink_toolbar_render_header($data) array( 'type' => 'text', 'name' => 'post', - 'placeholder' => 'URI', + 'placeholder' => t('URI'), ), array( 'type' => 'submit', - 'value' => 'Add link', + 'value' => t('Add link'), 'class' => 'bigbutton', ), ), @@ -40,3 +40,12 @@ function hook_addlink_toolbar_render_header($data) return $data; } + +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function addlink_toolbar_dummy_translation() +{ + // meta + t('Adds the addlink input on the linklist page.'); +} diff --git a/plugins/archiveorg/archiveorg.html b/plugins/archiveorg/archiveorg.html index 0781fe35..ad501f47 100644 --- a/plugins/archiveorg/archiveorg.html +++ b/plugins/archiveorg/archiveorg.html @@ -1 +1,5 @@ -archive.org + + + archive.org + + diff --git a/plugins/archiveorg/archiveorg.php b/plugins/archiveorg/archiveorg.php index 03d13d0e..cda35751 100644 --- a/plugins/archiveorg/archiveorg.php +++ b/plugins/archiveorg/archiveorg.php @@ -20,9 +20,18 @@ function hook_archiveorg_render_linklist($data) if($value['private'] && preg_match('/^\?[a-zA-Z0-9-_@]{6}($|&|#)/', $value['real_url'])) { continue; } - $archive = sprintf($archive_html, $value['url']); + $archive = sprintf($archive_html, $value['url'], t('View on archive.org')); $value['link_plugin'][] = $archive; } return $data; } + +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function archiveorg_dummy_translation() +{ + // meta + t('For each link, add an Archive.org icon.'); +} diff --git a/plugins/demo_plugin/demo_plugin.php b/plugins/demo_plugin/demo_plugin.php index 8fdbf663..3a90ae6a 100644 --- a/plugins/demo_plugin/demo_plugin.php +++ b/plugins/demo_plugin/demo_plugin.php @@ -433,3 +433,12 @@ function hook_demo_plugin_render_feed($data) } return $data; } + +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function demo_dummy_translation() +{ + // meta + t('A demo plugin covering all use cases for template designers and plugin developers.'); +} diff --git a/plugins/isso/isso.php b/plugins/isso/isso.php index ce16645f..5bc1cce2 100644 --- a/plugins/isso/isso.php +++ b/plugins/isso/isso.php @@ -4,10 +4,11 @@ * Plugin Isso. */ +use Shaarli\Config\ConfigManager; + /** * Display an error everywhere if the plugin is enabled without configuration. * - * @param $data array List of links * @param $conf ConfigManager instance * * @return mixed - linklist data with Isso plugin. @@ -16,8 +17,8 @@ function isso_init($conf) { $issoUrl = $conf->get('plugins.ISSO_SERVER'); if (empty($issoUrl)) { - $error = 'Isso plugin error: '. - 'Please define the "ISSO_SERVER" setting in the plugin administration page.'; + $error = t('Isso plugin error: '. + 'Please define the "ISSO_SERVER" setting in the plugin administration page.'); return array($error); } } @@ -52,3 +53,13 @@ function hook_isso_render_linklist($data, $conf) return $data; } + +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function isso_dummy_translation() +{ + // meta + t('Let visitor comment your shaares on permalinks with Isso.'); + t('Isso server URL (without \'http://\')'); +} diff --git a/plugins/markdown/help.html b/plugins/markdown/help.html index 9c4e5ae0..ded3d347 100644 --- a/plugins/markdown/help.html +++ b/plugins/markdown/help.html @@ -1,5 +1,5 @@
      - Description will be rendered with - - Markdown syntax. + %s + + %s.
      diff --git a/plugins/markdown/markdown.php b/plugins/markdown/markdown.php index 772c56e8..1531549d 100644 --- a/plugins/markdown/markdown.php +++ b/plugins/markdown/markdown.php @@ -154,8 +154,13 @@ function hook_markdown_render_includes($data) function hook_markdown_render_editlink($data) { // Load help HTML into a string - $data['edit_link_plugin'][] = file_get_contents(PluginManager::$PLUGINS_PATH .'/markdown/help.html'); - + $txt = file_get_contents(PluginManager::$PLUGINS_PATH .'/markdown/help.html'); + $translations = [ + t('Description will be rendered with'), + t('Markdown syntax documentation'), + t('Markdown syntax'), + ]; + $data['edit_link_plugin'][] = vsprintf($txt, $translations); // Add no markdown 'meta-tag' in tag list if it was never used, for autocompletion. if (! in_array(NO_MD_TAG, $data['tags'])) { $data['tags'][NO_MD_TAG] = 0; @@ -325,3 +330,15 @@ function process_markdown($description, $escape = true, $allowedProtocols = []) return $processedDescription; } + +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function markdown_dummy_translation() +{ + // meta + t('Render shaare description with Markdown syntax.
      Warning: +If your shaared descriptions contained HTML tags before enabling the markdown plugin, +enabling it might break your page. +See the README.'); +} diff --git a/plugins/piwik/piwik.php b/plugins/piwik/piwik.php index 4a2b48a1..ca00c2be 100644 --- a/plugins/piwik/piwik.php +++ b/plugins/piwik/piwik.php @@ -18,8 +18,8 @@ function piwik_init($conf) $piwikUrl = $conf->get('plugins.PIWIK_URL'); $piwikSiteid = $conf->get('plugins.PIWIK_SITEID'); if (empty($piwikUrl) || empty($piwikSiteid)) { - $error = 'Piwik plugin error: ' . - 'Please define PIWIK_URL and PIWIK_SITEID in the plugin administration page.'; + $error = t('Piwik plugin error: ' . + 'Please define PIWIK_URL and PIWIK_SITEID in the plugin administration page.'); return array($error); } } @@ -60,3 +60,14 @@ function hook_piwik_render_footer($data, $conf) return $data; } + +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function piwik_dummy_translation() +{ + // meta + t('A plugin that adds Piwik tracking code to Shaarli pages.'); + t('Piwik URL'); + t('Piwik site ID'); +} diff --git a/plugins/playvideos/playvideos.php b/plugins/playvideos/playvideos.php index 64484504..c6d6b0cc 100644 --- a/plugins/playvideos/playvideos.php +++ b/plugins/playvideos/playvideos.php @@ -19,10 +19,10 @@ function hook_playvideos_render_header($data) $playvideo = array( 'attr' => array( 'href' => '#', - 'title' => 'Video player', + 'title' => t('Video player'), 'id' => 'playvideos', ), - 'html' => '► Play Videos' + 'html' => '► '. t('Play Videos') ); $data['buttons_toolbar'][] = $playvideo; } @@ -46,3 +46,12 @@ function hook_playvideos_render_footer($data) return $data; } + +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function playvideos_dummy_translation() +{ + // meta + t('Add a button in the toolbar allowing to watch all videos.'); +} diff --git a/plugins/pubsubhubbub/pubsubhubbub.php b/plugins/pubsubhubbub/pubsubhubbub.php index 03b6757b..184b588b 100644 --- a/plugins/pubsubhubbub/pubsubhubbub.php +++ b/plugins/pubsubhubbub/pubsubhubbub.php @@ -10,6 +10,7 @@ */ use pubsubhubbub\publisher\Publisher; +use Shaarli\Config\ConfigManager; /** * Plugin init function - set the hub to the default appspot one. @@ -65,7 +66,7 @@ function hook_pubsubhubbub_save_link($data, $conf) $p = new Publisher($conf->get('plugins.PUBSUBHUB_URL')); $p->publish_update($feeds, $httpPost); } catch (Exception $e) { - error_log('Could not publish to PubSubHubbub: ' . $e->getMessage()); + error_log(sprintf(t('Could not publish to PubSubHubbub: %s'), $e->getMessage())); } return $data; @@ -91,11 +92,20 @@ function nocurl_http_post($url, $postString) { $context = stream_context_create($params); $fp = @fopen($url, 'rb', false, $context); if (!$fp) { - throw new Exception('Could not post to '. $url); + throw new Exception(sprintf(t('Could not post to %s'), $url)); } $response = @stream_get_contents($fp); if ($response === false) { - throw new Exception('Bad response from the hub '. $url); + throw new Exception(sprintf(t('Bad response from the hub %s'), $url)); } return $response; } + +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function pubsubhubbub_dummy_translation() +{ + // meta + t('Enable PubSubHubbub feed publishing.'); +} diff --git a/plugins/qrcode/qrcode.meta b/plugins/qrcode/qrcode.meta index cbf371ea..1812cd21 100644 --- a/plugins/qrcode/qrcode.meta +++ b/plugins/qrcode/qrcode.meta @@ -1 +1 @@ -description="For each link, add a QRCode icon ." +description="For each link, add a QRCode icon." diff --git a/plugins/qrcode/qrcode.php b/plugins/qrcode/qrcode.php index 8bc610d1..0f96a106 100644 --- a/plugins/qrcode/qrcode.php +++ b/plugins/qrcode/qrcode.php @@ -59,3 +59,12 @@ function hook_qrcode_render_includes($data) return $data; } + +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function qrcode_dummy_translation() +{ + // meta + t('For each link, add a QRCode icon.'); +} diff --git a/plugins/wallabag/wallabag.html b/plugins/wallabag/wallabag.html index e861536d..4c57691d 100644 --- a/plugins/wallabag/wallabag.html +++ b/plugins/wallabag/wallabag.html @@ -1 +1,5 @@ -wallabag + + + wallabag + + diff --git a/plugins/wallabag/wallabag.php b/plugins/wallabag/wallabag.php index 641e4cc2..9dfd079e 100644 --- a/plugins/wallabag/wallabag.php +++ b/plugins/wallabag/wallabag.php @@ -5,6 +5,7 @@ */ require_once 'WallabagInstance.php'; +use Shaarli\Config\ConfigManager; /** * Init function, return an error if the server is not set. @@ -17,8 +18,8 @@ function wallabag_init($conf) { $wallabagUrl = $conf->get('plugins.WALLABAG_URL'); if (empty($wallabagUrl)) { - $error = 'Wallabag plugin error: '. - 'Please define the "WALLABAG_URL" setting in the plugin administration page.'; + $error = t('Wallabag plugin error: '. + 'Please define the "WALLABAG_URL" setting in the plugin administration page.'); return array($error); } } @@ -43,12 +44,14 @@ function hook_wallabag_render_linklist($data, $conf) $wallabagHtml = file_get_contents(PluginManager::$PLUGINS_PATH . '/wallabag/wallabag.html'); + $linkTitle = t('Save to wallabag'); foreach ($data['links'] as &$value) { $wallabag = sprintf( $wallabagHtml, $wallabagInstance->getWallabagUrl(), urlencode($value['url']), - PluginManager::$PLUGINS_PATH + PluginManager::$PLUGINS_PATH, + $linkTitle ); $value['link_plugin'][] = $wallabag; } @@ -56,3 +59,14 @@ function hook_wallabag_render_linklist($data, $conf) return $data; } +/** + * This function is never called, but contains translation calls for GNU gettext extraction. + */ +function wallabag_dummy_translation() +{ + // meta + t('For each link, add a QRCode icon.'); + t('Wallabag API URL'); + t('Wallabag API version (1 or 2)'); +} + diff --git a/tests/LanguagesTest.php b/tests/LanguagesTest.php index 79c136c8..46bfcd72 100644 --- a/tests/LanguagesTest.php +++ b/tests/LanguagesTest.php @@ -1,41 +1,201 @@ conf = new ConfigManager(self::$configFile); + } + + /** + * Test t() with a simple non identified value. + */ + public function testTranslateSingleNotIDGettext() + { + $this->conf->set('translation.mode', 'gettext'); + new Languages('en', $this->conf); + $text = 'abcdé 564 fgK'; + $this->assertEquals($text, t($text)); + } + + /** + * Test t() with a simple identified value in gettext mode. + */ + public function testTranslateSingleIDGettext() + { + $this->conf->set('translation.mode', 'gettext'); + new Languages('en', $this->conf); + $text = 'permalink'; + $this->assertEquals($text, t($text)); + } + + /** + * Test t() with a non identified plural form in gettext mode. + */ + public function testTranslatePluralNotIDGettext() + { + $this->conf->set('translation.mode', 'gettext'); + new Languages('en', $this->conf); + $text = 'sandwich'; + $nText = 'sandwiches'; + $this->assertEquals('sandwiches', t($text, $nText, 0)); + $this->assertEquals('sandwich', t($text, $nText, 1)); + $this->assertEquals('sandwiches', t($text, $nText, 2)); + } + + /** + * Test t() with an identified plural form in gettext mode. + */ + public function testTranslatePluralIDGettext() + { + $this->conf->set('translation.mode', 'gettext'); + new Languages('en', $this->conf); + $text = 'shaare'; + $nText = 'shaares'; + // In english, zero is followed by plural form + $this->assertEquals('shaares', t($text, $nText, 0)); + $this->assertEquals('shaare', t($text, $nText, 1)); + $this->assertEquals('shaares', t($text, $nText, 2)); + } + /** * Test t() with a simple non identified value. */ - public function testTranslateSingleNotID() + public function testTranslateSingleNotIDPhp() { + $this->conf->set('translation.mode', 'php'); + new Languages('en', $this->conf); $text = 'abcdé 564 fgK'; $this->assertEquals($text, t($text)); } /** - * Test t() with a non identified plural form. + * Test t() with a simple identified value in PHP mode. */ - public function testTranslatePluralNotID() + public function testTranslateSingleIDPhp() { - $text = '%s sandwich'; - $nText = '%s sandwiches'; - $this->assertEquals('0 sandwich', t($text, $nText)); - $this->assertEquals('1 sandwich', t($text, $nText, 1)); - $this->assertEquals('2 sandwiches', t($text, $nText, 2)); + $this->conf->set('translation.mode', 'php'); + new Languages('en', $this->conf); + $text = 'permalink'; + $this->assertEquals($text, t($text)); } /** - * Test t() with a non identified invalid plural form. + * Test t() with a non identified plural form in PHP mode. */ - public function testTranslatePluralNotIDInvalid() + public function testTranslatePluralNotIDPhp() { + $this->conf->set('translation.mode', 'php'); + new Languages('en', $this->conf); $text = 'sandwich'; $nText = 'sandwiches'; + $this->assertEquals('sandwiches', t($text, $nText, 0)); $this->assertEquals('sandwich', t($text, $nText, 1)); $this->assertEquals('sandwiches', t($text, $nText, 2)); } + + /** + * Test t() with an identified plural form in PHP mode. + */ + public function testTranslatePluralIDPhp() + { + $this->conf->set('translation.mode', 'php'); + new Languages('en', $this->conf); + $text = 'shaare'; + $nText = 'shaares'; + // In english, zero is followed by plural form + $this->assertEquals('shaares', t($text, $nText, 0)); + $this->assertEquals('shaare', t($text, $nText, 1)); + $this->assertEquals('shaares', t($text, $nText, 2)); + } + + /** + * Test t() with an invalid language set in the configuration in gettext mode. + */ + public function testTranslateWithInvalidConfLanguageGettext() + { + $this->conf->set('translation.mode', 'gettext'); + $this->conf->set('translation.language', 'nope'); + new Languages('fr', $this->conf); + $text = 'grumble'; + $this->assertEquals($text, t($text)); + } + + /** + * Test t() with an invalid language set in the configuration in PHP mode. + */ + public function testTranslateWithInvalidConfLanguagePhp() + { + $this->conf->set('translation.mode', 'php'); + $this->conf->set('translation.language', 'nope'); + new Languages('fr', $this->conf); + $text = 'grumble'; + $this->assertEquals($text, t($text)); + } + + /** + * Test t() with an invalid language set with auto language in gettext mode. + */ + public function testTranslateWithInvalidAutoLanguageGettext() + { + $this->conf->set('translation.mode', 'gettext'); + new Languages('nope', $this->conf); + $text = 'grumble'; + $this->assertEquals($text, t($text)); + } + + /** + * Test t() with an invalid language set with auto language in PHP mode. + */ + public function testTranslateWithInvalidAutoLanguagePhp() + { + $this->conf->set('translation.mode', 'php'); + new Languages('nope', $this->conf); + $text = 'grumble'; + $this->assertEquals($text, t($text)); + } + + /** + * Test t() with an extension language file in gettext mode + */ + public function testTranslationExtensionGettext() + { + $this->conf->set('translation.mode', 'gettext'); + $this->conf->set('translation.extensions.test', 'tests/utils/languages/'); + new Languages('en', $this->conf); + $this->assertEquals('car', t('car', 'car', 1, 'test')); + $this->assertEquals('Search', t('Search', 'Search', 1, 'test')); + } + + /** + * Test t() with an extension language file in PHP mode + */ + public function testTranslationExtensionPhp() + { + $this->conf->set('translation.mode', 'php'); + $this->conf->set('translation.extensions.test', 'tests/utils/languages/'); + new Languages('en', $this->conf); + $this->assertEquals('car', t('car', 'car', 1, 'test')); + $this->assertEquals('Search', t('Search', 'Search', 1, 'test')); + } } diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index 3d1aa653..840eaf21 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -384,18 +384,18 @@ class UtilsTest extends PHPUnit_Framework_TestCase */ public function testHumanBytes() { - $this->assertEquals('2kiB', human_bytes(2 * 1024)); - $this->assertEquals('2kiB', human_bytes(strval(2 * 1024))); - $this->assertEquals('2MiB', human_bytes(2 * (pow(1024, 2)))); - $this->assertEquals('2MiB', human_bytes(strval(2 * (pow(1024, 2))))); - $this->assertEquals('2GiB', human_bytes(2 * (pow(1024, 3)))); - $this->assertEquals('2GiB', human_bytes(strval(2 * (pow(1024, 3))))); - $this->assertEquals('374B', human_bytes(374)); - $this->assertEquals('374B', human_bytes('374')); - $this->assertEquals('232kiB', human_bytes(237481)); - $this->assertEquals('Unlimited', human_bytes('0')); - $this->assertEquals('Unlimited', human_bytes(0)); - $this->assertEquals('Setting not set', human_bytes('')); + $this->assertEquals('2'. t('kiB'), human_bytes(2 * 1024)); + $this->assertEquals('2'. t('kiB'), human_bytes(strval(2 * 1024))); + $this->assertEquals('2'. t('MiB'), human_bytes(2 * (pow(1024, 2)))); + $this->assertEquals('2'. t('MiB'), human_bytes(strval(2 * (pow(1024, 2))))); + $this->assertEquals('2'. t('GiB'), human_bytes(2 * (pow(1024, 3)))); + $this->assertEquals('2'. t('GiB'), human_bytes(strval(2 * (pow(1024, 3))))); + $this->assertEquals('374'. t('B'), human_bytes(374)); + $this->assertEquals('374'. t('B'), human_bytes('374')); + $this->assertEquals('232'. t('kiB'), human_bytes(237481)); + $this->assertEquals(t('Unlimited'), human_bytes('0')); + $this->assertEquals(t('Unlimited'), human_bytes(0)); + $this->assertEquals(t('Setting not set'), human_bytes('')); } /** @@ -403,9 +403,9 @@ class UtilsTest extends PHPUnit_Framework_TestCase */ public function testGetMaxUploadSize() { - $this->assertEquals('1MiB', get_max_upload_size(2097152, '1024k')); - $this->assertEquals('1MiB', get_max_upload_size('1m', '2m')); - $this->assertEquals('100B', get_max_upload_size(100, 100)); + $this->assertEquals('1'. t('MiB'), get_max_upload_size(2097152, '1024k')); + $this->assertEquals('1'. t('MiB'), get_max_upload_size('1m', '2m')); + $this->assertEquals('100'. t('B'), get_max_upload_size(100, 100)); } /** diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 00000000..d36d73cd --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,6 @@ +conf = new ConfigManager(self::$configFile); + $this->conf->set('translation.language', 'fr'); + } + + /** + * Reset the locale since gettext seems to mess with it, making it too long + */ + public static function tearDownAfterClass() + { + if (! empty(getenv('UT_LOCALE'))) { + setlocale(LC_ALL, getenv('UT_LOCALE')); + } + } + + /** + * Test t() with a simple non identified value. + */ + public function testTranslateSingleNotIDGettext() + { + $this->conf->set('translation.mode', 'gettext'); + new Languages('en', $this->conf); + $text = 'abcdé 564 fgK'; + $this->assertEquals($text, t($text)); + } + + /** + * Test t() with a simple identified value in gettext mode. + */ + public function testTranslateSingleIDGettext() + { + $this->conf->set('translation.mode', 'gettext'); + new Languages('en', $this->conf); + $text = 'permalink'; + $this->assertEquals('permalien', t($text)); + } + + /** + * Test t() with a non identified plural form in gettext mode. + */ + public function testTranslatePluralNotIDGettext() + { + $this->conf->set('translation.mode', 'gettext'); + new Languages('en', $this->conf); + $text = 'sandwich'; + $nText = 'sandwiches'; + // Not ID, so English fallback, and in english, plural 0 + $this->assertEquals('sandwiches', t($text, $nText, 0)); + $this->assertEquals('sandwich', t($text, $nText, 1)); + $this->assertEquals('sandwiches', t($text, $nText, 2)); + } + + /** + * Test t() with an identified plural form in gettext mode. + */ + public function testTranslatePluralIDGettext() + { + $this->conf->set('translation.mode', 'gettext'); + new Languages('en', $this->conf); + $text = 'shaare'; + $nText = 'shaares'; + $this->assertEquals('shaare', t($text, $nText, 0)); + $this->assertEquals('shaare', t($text, $nText, 1)); + $this->assertEquals('shaares', t($text, $nText, 2)); + } + + /** + * Test t() with a simple non identified value. + */ + public function testTranslateSingleNotIDPhp() + { + $this->conf->set('translation.mode', 'php'); + new Languages('en', $this->conf); + $text = 'abcdé 564 fgK'; + $this->assertEquals($text, t($text)); + } + + /** + * Test t() with a simple identified value in PHP mode. + */ + public function testTranslateSingleIDPhp() + { + $this->conf->set('translation.mode', 'php'); + new Languages('en', $this->conf); + $text = 'permalink'; + $this->assertEquals('permalien', t($text)); + } + + /** + * Test t() with a non identified plural form in PHP mode. + */ + public function testTranslatePluralNotIDPhp() + { + $this->conf->set('translation.mode', 'php'); + new Languages('en', $this->conf); + $text = 'sandwich'; + $nText = 'sandwiches'; + // Not ID, so English fallback, and in english, plural 0 + $this->assertEquals('sandwiches', t($text, $nText, 0)); + $this->assertEquals('sandwich', t($text, $nText, 1)); + $this->assertEquals('sandwiches', t($text, $nText, 2)); + } + + /** + * Test t() with an identified plural form in PHP mode. + */ + public function testTranslatePluralIDPhp() + { + $this->conf->set('translation.mode', 'php'); + new Languages('en', $this->conf); + $text = 'shaare'; + $nText = 'shaares'; + // In english, zero is followed by plural form + $this->assertEquals('shaare', t($text, $nText, 0)); + $this->assertEquals('shaare', t($text, $nText, 1)); + $this->assertEquals('shaares', t($text, $nText, 2)); + } + + /** + * Test t() with an extension language file in gettext mode + */ + public function testTranslationExtensionGettext() + { + $this->conf->set('translation.mode', 'gettext'); + $this->conf->set('translation.extensions.test', 'tests/utils/languages/'); + new Languages('en', $this->conf); + $this->assertEquals('voiture', t('car', 'car', 1, 'test')); + $this->assertEquals('Fouille', t('Search', 'Search', 1, 'test')); + } + + /** + * Test t() with an extension language file in PHP mode + */ + public function testTranslationExtensionPhp() + { + $this->conf->set('translation.mode', 'php'); + $this->conf->set('translation.extensions.test', 'tests/utils/languages/'); + new Languages('en', $this->conf); + $this->assertEquals('voiture', t('car', 'car', 1, 'test')); + $this->assertEquals('Fouille', t('Search', 'Search', 1, 'test')); + } +} diff --git a/tests/utils/languages/fr/LC_MESSAGES/test.mo b/tests/utils/languages/fr/LC_MESSAGES/test.mo new file mode 100644 index 0000000000000000000000000000000000000000..416c783105300fb5ecdfdb2636b060c338b65e55 GIT binary patch literal 456 zcmZvX&rSj{5XS5OWRIRb^r$h#?g~mu@Pe!%LL{&nZ#pgmTeG&L+a>rQzKchn#Ak69 zj9i@bm-#yR+J5~$-2GrwJH!!DC-#UwQPnfCPXJMQGU9fNv7Gt=@kzSsU({)>s`73B zYBol2X~t4;Z0PJOre5?W;sITutx>$Y^k^!{Jr+I~-X)^r5Ijx9HF#7!lHsM04G~Em zo~uUvR7O&gQH*e*tCRou>MFcg`}$CLkvK3#4&FM&gFcv92{RN4!kgmb48Z03Z>;## zJ;kG7&>M6&F~gb+I@VBDy6t^Vu{j>PPCaR z-h9#Y$Gmiqi`criLUA)+ZHso);%nJHHvEc*C#~R7+@L|X4nDLv(Vj;&SqlRe+fwH_ LvW3;YbjW@H<$QQq literal 0 HcmV?d00001 diff --git a/tests/utils/languages/fr/LC_MESSAGES/test.po b/tests/utils/languages/fr/LC_MESSAGES/test.po new file mode 100644 index 00000000..89a4fd9b --- /dev/null +++ b/tests/utils/languages/fr/LC_MESSAGES/test.po @@ -0,0 +1,19 @@ +msgid "" +msgstr "" +"Project-Id-Version: Extension test\n" +"POT-Creation-Date: 2017-05-20 13:54+0200\n" +"PO-Revision-Date: 2017-05-20 14:16+0200\n" +"Last-Translator: \n" +"Language-Team: Shaarli\n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 2.0.1\n" + +msgid "car" +msgstr "voiture" + +msgid "Search" +msgstr "Fouille" diff --git a/tpl/default/import.html b/tpl/default/import.html index 1f040685..000a50ac 100644 --- a/tpl/default/import.html +++ b/tpl/default/import.html @@ -18,7 +18,7 @@
      -


      Maximum size allowed: {$maxfilesizeHuman}

      +


      {'Maximum size allowed:'|t} {$maxfilesizeHuman}

      @@ -31,15 +31,15 @@
      - Use values from the imported file, default to public + {'Use values from the imported file, default to public'|t}
      - Import all bookmarks as private + {'Import all bookmarks as private'|t}
      - Import all bookmarks as public + {'Import all bookmarks as public'|t}
      diff --git a/tpl/default/linklist.html b/tpl/default/linklist.html index 685821e3..5dab8e9a 100644 --- a/tpl/default/linklist.html +++ b/tpl/default/linklist.html @@ -86,7 +86,7 @@
      - {function="t('%s result', '%s results', $result_count)"} + {function="sprintf(t('%s result', '%s results', $result_count), $result_count)"} {if="!empty($search_term)"} {'for'|t} {$search_term} {/if} @@ -117,6 +117,16 @@
      + {ignore}Set translation here, for performances{/ignore} + {$strPrivate=t('Private')} + {$strEdit=t('Edit')} + {$strDelete=t('Delete')} + {$strFold=t('Fold')} + {$strEdited=t('Edited: ')} + {$strPermalink=t('Permalink')} + {$strPermalinkLc=t('permalink')} + {$strAddTag=t('Add tag')} + {ignore}End of translations{/ignore} {loop="links"}