diff options
| -rw-r--r-- | .travis.yml | 20 | ||||
| -rw-r--r-- | tools/check.translation.php | 127 | ||||
| -rw-r--r-- | tools/translation.ignore.php | 58 |
3 files changed, 201 insertions, 4 deletions
diff --git a/.travis.yml b/.travis.yml index 5c43e5666..945e77a74 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,16 +14,27 @@ install: script: - phpenv rehash - - phpcs . --standard=phpcs.xml --warning-severity=0 --extensions=php -p + - | + if [[ $VALIDATE_STANDARD == yes ]]; then + phpcs . --standard=phpcs.xml --warning-severity=0 --extensions=php -p + fi + - | + if [[ $CHECK_TRANSLATION == yes ]]; then + php tools/check.translation.php -r + fi + +env: + - CHECK_TRANSLATION=no VALIDATE_STANDARD=yes -env: # important! otherwise no job will be allowed to fail matrix: - # PHP 5.3 only runs on Ubuntu 12.04 (precise), not 14.04 (trusty) + fast_finish: true include: - php: "5.3" dist: precise - fast_finish: true + - php: "7.1" + env: CHECK_TRANSLATION=yes VALIDATE_STANDARD=no allow_failures: + # PHP 5.3 only runs on Ubuntu 12.04 (precise), not 14.04 (trusty) - php: "5.3" dist: precise - php: "5.4" @@ -32,3 +43,4 @@ matrix: - php: "7.0" - php: hhvm - php: nightly + - env: CHECK_TRANSLATION=yes VALIDATE_STANDARD=no diff --git a/tools/check.translation.php b/tools/check.translation.php new file mode 100644 index 000000000..7854e131f --- /dev/null +++ b/tools/check.translation.php @@ -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; +} diff --git a/tools/translation.ignore.php b/tools/translation.ignore.php new file mode 100644 index 000000000..a05f36267 --- /dev/null +++ b/tools/translation.ignore.php @@ -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; |
