[CI] Add a translation validation tool. (#1653)
It's triggered by Travis to check what is missing.pull/1658/head
parent
1cf9816fe5
commit
51e69e9535
3 changed files with 201 additions and 4 deletions
@ -0,0 +1,127 @@ |
||||
<?php |
||||
|
||||
$options = getopt("dhl:r"); |
||||
|
||||
$ignore = include __DIR__ . '/translation.ignore.php'; |
||||
|
||||
if (array_key_exists('h', $options)) { |
||||
help(); |
||||
} |
||||
if (array_key_exists('l', $options)) { |
||||
$langPattern = sprintf('/%s/', $options['l']); |
||||
} else { |
||||
$langPattern = '/*/'; |
||||
} |
||||
$displayErrors = array_key_exists('d', $options); |
||||
$displayReport = array_key_exists('r', $options); |
||||
|
||||
$i18nPath = __DIR__ . '/../app/i18n/'; |
||||
$errors = 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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if ($displayErrors) { |
||||
foreach ($errors 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; |
||||
} |
||||
} |
||||
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; |
||||
} |
||||
} |
||||
|
||||
if (!empty($errors)) { |
||||
exit(1); |
||||
} |
||||
|
||||
/** |
||||
* Flatten an array of translation |
||||
* |
||||
* @param array $translation |
||||
* @param string $prependKey |
||||
* @return array |
||||
*/ |
||||
function flatten($translation, $prependKey = '') { |
||||
$a = array(); |
||||
|
||||
if ('' !== $prependKey) { |
||||
$prependKey .= '.'; |
||||
} |
||||
|
||||
foreach ($translation as $key => $value) { |
||||
if (is_array($value)) { |
||||
$a += flatten($value, $prependKey . $key); |
||||
} else { |
||||
$a[$prependKey . $key] = $value; |
||||
} |
||||
} |
||||
|
||||
return $a; |
||||
} |
||||
|
||||
/** |
||||
* Output help message. |
||||
*/ |
||||
function help() { |
||||
$help = <<<HELP |
||||
NAME |
||||
%s |
||||
|
||||
SYNOPSIS |
||||
php %s [OPTION]... |
||||
|
||||
DESCRIPTION |
||||
Check if translation files have missing keys or missing translations. |
||||
|
||||
-d display results. |
||||
-h display this help and exit. |
||||
-l=LANG filter by LANG. |
||||
-r display completion report. |
||||
|
||||
HELP; |
||||
$file = str_replace(__DIR__ . '/', '', __FILE__); |
||||
echo sprintf($help, $file, $file); |
||||
exit; |
||||
} |
@ -0,0 +1,58 @@ |
||||
<?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; |
Loading…
Reference in new issue