From f9a42adadec9acd259c205727c95bd6f376dfbc5 Mon Sep 17 00:00:00 2001 From: Inverle Date: Wed, 16 Jul 2025 16:11:51 +0200 Subject: Show translation status in README.md (#7715) * Show translation status in README.md * Fix colon * markdownlint: Allow tag `` * Use mostly Unicode flags instead * Only `oc.svg` remains in an image format * `check.translation.php` still supports `.png` even though there aren't any PNGs as of right now * Fix CodeSniffer * Attempt approach with generating local SVGs * Fixes for local SVG approach * Cleanup old code * PHPStan fix * Remove decimal precision from percentages * Suggestions + better error messages * codesniffer fix v2 * Revert `ghSearchUrl` change * Generate readme * Fix syntax highlight, maybe * Regenerate * Update help message * Use existing translation files instead of .txt * Add test against wrong Unicode flag --------- Co-authored-by: Alexandre Alapetite --- cli/check.translation.php | 113 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) (limited to 'cli/check.translation.php') diff --git a/cli/check.translation.php b/cli/check.translation.php index ebe665ef7..151a6084f 100755 --- a/cli/check.translation.php +++ b/cli/check.translation.php @@ -14,12 +14,14 @@ $cliOptions = new class extends CliOptionsParser { public bool $displayResult; public bool $help; public bool $displayReport; + public bool $generateReadme; public function __construct() { $this->addOption('language', (new CliOption('language', 'l'))->typeOfArrayOfString()); $this->addOption('displayResult', (new CliOption('display-result', 'd'))->withValueNone()); $this->addOption('help', (new CliOption('help', 'h'))->withValueNone()); $this->addOption('displayReport', (new CliOption('display-report', 'r'))->withValueNone()); + $this->addOption('generateReadme', (new CliOption('generate-readme', 'g'))->withValueNone()); parent::__construct(); } }; @@ -43,6 +45,7 @@ if (isset($cliOptions->language)) { $isValidated = true; $result = []; $report = []; +$percentage = []; foreach ($languages as $language) { if ($language === $i18nData::REFERENCE_LANGUAGE) { @@ -53,6 +56,7 @@ foreach ($languages as $language) { $isValidated = $i18nValidator->validate() && $isValidated; $report[$language] = sprintf('%-5s - %s', $language, $i18nValidator->displayReport()); + $percentage[$language] = $i18nValidator->displayReport(percentage_only: true); $result[$language] = $i18nValidator->displayResult(); } @@ -70,6 +74,114 @@ if ($cliOptions->displayReport) { } } +function writeToReadme(string $readmePath, string $markdownImgStr): void { + $readme = file_get_contents($readmePath); + if ($readme === false) { + echo 'Error: Unable to open ' . $readmePath, PHP_EOL; + exit(1); + } + if (file_put_contents($readmePath, preg_replace('/(.*?)<\/translations>/s', << + + + $markdownImgStr + + + EOF, $readme)) === false) { + echo 'Error: Fail while writing to ' . $readmePath, PHP_EOL; + exit(1); + } + echo 'Successfully written translation status into ' . $readmePath, PHP_EOL; +} + +function embedSvg(string $contents): string { + return preg_replace( + '/]*?)(xmlns=["\'][^"\']+["\']))?(?:(?:[^>]*?)(viewBox=["\'][^"\']+["\']))?(?:[^>]*?)>/i', + '', + $contents + ) ?? ''; +} + +if ($cliOptions->generateReadme) { + $supportedFormats = ['txt', 'svg']; + $flagsDir = __DIR__ . '/../docs/i18n/flags'; + + $markdownImgStr = ''; + foreach ($percentage as $lang => $value) { + $percentageInt = intval(rtrim($value, '%')); + $color = 'green'; + if ($percentageInt < 90) { + $color = 'gold'; + } + if ($percentageInt < 70) { + $color = 'darkred'; + } + $svgFile = $flagsDir . '/' . $lang . '.svg'; + $svg = ''; + if (file_exists($svgFile)) { + $svg = file_get_contents($svgFile); + if ($svg === false) { + echo 'Error: Unable to open ' . $svgFile, PHP_EOL; + exit(1); + } + } + + $ghSearchUrl = 'https://github.com/search?q=' . urlencode("repo:FreshRSS/FreshRSS path:app/i18n/$lang /(TODO|DIRTY)$/"); + $genPath = $flagsDir . '/gen/' . $lang . '.svg'; + $template = '' . "\n"; + + if ($svg === '') { + $i18nGen = include __DIR__ . "/../app/i18n/$lang/gen.php"; + if (!is_array($i18nGen) || !is_string($i18nGen['flag'] ?? null)) { + echo 'Error: No Unicode flag found for language ' . $lang, PHP_EOL; + exit(1); + } + $unicodeFlag = $i18nGen['flag']; + if ($lang !== 'en' && $unicodeFlag === '🇬🇧') { + echo 'Error: Wrong Unicode flag for language ' . $lang, PHP_EOL; + exit(1); + } + $value = $unicodeFlag . ' ' . $percentageInt . '%'; + $template .= << + + + $value + + + EOF; + } else { + // An SVG file is available to override the Unicode flag + $value = $percentageInt . '%'; + $contents = embedSvg($svg); + $template .= << + + + + $contents + + $value + + + EOF; + } + if (file_put_contents($genPath, $template) === false) { + echo 'Error: Fail while writing to ' . $genPath, PHP_EOL; + exit(1); + } + $markdownImgStr .= "[![$lang](./docs/i18n/flags/gen/$lang.svg)]($ghSearchUrl) "; + } + // In case we're located in ./cli/ + if (!file_exists('constants.php')) { + chdir('..'); + } + foreach (array_merge(['README.md'], glob('README.*.md') ?: []) as $readmePath) { + writeToReadme($readmePath, rtrim($markdownImgStr)); + } + exit(); +} + if (!$isValidated) { exit(1); } @@ -121,6 +233,7 @@ DESCRIPTION -h, --help display this help and exit. -l, --language=LANG filter by LANG. -r, --display-report display completion report. + -g, --generate-readme generate readme for translation status. HELP; exit(); -- cgit v1.2.3