mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2026-03-30 12:12:42 -04:00
Merge pull request #1658 from aledeg/improve-i18n-tools
Improve translation tools
This commit is contained in:
@@ -7,7 +7,8 @@
|
||||
* Bug fixing
|
||||
* Work-around for `CURLOPT_FOLLOWLOCATION` `open_basedir` bug in favicons and PubSubHubbub [#1655](https://github.com/FreshRSS/FreshRSS/issues/1655)
|
||||
* Misc.
|
||||
* Travis translation validation tool [#1653](https://github.com/FreshRSS/FreshRSS/pull/1653)
|
||||
* Translation validation tool [#1653](https://github.com/FreshRSS/FreshRSS/pull/1653)
|
||||
* Translation manipulation tool [#1658](https://github.com/FreshRSS/FreshRSS/pull/1658)
|
||||
|
||||
|
||||
## 2017-10-01 FreshRSS 1.8.0
|
||||
|
||||
@@ -186,16 +186,16 @@
|
||||
if (FreshRSS_Context::$order === 'DESC') {
|
||||
$order = 'ASC';
|
||||
$icon = 'up';
|
||||
$title = 'index.menu.older_first';
|
||||
$title = _t('index.menu.older_first');
|
||||
} else {
|
||||
$order = 'DESC';
|
||||
$icon = 'down';
|
||||
$title = 'index.menu.newer_first';
|
||||
$title = _t('index.menu.newer_first');
|
||||
}
|
||||
$url_order = Minz_Request::currentRequest();
|
||||
$url_order['params']['order'] = $order;
|
||||
?>
|
||||
<a id="toggle-order" class="btn" href="<?php echo Minz_Url::display($url_order); ?>" title="<?php echo _t($title); ?>">
|
||||
<a id="toggle-order" class="btn" href="<?php echo Minz_Url::display($url_order); ?>" title="<?php echo $title; ?>">
|
||||
<?php echo _i($icon); ?>
|
||||
</a>
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<div class="group-controls">
|
||||
<?php
|
||||
$number = count(listUsers());
|
||||
echo _t($number > 1 ? 'admin.user.numbers' : 'admin.user.number', $number);
|
||||
echo ($number > 1 ? _t('admin.user.numbers', $number) : _t('admin.user.number', $number));
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
49
tools/I18nCompletionValidator.php
Normal file
49
tools/I18nCompletionValidator.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/I18nValidatorInterface.php';
|
||||
|
||||
class I18nCompletionValidator implements I18nValidatorInterface {
|
||||
|
||||
private $reference;
|
||||
private $language;
|
||||
private $totalEntries = 0;
|
||||
private $passEntries = 0;
|
||||
private $result = '';
|
||||
|
||||
public function __construct($reference, $language) {
|
||||
$this->reference = $reference;
|
||||
$this->language = $language;
|
||||
}
|
||||
|
||||
public function displayReport() {
|
||||
return sprintf('Translation is %5.1f%% complete.', $this->passEntries / $this->totalEntries * 100) . PHP_EOL;
|
||||
}
|
||||
|
||||
public function displayResult() {
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
public function validate($ignore) {
|
||||
foreach ($this->reference as $file => $data) {
|
||||
foreach ($data as $key => $value) {
|
||||
$this->totalEntries++;
|
||||
if (is_array($ignore) && in_array($key, $ignore)) {
|
||||
$this->passEntries++;
|
||||
continue;
|
||||
}
|
||||
if (!array_key_exists($key, $this->language[$file])) {
|
||||
$this->result .= sprintf('Missing key %s', $key) . PHP_EOL;
|
||||
continue;
|
||||
}
|
||||
if ($value === $this->language[$file][$key]) {
|
||||
$this->result .= sprintf('Untranslated key %s - %s', $key, $value) . PHP_EOL;
|
||||
continue;
|
||||
}
|
||||
$this->passEntries++;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->totalEntries === $this->passEntries;
|
||||
}
|
||||
|
||||
}
|
||||
118
tools/I18nData.php
Normal file
118
tools/I18nData.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
class I18nData {
|
||||
|
||||
const REFERENCE_LANGUAGE = 'en';
|
||||
|
||||
private $data = array();
|
||||
private $originalData = array();
|
||||
|
||||
public function __construct($data) {
|
||||
$this->data = $data;
|
||||
$this->originalData = $data;
|
||||
}
|
||||
|
||||
public function getData() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the available languages
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAvailableLanguages() {
|
||||
$languages = array_keys($this->data);
|
||||
sort($languages);
|
||||
|
||||
return $languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new language. It's a copy of the reference language.
|
||||
*
|
||||
* @param string $language
|
||||
*/
|
||||
public function addLanguage($language) {
|
||||
if (array_key_exists($language, $this->data)) {
|
||||
throw new Exception('The selected language already exist.');
|
||||
}
|
||||
$this->data[$language] = $this->data[static::REFERENCE_LANGUAGE];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a key in the reference language
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*/
|
||||
public function addKey($key, $value) {
|
||||
if (array_key_exists($key, $this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)])) {
|
||||
throw new Exception('The selected key already exist.');
|
||||
}
|
||||
$this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)][$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate a key from the reference language to all other languages
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function duplicateKey($key) {
|
||||
if (!array_key_exists($key, $this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)])) {
|
||||
throw new Exception('The selected key does not exist.');
|
||||
}
|
||||
$value = $this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)][$key];
|
||||
foreach ($this->getAvailableLanguages() as $language) {
|
||||
if (static::REFERENCE_LANGUAGE === $language) {
|
||||
continue;
|
||||
}
|
||||
if (array_key_exists($key, $this->data[$language][$this->getFilenamePrefix($key)])) {
|
||||
throw new Exception(sprintf('The selected key already exist in %s.', $language));
|
||||
}
|
||||
$this->data[$language][$this->getFilenamePrefix($key)][$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a key in all languages
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function removeKey($key) {
|
||||
if (!array_key_exists($key, $this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)])) {
|
||||
throw new Exception('The selected key does not exist.');
|
||||
}
|
||||
foreach ($this->getAvailableLanguages() as $language) {
|
||||
if (array_key_exists($key, $this->data[$language][$this->getFilenamePrefix($key)])) {
|
||||
unset($this->data[$language][$this->getFilenamePrefix($key)][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the data has changed
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasChanged() {
|
||||
return $this->data !== $this->originalData;
|
||||
}
|
||||
|
||||
public function getLanguage($language) {
|
||||
return $this->data[$language];
|
||||
}
|
||||
|
||||
public function getReferenceLanguage() {
|
||||
return $this->getLanguage(static::REFERENCE_LANGUAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
private function getFilenamePrefix($key) {
|
||||
return preg_replace('/\..*/', '.php', $key);
|
||||
}
|
||||
|
||||
}
|
||||
92
tools/I18nFile.php
Normal file
92
tools/I18nFile.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/I18nData.php';
|
||||
|
||||
class i18nFile {
|
||||
|
||||
private $i18nPath;
|
||||
|
||||
public function __construct() {
|
||||
$this->i18nPath = __DIR__ . '/../app/i18n';
|
||||
}
|
||||
|
||||
public function load() {
|
||||
$dirs = new DirectoryIterator($this->i18nPath);
|
||||
foreach ($dirs as $dir) {
|
||||
if ($dir->isDot()) {
|
||||
continue;
|
||||
}
|
||||
$files = new DirectoryIterator($dir->getPathname());
|
||||
foreach ($files as $file) {
|
||||
if (!$file->isFile()) {
|
||||
continue;
|
||||
}
|
||||
$i18n[$dir->getFilename()][$file->getFilename()] = $this->flatten(include $file->getPathname(), $file->getBasename('.php'));
|
||||
}
|
||||
}
|
||||
|
||||
return new I18nData($i18n);
|
||||
}
|
||||
|
||||
public function dump(I18nData $i18n) {
|
||||
foreach ($i18n->getData() as $language => $file) {
|
||||
$dir = $this->i18nPath . DIRECTORY_SEPARATOR . $language;
|
||||
if (!file_exists($dir)) {
|
||||
mkdir($dir);
|
||||
}
|
||||
foreach ($file as $name => $content) {
|
||||
$filename = $dir . DIRECTORY_SEPARATOR . $name;
|
||||
$fullContent = var_export($this->unflatten($content), true);
|
||||
file_put_contents($filename, sprintf('<?php return %s;', $fullContent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten an array of translation
|
||||
*
|
||||
* @param array $translation
|
||||
* @param string $prefix
|
||||
* @return array
|
||||
*/
|
||||
private function flatten($translation, $prefix = '') {
|
||||
$a = array();
|
||||
|
||||
if ('' !== $prefix) {
|
||||
$prefix .= '.';
|
||||
}
|
||||
|
||||
foreach ($translation as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$a += $this->flatten($value, $prefix . $key);
|
||||
} else {
|
||||
$a[$prefix . $key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unflatten an array of translation
|
||||
*
|
||||
* The first key is dropped since it represents the filename and we have
|
||||
* no use of it.
|
||||
*
|
||||
* @param array $translation
|
||||
* @return array
|
||||
*/
|
||||
private function unflatten($translation) {
|
||||
$a = array();
|
||||
|
||||
ksort($translation);
|
||||
foreach ($translation as $compoundKey => $value) {
|
||||
$keys = explode('.', $compoundKey);
|
||||
array_shift($keys);
|
||||
eval("\$a['" . implode("']['", $keys) . "'] = '" . $value . "';");
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
}
|
||||
47
tools/I18nUsageValidator.php
Normal file
47
tools/I18nUsageValidator.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/I18nValidatorInterface.php';
|
||||
|
||||
class I18nUsageValidator implements I18nValidatorInterface {
|
||||
|
||||
private $code;
|
||||
private $reference;
|
||||
private $totalEntries = 0;
|
||||
private $failedEntries = 0;
|
||||
private $result = '';
|
||||
|
||||
public function __construct($reference, $code) {
|
||||
$this->code = $code;
|
||||
$this->reference = $reference;
|
||||
}
|
||||
|
||||
public function displayReport() {
|
||||
return sprintf('%5.1f%% of translation keys are unused.', $this->failedEntries / $this->totalEntries * 100) . PHP_EOL;
|
||||
}
|
||||
|
||||
public function displayResult() {
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
public function validate($ignore) {
|
||||
foreach ($this->reference as $file => $data) {
|
||||
foreach ($data as $key => $value) {
|
||||
$this->totalEntries++;
|
||||
if (preg_match('/\._$/', $key) && in_array(preg_replace('/\._$/', '', $key), $this->code)) {
|
||||
continue;
|
||||
}
|
||||
if (is_array($ignore) && in_array($key, $ignore)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($key, $this->code)) {
|
||||
$this->result .= sprintf('Unused key %s - %s', $key, $value) . PHP_EOL;
|
||||
$this->failedEntries++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0 === $this->failedEntries;
|
||||
}
|
||||
|
||||
}
|
||||
26
tools/I18nValidatorInterface.php
Normal file
26
tools/I18nValidatorInterface.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
interface I18nValidatorInterface {
|
||||
|
||||
/**
|
||||
* Display the validation result.
|
||||
* Empty if there are no errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function displayResult();
|
||||
|
||||
/**
|
||||
* @param array $ignore Keys to ignore for validation
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($ignore);
|
||||
|
||||
/**
|
||||
* Display the validation report.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function displayReport();
|
||||
|
||||
}
|
||||
@@ -1,104 +1,83 @@
|
||||
<?php
|
||||
|
||||
$options = getopt("dhl:r");
|
||||
require_once __DIR__ . '/I18nFile.php';
|
||||
require_once __DIR__ . '/I18nCompletionValidator.php';
|
||||
require_once __DIR__ . '/I18nUsageValidator.php';
|
||||
|
||||
$ignore = include __DIR__ . '/translation.ignore.php';
|
||||
$i18nFile = new I18nFile();
|
||||
$i18nData = $i18nFile->load();
|
||||
|
||||
$options = getopt("dhl:r");
|
||||
|
||||
if (array_key_exists('h', $options)) {
|
||||
help();
|
||||
}
|
||||
if (array_key_exists('l', $options)) {
|
||||
$langPattern = sprintf('/%s/', $options['l']);
|
||||
$languages = array($options['l']);
|
||||
} else {
|
||||
$langPattern = '/*/';
|
||||
$languages = $i18nData->getAvailableLanguages();
|
||||
}
|
||||
$displayErrors = array_key_exists('d', $options);
|
||||
$displayResults = array_key_exists('d', $options);
|
||||
$displayReport = array_key_exists('r', $options);
|
||||
|
||||
$i18nPath = __DIR__ . '/../app/i18n/';
|
||||
$errors = array();
|
||||
$isValidated = true;
|
||||
$result = array();
|
||||
$report = array();
|
||||
|
||||
foreach (glob($i18nPath . 'en/*.php') as $i18nFileReference) {
|
||||
$en = flatten(include $i18nFileReference);
|
||||
foreach (glob(str_replace('/en/', $langPattern, $i18nFileReference)) as $i18nFile) {
|
||||
preg_match('#(?P<lang>[^/]+)/(?P<file>[^/]*.php)#', $i18nFile, $matches);
|
||||
$lang = $matches['lang'];
|
||||
$file = $matches['file'];
|
||||
if ('en' === $lang) {
|
||||
continue;
|
||||
}
|
||||
if (!array_key_exists($lang, $report)) {
|
||||
$report[$lang]['total'] = 0;
|
||||
$report[$lang]['errors'] = 0;
|
||||
}
|
||||
$i18n = flatten(include $i18nFile);
|
||||
foreach ($en as $key => $value) {
|
||||
$report[$lang]['total'] ++;
|
||||
if (array_key_exists($lang, $ignore) && array_key_exists($file, $ignore[$lang]) && in_array($key, $ignore[$lang][$file])) {
|
||||
continue;
|
||||
}
|
||||
if (!array_key_exists($key, $i18n)) {
|
||||
$errors[$lang][$file][] = sprintf('Missing key %s', $key);
|
||||
$report[$lang]['errors'] ++;
|
||||
continue;
|
||||
}
|
||||
if ($i18n[$key] === $value) {
|
||||
$errors[$lang][$file][] = sprintf('Untranslated key %s - %s', $key, $value);
|
||||
$report[$lang]['errors'] ++;
|
||||
continue;
|
||||
}
|
||||
foreach ($languages as $language) {
|
||||
if ($language === $i18nData::REFERENCE_LANGUAGE) {
|
||||
$i18nValidator = new I18nUsageValidator($i18nData->getReferenceLanguage(), findUsedTranslations());
|
||||
$isValidated = $i18nValidator->validate(include __DIR__ . '/ignore/' . $language . '.php') && $isValidated;
|
||||
} else {
|
||||
$i18nValidator = new I18nCompletionValidator($i18nData->getReferenceLanguage(), $i18nData->getLanguage($language));
|
||||
if (file_exists(__DIR__ . '/ignore/' . $language . '.php')) {
|
||||
$isValidated = $i18nValidator->validate(include __DIR__ . '/ignore/' . $language . '.php') && $isValidated;
|
||||
} else {
|
||||
$isValidated = $i18nValidator->validate(null) && $isValidated;
|
||||
}
|
||||
}
|
||||
|
||||
$report[$language] = sprintf('%-5s - %s', $language, $i18nValidator->displayReport());
|
||||
$result[$language] = $i18nValidator->displayResult();
|
||||
}
|
||||
|
||||
if ($displayErrors) {
|
||||
foreach ($errors as $lang => $value) {
|
||||
if ($displayResults) {
|
||||
foreach ($result as $lang => $value) {
|
||||
echo 'Language: ', $lang, PHP_EOL;
|
||||
foreach ($value as $file => $messages) {
|
||||
echo ' - File: ', $file, PHP_EOL;
|
||||
foreach ($messages as $message) {
|
||||
echo ' - ', $message, PHP_EOL;
|
||||
}
|
||||
}
|
||||
print_r($value);
|
||||
echo PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
if ($displayReport) {
|
||||
foreach ($report as $lang => $value) {
|
||||
$completion = ($value['total'] - $value['errors']) / $value['total'] * 100;
|
||||
echo sprintf('Translation for %-5s is %5.1f%% complete.', $lang, $completion), PHP_EOL;
|
||||
foreach ($report as $value) {
|
||||
echo $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
if (!$isValidated) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten an array of translation
|
||||
* Find used translation keys in the project
|
||||
*
|
||||
* Iterates through all php and phtml files in the whole project and extracts all
|
||||
* translation keys used.
|
||||
*
|
||||
* @param array $translation
|
||||
* @param string $prependKey
|
||||
* @return array
|
||||
*/
|
||||
function flatten($translation, $prependKey = '') {
|
||||
$a = array();
|
||||
|
||||
if ('' !== $prependKey) {
|
||||
$prependKey .= '.';
|
||||
function findUsedTranslations() {
|
||||
$directory = new RecursiveDirectoryIterator(__DIR__ . '/..');
|
||||
$iterator = new RecursiveIteratorIterator($directory);
|
||||
$regex = new RegexIterator($iterator, '/^.+\.(php|phtml)$/i', RecursiveRegexIterator::GET_MATCH);
|
||||
$usedI18n = array();
|
||||
foreach (array_keys(iterator_to_array($regex)) as $file) {
|
||||
$fileContent = file_get_contents($file);
|
||||
preg_match_all('/_t\([\'"](?P<strings>[^\'"]+)[\'"]/', $fileContent, $matches);
|
||||
$usedI18n = array_merge($usedI18n, $matches['strings']);
|
||||
}
|
||||
|
||||
foreach ($translation as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$a += flatten($value, $prependKey . $key);
|
||||
} else {
|
||||
$a[$prependKey . $key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $a;
|
||||
return $usedI18n;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
105
tools/ignore/en.php
Normal file
105
tools/ignore/en.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'admin.check_install.cache.nok',
|
||||
'admin.check_install.cache.ok',
|
||||
'admin.check_install.categories.nok',
|
||||
'admin.check_install.categories.ok',
|
||||
'admin.check_install.connection.nok',
|
||||
'admin.check_install.connection.ok',
|
||||
'admin.check_install.ctype.nok',
|
||||
'admin.check_install.ctype.ok',
|
||||
'admin.check_install.curl.nok',
|
||||
'admin.check_install.curl.ok',
|
||||
'admin.check_install.data.nok',
|
||||
'admin.check_install.data.ok',
|
||||
'admin.check_install.dom.nok',
|
||||
'admin.check_install.dom.ok',
|
||||
'admin.check_install.entries.nok',
|
||||
'admin.check_install.entries.ok',
|
||||
'admin.check_install.favicons.nok',
|
||||
'admin.check_install.favicons.ok',
|
||||
'admin.check_install.feeds.nok',
|
||||
'admin.check_install.feeds.ok',
|
||||
'admin.check_install.fileinfo.nok',
|
||||
'admin.check_install.fileinfo.ok',
|
||||
'admin.check_install.json.nok',
|
||||
'admin.check_install.json.ok',
|
||||
'admin.check_install.minz.nok',
|
||||
'admin.check_install.minz.ok',
|
||||
'admin.check_install.pcre.nok',
|
||||
'admin.check_install.pcre.ok',
|
||||
'admin.check_install.pdo.nok',
|
||||
'admin.check_install.pdo.ok',
|
||||
'admin.check_install.php.nok',
|
||||
'admin.check_install.php.ok',
|
||||
'admin.check_install.tables.nok',
|
||||
'admin.check_install.tables.ok',
|
||||
'admin.check_install.tokens.nok',
|
||||
'admin.check_install.tokens.ok',
|
||||
'admin.check_install.users.nok',
|
||||
'admin.check_install.users.ok',
|
||||
'admin.check_install.zip.nok',
|
||||
'admin.check_install.zip.ok',
|
||||
'conf.query.get_all',
|
||||
'conf.query.get_category',
|
||||
'conf.query.get_favorite',
|
||||
'conf.query.get_feed',
|
||||
'conf.query.order_asc',
|
||||
'conf.query.order_desc',
|
||||
'conf.query.state_0',
|
||||
'conf.query.state_1',
|
||||
'conf.query.state_2',
|
||||
'conf.query.state_3',
|
||||
'conf.query.state_4',
|
||||
'conf.query.state_5',
|
||||
'conf.query.state_6',
|
||||
'conf.query.state_7',
|
||||
'conf.query.state_8',
|
||||
'conf.query.state_9',
|
||||
'conf.query.state_10',
|
||||
'conf.query.state_11',
|
||||
'conf.query.state_12',
|
||||
'conf.query.state_13',
|
||||
'conf.query.state_14',
|
||||
'conf.query.state_15',
|
||||
'conf.sharing.blogotext',
|
||||
'conf.sharing.diaspora',
|
||||
'conf.sharing.email',
|
||||
'conf.sharing.facebook',
|
||||
'conf.sharing.g+',
|
||||
'conf.sharing.print',
|
||||
'conf.sharing.shaarli',
|
||||
'conf.sharing.twitter',
|
||||
'conf.sharing.wallabag',
|
||||
'gen.lang.cz',
|
||||
'gen.lang.de',
|
||||
'gen.lang.en',
|
||||
'gen.lang.es',
|
||||
'gen.lang.fr',
|
||||
'gen.lang.it',
|
||||
'gen.lang.kr',
|
||||
'gen.lang.nl',
|
||||
'gen.lang.pt-br',
|
||||
'gen.lang.ru',
|
||||
'gen.lang.tr',
|
||||
'gen.lang.zh-cn',
|
||||
'gen.share.blogotext',
|
||||
'gen.share.diaspora',
|
||||
'gen.share.email',
|
||||
'gen.share.facebook',
|
||||
'gen.share.g+',
|
||||
'gen.share.movim',
|
||||
'gen.share.print',
|
||||
'gen.share.shaarli',
|
||||
'gen.share.twitter',
|
||||
'gen.share.wallabag',
|
||||
'gen.share.wallabagv2',
|
||||
'gen.share.jdh',
|
||||
'gen.share.Known',
|
||||
'gen.share.gnusocial',
|
||||
'index.menu.non-starred',
|
||||
'index.menu.read',
|
||||
'index.menu.starred',
|
||||
'index.menu.unread',
|
||||
);
|
||||
55
tools/ignore/fr.php
Normal file
55
tools/ignore/fr.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'admin.extensions.title',
|
||||
'admin.stats.number_entries',
|
||||
'admin.user.articles_and_size',
|
||||
'conf.display.width.large',
|
||||
'conf.sharing.blogotext',
|
||||
'conf.sharing.diaspora',
|
||||
'conf.sharing.facebook',
|
||||
'conf.sharing.g+',
|
||||
'conf.sharing.print',
|
||||
'conf.sharing.shaarli',
|
||||
'conf.sharing.twitter',
|
||||
'conf.sharing.wallabag',
|
||||
'conf.shortcut.navigation',
|
||||
'conf.user.articles_and_size',
|
||||
'gen.freshrss._',
|
||||
'gen.lang.cz',
|
||||
'gen.lang.de',
|
||||
'gen.lang.en',
|
||||
'gen.lang.es',
|
||||
'gen.lang.fr',
|
||||
'gen.lang.it',
|
||||
'gen.lang.kr',
|
||||
'gen.lang.nl',
|
||||
'gen.lang.pt-br',
|
||||
'gen.lang.ru',
|
||||
'gen.lang.tr',
|
||||
'gen.lang.zh-cn',
|
||||
'gen.menu.admin',
|
||||
'gen.menu.configuration',
|
||||
'gen.menu.extensions',
|
||||
'gen.menu.logs',
|
||||
'gen.share.blogotext',
|
||||
'gen.share.diaspora',
|
||||
'gen.share.facebook',
|
||||
'gen.share.g+',
|
||||
'gen.share.movim',
|
||||
'gen.share.shaarli',
|
||||
'gen.share.twitter',
|
||||
'gen.share.wallabag',
|
||||
'gen.share.wallabagv2',
|
||||
'gen.share.jdh',
|
||||
'gen.share.gnusocial',
|
||||
'index.about.agpl3',
|
||||
'index.about.version',
|
||||
'index.log._',
|
||||
'index.log.title',
|
||||
'install.title',
|
||||
'install.this_is_the_end',
|
||||
'sub.bookmarklet.title',
|
||||
'sub.feed.description',
|
||||
'sub.feed.number_entries',
|
||||
);
|
||||
79
tools/manipulate.translation.php
Normal file
79
tools/manipulate.translation.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
$options = getopt("h");
|
||||
|
||||
if (array_key_exists('h', $options)) {
|
||||
help();
|
||||
}
|
||||
|
||||
if (1 === $argc || 4 < $argc) {
|
||||
help();
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/I18nFile.php';
|
||||
|
||||
$i18nFile = new I18nFile();
|
||||
$i18nData = $i18nFile->load();
|
||||
|
||||
switch ($argv[1]) {
|
||||
case 'add_language' :
|
||||
$i18nData->addLanguage($argv[2]);
|
||||
break;
|
||||
case 'add_key' :
|
||||
if (3 === $argc) {
|
||||
help();
|
||||
}
|
||||
$i18nData->addKey($argv[2], $argv[3]);
|
||||
break;
|
||||
case 'duplicate_key' :
|
||||
$i18nData->duplicateKey($argv[2]);
|
||||
break;
|
||||
case 'delete_key' :
|
||||
$i18nData->removeKey($argv[2]);
|
||||
break;
|
||||
default :
|
||||
help();
|
||||
}
|
||||
|
||||
if ($i18nData->hasChanged()) {
|
||||
$i18nFile->dump($i18nData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output help message.
|
||||
*/
|
||||
function help() {
|
||||
$help = <<<HELP
|
||||
NAME
|
||||
%s
|
||||
|
||||
SYNOPSIS
|
||||
php %s [OPTION] [OPERATION] [KEY] [VALUE]
|
||||
|
||||
DESCRIPTION
|
||||
Manipulate translation files. Available operations are
|
||||
Check if translation files have missing keys or missing translations.
|
||||
|
||||
-h display this help and exit.
|
||||
|
||||
OPERATION
|
||||
add_language
|
||||
add a new language by duplicating the referential. This operation
|
||||
needs only a KEY.
|
||||
|
||||
add_key add a new key in the referential. This operation needs a KEY and
|
||||
a VALUE.
|
||||
|
||||
duplicate_key
|
||||
duplicate a referential key in other languages. This operation
|
||||
needs only a KEY.
|
||||
|
||||
delete_key
|
||||
delete a referential key from all languages. This operation needs
|
||||
only a KEY.
|
||||
|
||||
HELP;
|
||||
$file = str_replace(__DIR__ . '/', '', __FILE__);
|
||||
echo sprintf($help, $file, $file);
|
||||
exit;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
$ignore = array();
|
||||
|
||||
// ignore for FR
|
||||
$ignore['fr']['admin.php'][] = 'extensions.title';
|
||||
$ignore['fr']['admin.php'][] = 'stats.number_entries';
|
||||
$ignore['fr']['admin.php'][] = 'user.articles_and_size';
|
||||
$ignore['fr']['conf.php'][] = 'display.width.large';
|
||||
$ignore['fr']['conf.php'][] = 'sharing.blogotext';
|
||||
$ignore['fr']['conf.php'][] = 'sharing.diaspora';
|
||||
$ignore['fr']['conf.php'][] = 'sharing.facebook';
|
||||
$ignore['fr']['conf.php'][] = 'sharing.g+';
|
||||
$ignore['fr']['conf.php'][] = 'sharing.print';
|
||||
$ignore['fr']['conf.php'][] = 'sharing.shaarli';
|
||||
$ignore['fr']['conf.php'][] = 'sharing.twitter';
|
||||
$ignore['fr']['conf.php'][] = 'sharing.wallabag';
|
||||
$ignore['fr']['conf.php'][] = 'shortcut.navigation';
|
||||
$ignore['fr']['conf.php'][] = 'user.articles_and_size';
|
||||
$ignore['fr']['gen.php'][] = 'freshrss._';
|
||||
$ignore['fr']['gen.php'][] = 'lang.cz';
|
||||
$ignore['fr']['gen.php'][] = 'lang.de';
|
||||
$ignore['fr']['gen.php'][] = 'lang.en';
|
||||
$ignore['fr']['gen.php'][] = 'lang.es';
|
||||
$ignore['fr']['gen.php'][] = 'lang.fr';
|
||||
$ignore['fr']['gen.php'][] = 'lang.it';
|
||||
$ignore['fr']['gen.php'][] = 'lang.kr';
|
||||
$ignore['fr']['gen.php'][] = 'lang.nl';
|
||||
$ignore['fr']['gen.php'][] = 'lang.pt-br';
|
||||
$ignore['fr']['gen.php'][] = 'lang.ru';
|
||||
$ignore['fr']['gen.php'][] = 'lang.tr';
|
||||
$ignore['fr']['gen.php'][] = 'lang.zh-cn';
|
||||
$ignore['fr']['gen.php'][] = 'menu.admin';
|
||||
$ignore['fr']['gen.php'][] = 'menu.configuration';
|
||||
$ignore['fr']['gen.php'][] = 'menu.extensions';
|
||||
$ignore['fr']['gen.php'][] = 'menu.logs';
|
||||
$ignore['fr']['gen.php'][] = 'share.blogotext';
|
||||
$ignore['fr']['gen.php'][] = 'share.diaspora';
|
||||
$ignore['fr']['gen.php'][] = 'share.facebook';
|
||||
$ignore['fr']['gen.php'][] = 'share.g+';
|
||||
$ignore['fr']['gen.php'][] = 'share.movim';
|
||||
$ignore['fr']['gen.php'][] = 'share.shaarli';
|
||||
$ignore['fr']['gen.php'][] = 'share.twitter';
|
||||
$ignore['fr']['gen.php'][] = 'share.wallabag';
|
||||
$ignore['fr']['gen.php'][] = 'share.wallabagv2';
|
||||
$ignore['fr']['gen.php'][] = 'share.jdh';
|
||||
$ignore['fr']['gen.php'][] = 'share.gnusocial';
|
||||
$ignore['fr']['index.php'][] = 'about.agpl3';
|
||||
$ignore['fr']['index.php'][] = 'about.version';
|
||||
$ignore['fr']['index.php'][] = 'log._';
|
||||
$ignore['fr']['index.php'][] = 'log.title';
|
||||
$ignore['fr']['install.php'][] = 'title';
|
||||
$ignore['fr']['install.php'][] = 'this_is_the_end';
|
||||
$ignore['fr']['sub.php'][] = 'bookmarklet.title';
|
||||
$ignore['fr']['sub.php'][] = 'feed.description';
|
||||
$ignore['fr']['sub.php'][] = 'feed.number_entries';
|
||||
|
||||
return $ignore;
|
||||
Reference in New Issue
Block a user