Chris@18: Chris@18: * Chris@18: * For the full copyright and license information, please view the LICENSE Chris@18: * file that was distributed with this source code. Chris@18: */ Chris@18: Chris@18: $usageInstructions = << false, Chris@18: // NULL = analyze all locales Chris@18: 'locale_to_analyze' => null, Chris@18: // the reference files all the other translations are compared to Chris@18: 'original_files' => [ Chris@18: 'src/Symfony/Component/Form/Resources/translations/validators.en.xlf', Chris@18: 'src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf', Chris@18: 'src/Symfony/Component/Validator/Resources/translations/validators.en.xlf', Chris@18: ], Chris@18: ]; Chris@18: Chris@18: $argc = $_SERVER['argc']; Chris@18: $argv = $_SERVER['argv']; Chris@18: Chris@18: if ($argc > 3) { Chris@18: echo str_replace('translation-status.php', $argv[0], $usageInstructions); Chris@18: exit(1); Chris@18: } Chris@18: Chris@18: foreach (array_slice($argv, 1) as $argumentOrOption) { Chris@18: if (0 === strpos($argumentOrOption, '-')) { Chris@18: $config['verbose_output'] = true; Chris@18: } else { Chris@18: $config['locale_to_analyze'] = $argumentOrOption; Chris@18: } Chris@18: } Chris@18: Chris@18: foreach ($config['original_files'] as $originalFilePath) { Chris@18: if (!file_exists($originalFilePath)) { Chris@18: echo sprintf('The following file does not exist. Make sure that you execute this command at the root dir of the Symfony code repository.%s %s', PHP_EOL, $originalFilePath); Chris@18: exit(1); Chris@18: } Chris@18: } Chris@18: Chris@18: $totalMissingTranslations = 0; Chris@18: Chris@18: foreach ($config['original_files'] as $originalFilePath) { Chris@18: $translationFilePaths = findTranslationFiles($originalFilePath, $config['locale_to_analyze']); Chris@18: $translationStatus = calculateTranslationStatus($originalFilePath, $translationFilePaths); Chris@18: Chris@18: $totalMissingTranslations += array_sum(array_map(function ($translation) { Chris@18: return \count($translation['missingKeys']); Chris@18: }, array_values($translationStatus))); Chris@18: Chris@18: printTranslationStatus($originalFilePath, $translationStatus, $config['verbose_output']); Chris@18: } Chris@18: Chris@18: exit($totalMissingTranslations > 0 ? 1 : 0); Chris@18: Chris@18: function findTranslationFiles($originalFilePath, $localeToAnalyze) Chris@18: { Chris@18: $translations = []; Chris@18: Chris@18: $translationsDir = dirname($originalFilePath); Chris@18: $originalFileName = basename($originalFilePath); Chris@18: $translationFileNamePattern = str_replace('.en.', '.*.', $originalFileName); Chris@18: Chris@18: $translationFiles = glob($translationsDir.'/'.$translationFileNamePattern); Chris@18: foreach ($translationFiles as $filePath) { Chris@18: $locale = extractLocaleFromFilePath($filePath); Chris@18: Chris@18: if (null !== $localeToAnalyze && $locale !== $localeToAnalyze) { Chris@18: continue; Chris@18: } Chris@18: Chris@18: $translations[$locale] = $filePath; Chris@18: } Chris@18: Chris@18: return $translations; Chris@18: } Chris@18: Chris@18: function calculateTranslationStatus($originalFilePath, $translationFilePaths) Chris@18: { Chris@18: $translationStatus = []; Chris@18: $allTranslationKeys = extractTranslationKeys($originalFilePath); Chris@18: Chris@18: foreach ($translationFilePaths as $locale => $translationPath) { Chris@18: $translatedKeys = extractTranslationKeys($translationPath); Chris@18: $missingKeys = array_diff_key($allTranslationKeys, $translatedKeys); Chris@18: Chris@18: $translationStatus[$locale] = [ Chris@18: 'total' => \count($allTranslationKeys), Chris@18: 'translated' => \count($translatedKeys), Chris@18: 'missingKeys' => $missingKeys, Chris@18: ]; Chris@18: } Chris@18: Chris@18: return $translationStatus; Chris@18: } Chris@18: Chris@18: function printTranslationStatus($originalFilePath, $translationStatus, $verboseOutput) Chris@18: { Chris@18: printTitle($originalFilePath); Chris@18: printTable($translationStatus, $verboseOutput); Chris@18: echo PHP_EOL.PHP_EOL; Chris@18: } Chris@18: Chris@18: function extractLocaleFromFilePath($filePath) Chris@18: { Chris@18: $parts = explode('.', $filePath); Chris@18: Chris@18: return $parts[count($parts) - 2]; Chris@18: } Chris@18: Chris@18: function extractTranslationKeys($filePath) Chris@18: { Chris@18: $translationKeys = []; Chris@18: $contents = new \SimpleXMLElement(file_get_contents($filePath)); Chris@18: Chris@18: foreach ($contents->file->body->{'trans-unit'} as $translationKey) { Chris@18: $translationId = (string) $translationKey['id']; Chris@18: $translationKey = (string) $translationKey->source; Chris@18: Chris@18: $translationKeys[$translationId] = $translationKey; Chris@18: } Chris@18: Chris@18: return $translationKeys; Chris@18: } Chris@18: Chris@18: function printTitle($title) Chris@18: { Chris@18: echo $title.PHP_EOL; Chris@18: echo str_repeat('=', strlen($title)).PHP_EOL.PHP_EOL; Chris@18: } Chris@18: Chris@18: function printTable($translations, $verboseOutput) Chris@18: { Chris@18: if (0 === count($translations)) { Chris@18: echo 'No translations found'; Chris@18: Chris@18: return; Chris@18: } Chris@18: $longestLocaleNameLength = max(array_map('strlen', array_keys($translations))); Chris@18: Chris@18: foreach ($translations as $locale => $translation) { Chris@18: $isTranslationCompleted = $translation['translated'] === $translation['total']; Chris@18: if ($isTranslationCompleted) { Chris@18: textColorGreen(); Chris@18: } Chris@18: Chris@18: echo sprintf('| Locale: %-'.$longestLocaleNameLength.'s | Translated: %d/%d', $locale, $translation['translated'], $translation['total']).PHP_EOL; Chris@18: Chris@18: textColorNormal(); Chris@18: Chris@18: if (true === $verboseOutput && \count($translation['missingKeys']) > 0) { Chris@18: echo str_repeat('-', 80).PHP_EOL; Chris@18: echo '| Missing Translations:'.PHP_EOL; Chris@18: Chris@18: foreach ($translation['missingKeys'] as $id => $content) { Chris@18: echo sprintf('| (id=%s) %s', $id, $content).PHP_EOL; Chris@18: } Chris@18: Chris@18: echo str_repeat('-', 80).PHP_EOL; Chris@18: } Chris@18: } Chris@18: } Chris@18: Chris@18: function textColorGreen() Chris@18: { Chris@18: echo "\033[32m"; Chris@18: } Chris@18: Chris@18: function textColorNormal() Chris@18: { Chris@18: echo "\033[0m"; Chris@18: }