Selaa lähdekoodia

[CI] Add a translation validation tool. (#1653)

It's triggered by Travis to check what is missing.
Alexis Degrugillier 8 vuotta sitten
vanhempi
commit
51e69e9535
3 muutettua tiedostoa jossa 201 lisäystä ja 4 poistoa
  1. 16 4
      .travis.yml
  2. 127 0
      tools/check.translation.php
  3. 58 0
      tools/translation.ignore.php

+ 16 - 4
.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

+ 127 - 0
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;
+}

+ 58 - 0
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;