From 51c58e029e06a6fbf0556474fa22c93bc471f2ec Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Thu, 25 Sep 2025 15:50:18 +0200 Subject: [PATCH 01/26] Add FileValidator-Function for composer.json --- .../Command/ValidateCommand.php | 6 +- .../Validator/FileValidator.php | 198 ++++++++++++++---- 2 files changed, 163 insertions(+), 41 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Command/ValidateCommand.php b/src/Phpbb/TranslationValidator/Command/ValidateCommand.php index e65bf8b..7aa1d38 100644 --- a/src/Phpbb/TranslationValidator/Command/ValidateCommand.php +++ b/src/Phpbb/TranslationValidator/Command/ValidateCommand.php @@ -25,7 +25,7 @@ protected function configure() ->setName('validate') ->setDescription('Run the validator on your language pack.') ->addArgument('origin-iso', InputArgument::REQUIRED, 'The ISO of the language to validate') - ->addOption('phpbb-version', null, InputOption::VALUE_OPTIONAL, 'The phpBB Version to validate against', '3.3') + ->addOption('phpbb-version', null, InputOption::VALUE_OPTIONAL, 'The phpBB Version to validate against', '4.0') ->addOption('source-iso', null, InputOption::VALUE_OPTIONAL, 'The ISO of the language to validate against', 'en') ->addOption('package-dir', null, InputOption::VALUE_OPTIONAL, 'The path to the directory with the language packages', null) ->addOption('language-dir', null, InputOption::VALUE_OPTIONAL, 'The path to the directory with the language folders', null) @@ -52,9 +52,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $displayNotices = $input->getOption('display-notices'); $safeMode = $input->getOption('safe-mode'); - if (!in_array($phpbbVersion, array('3.2', '3.3'))) + if ($phpbbVersion != '4.0') { - throw new \RuntimeException('Invalid phpbb-version, allowed versions: 3.2 and 3.3'); + throw new \RuntimeException('Invalid phpbb-version, allowed versions: 4.0'); } $output = new Output($output, $debug); diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 784f275..1ed6354 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -119,6 +119,47 @@ class FileValidator '', // Allow empty strings ]; + /** @var array List from https://developers.cloudflare.com/turnstile/reference/supported-languages/ */ + private $reTurnstilesLanguages = [ + 'ar', + 'bg', + 'zh', + 'hr', + 'cs', + 'da', + 'nl', + 'en', + 'fa', + 'fi', + 'fr', + 'de', + 'el', + 'he', + 'hi', + 'hu', + 'id', + 'it', + 'ja', + 'ko', + 'lt', + 'ms', + 'nb', + 'pl', + 'pt', + 'ro', + 'ru', + 'sr', + 'sk', + 'sl', + 'es', + 'sv', + 'tl', + 'th', + 'tr', + 'uk', + 'vi', + '', // Allow empty strings + ]; /** * @param InputInterface $input * @param OutputInterface $output @@ -260,9 +301,9 @@ public function validate($sourceFile, $originFile) { $this->validateLicenseFile($originFile); } - else if ($originFile === $this->originLanguagePath . 'iso.txt') + else if ($originFile === $this->originLanguagePath . 'composer.json') { - $this->validateIsoFile($originFile); + $this->validateJsonFile($originFile); } else if (substr($originFile, -4) === '.css') { @@ -361,32 +402,10 @@ public function validateLangFile($sourceFile, $originFile) $this->output->addMessage(Output::FATAL, 'Must not contain key: ' . $validateLangKey, $originFile); } } - - // Check reCaptcha file - if ($originFile === $this->originLanguagePath . 'captcha_recaptcha.php') - { - $this->validateReCaptchaValue($originFile, $validate); - } - } - - /** - * Check that the reCaptcha key provided is allowed - * @param $originFile - * @param array $validate - */ - public function validateReCaptchaValue($originFile, $validate) - { - // The key 'RECAPTCHA_LANG' must match the list provided by Google, or be left empty - // If any other key is used, we will show an error - if (array_key_exists('RECAPTCHA_LANG', $validate) && !in_array($validate['RECAPTCHA_LANG'], $this->reCaptchaLanguages)) - { - // The supplied value doesn't match the allowed values - $this->output->addMessage(Output::ERROR, 'reCaptcha must match a language/country code on https://developers.google.com/recaptcha/docs/language - if no code exists for your language you can use "en" or leave the string empty', $originFile, 'RECAPTCHA_LANG'); - } } /** - * Validates a email .txt file + * Validates an email .txt file * * Emails must have a subject when the source file has one, otherwise must not have one. * Emails must have a signature when the source file has one, otherwise must not have one. @@ -521,26 +540,129 @@ public function validateIndexFile($originFile) } /** - * Validates the iso.txt file + * Validates the composer.json file * - * Should only contain 3 lines: - * 1. English name of the language - * 2. Native name of the language - * 3. Line with information about the author + * Should be valid and contain the necessary information: + * Mandatory: + * name, description, type, version, homepage, license + * Authors: name (optional: email and homepage) + * Extra: language-iso, english-name, local-name, + * phpbb-version, direction, user-lang, plural-rule, + * recaptcha-lang, turnstile-lang + * Optional: + * Support: urls to: forum, wiki, issues etc * * @param string $originFile File to validate * @return null */ - public function validateIsoFile($originFile) + public function validateJsonFile($originFile) { $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); - $isoFile = explode("\n", $fileContents); - - if (sizeof($isoFile) != 3) - { - $this->output->addMessage(Output::FATAL, 'Must contain exactly 3 lines: 1. English name, 2. Native name, 3. Author information', $originFile); - } - } + $jsonContent = json_decode($fileContents, true); + + if (!$jsonContent['name'] == (substr($originFile, 21) === 'phpbb/phpbb-language-')) + { + $this->output->addMessage(Output::FATAL, 'File must have name value which starts with phpbb/phpbb-language- following by the language iso code', $originFile); + } + + if (!array_key_exists('description', $jsonContent)) + { + $this->output->addMessage(Output::FATAL, 'File must contain a description value', $originFile); + } + // Check if the type is correctly defined + if (!$jsonContent['type'] == 'phpbb-language') + { + $this->output->addMessage(Output::FATAL, 'File must contain a type with the value "phpbb-language"', $originFile); + } + // Check if there is a valid version definition + if (!array_key_exists('version', $jsonContent)) + { + $this->output->addMessage(Output::FATAL, 'Language pack needs a version definition.', $originFile); + } + elseif ($jsonContent['version'] == '') + { + $this->output->addMessage(Output::FATAL, 'The defined version should not be empty.', $originFile); + } + elseif (preg_match('^(\d+\.)?(\d+\.)?(\*|\d+)$', $jsonContent['version'])) + { + $this->output->addMessage(Output::FATAL, 'The defined version is in the wrong format.', $originFile); + } + // Homepage should be at least an empty string + if (!array_key_exists('homepage', $jsonContent)) + { + $this->output->addMessage(Output::FATAL, 'The homepage value is missing, can be an empty string.', $originFile); + } + // Check for the correct license value + if (!$jsonContent['license'] == 'GPL-2.0') + { + $this->output->addMessage(Output::FATAL, 'The license value has to be "GPL-2.0"', $originFile); + } + // Check for the authors + if (!array_key_exists('authors', $jsonContent)) + { + $this->output->addMessage(Output::FATAL, 'The authors value is missing.', $originFile); + } + // Check for support, authors should at least give one contact option! + if (!array_key_exists('support', $jsonContent)) + { + $this->output->addMessage(Output::FATAL, 'The support value is missing.', $originFile); + } + elseif (count ($jsonContent['support']) < 1) + { + $this->output->addMessage(Output::FATAL, 'The support value has not sub values. Please provide at least one contact option e.g. forum, email.', $originFile); + } + // Check for the extra-section + if (!array_key_exists('extra', $jsonContent)) + { + $this->output->addMessage(Output::FATAL, 'The extra section is missing.', $originFile); + } + // language-iso must be valid + if (preg_match('^(?:[a-z]*_?){0,2}[a-z]*$', $jsonContent['extra']['language-iso'])) + { + $this->output->addMessage(Output::FATAL, 'The language-iso should only contain small letters from a to z or maximum two underscores.', $originFile); + } + // Check for english name + if ($jsonContent['extra']['english-name'] == '' || preg_match('^[a-zA-Z\s]+$', $jsonContent['extra']['english-name'])) + { + $this->output->addMessage(Output::ERROR, 'The english-name value should only contain letters aA-zZ and spaces.', $originFile); + } + // Check for local name + if ($jsonContent['extra']['local-name'] == '') + { + $this->output->addMessage(Output::ERROR, 'The local-name value should not be empty.', $originFile); + } + // Check for valid phpBB-Version, we accept: 4.0.0, 4.0.0-a1 or 4.0.0-b1 or 4.0.0-RC1 + if (!preg_match('^\d+\.\d+\.\d+(-(?:a|b|RC)\d+)?$', $jsonContent['extra']['phpbb-version']) || $jsonContent['extra']['phpbb-version'] == '' ) + { + $this->output->addMessage(Output::FATAL, 'The phpbb-version value should not be empty and contain a valid version number.', $originFile); + } + // Check for valid direction + $direction = $jsonContent['extra']['phpbb-direction']; + if (!in_array($direction, array('ltr', 'rtl'))) + { + $this->output->addMessage(Output::FATAL, 'The direction can only be rtl or ltr.', $originFile); + } + // Check for user-lang: en-gb + if (!isset($jsonContent['extra']['user-lang']) || $jsonContent['extra']['user-lang'] == '') + { + $this->output->addMessage(Output::FATAL, 'The user-lang must be defined.', $originFile); + } + // Check for plural-rule + if (!preg_match('^(?:[0-9]|1[0-5])$', $jsonContent['extra']['plural-rule'])) + { + $this->output->addMessage(Output::FATAL, 'Plural rules does not have a valid value.', $originFile); + } + // Check for valid recaptcha-lang: en-GB + if (!in_array($jsonContent['extra']['recaptcha-lang'], $this->reCaptchaLanguages)) + { + $this->output->addMessage(Output::ERROR, 'reCaptcha must match a language/country code on https://developers.google.com/recaptcha/docs/language - if no code exists for your language you can use "en" or leave the string empty', $originFile); + } + // Check for valid turnstile-lang: en (should be in: https://developers.cloudflare.com/turnstile/reference/supported-languages/ ) + if (!in_array($jsonContent['extra']['turnstile-lang'], $this->reTurnstilesLanguages)) + { + $this->output->addMessage(Output::ERROR, 'Turnstile must match a 2-digit-language code from https://developers.cloudflare.com/turnstile/reference/supported-languages/ ', $originFile); + } + } /** * Validates whether a file checks for the IN_PHPBB constant From 4b49c5bc127a4f301fc0347443773673cd796ff1 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Thu, 25 Sep 2025 16:35:36 +0200 Subject: [PATCH 02/26] Add preg_match limiter / --- .../Validator/FileValidator.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 1ed6354..8fb3d15 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -557,7 +557,7 @@ public function validateIndexFile($originFile) */ public function validateJsonFile($originFile) { - $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); + $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); $jsonContent = json_decode($fileContents, true); if (!$jsonContent['name'] == (substr($originFile, 21) === 'phpbb/phpbb-language-')) @@ -583,7 +583,7 @@ public function validateJsonFile($originFile) { $this->output->addMessage(Output::FATAL, 'The defined version should not be empty.', $originFile); } - elseif (preg_match('^(\d+\.)?(\d+\.)?(\*|\d+)$', $jsonContent['version'])) + elseif (preg_match('/^(\d+\.)?(\d+\.)?(\*|\d+)$/', $jsonContent['version'])) { $this->output->addMessage(Output::FATAL, 'The defined version is in the wrong format.', $originFile); } @@ -617,12 +617,12 @@ public function validateJsonFile($originFile) $this->output->addMessage(Output::FATAL, 'The extra section is missing.', $originFile); } // language-iso must be valid - if (preg_match('^(?:[a-z]*_?){0,2}[a-z]*$', $jsonContent['extra']['language-iso'])) + if (preg_match('/^(?:[a-z]*_?){0,2}[a-z]*$/', $jsonContent['extra']['language-iso'])) { - $this->output->addMessage(Output::FATAL, 'The language-iso should only contain small letters from a to z or maximum two underscores.', $originFile); + $this->output->addMessage(Output::FATAL, 'The language-iso should only contain small letters from a to z and maximum two underscores.', $originFile); } // Check for english name - if ($jsonContent['extra']['english-name'] == '' || preg_match('^[a-zA-Z\s]+$', $jsonContent['extra']['english-name'])) + if ($jsonContent['extra']['english-name'] == '' || preg_match('/^[a-zA-Z\s]+$/', $jsonContent['extra']['english-name'])) { $this->output->addMessage(Output::ERROR, 'The english-name value should only contain letters aA-zZ and spaces.', $originFile); } @@ -632,12 +632,12 @@ public function validateJsonFile($originFile) $this->output->addMessage(Output::ERROR, 'The local-name value should not be empty.', $originFile); } // Check for valid phpBB-Version, we accept: 4.0.0, 4.0.0-a1 or 4.0.0-b1 or 4.0.0-RC1 - if (!preg_match('^\d+\.\d+\.\d+(-(?:a|b|RC)\d+)?$', $jsonContent['extra']['phpbb-version']) || $jsonContent['extra']['phpbb-version'] == '' ) + if (!preg_match('/^\d+\.\d+\.\d+(-(?:a|b|RC)\d+)?$/', $jsonContent['extra']['phpbb-version']) || $jsonContent['extra']['phpbb-version'] == '' ) { $this->output->addMessage(Output::FATAL, 'The phpbb-version value should not be empty and contain a valid version number.', $originFile); } // Check for valid direction - $direction = $jsonContent['extra']['phpbb-direction']; + $direction = $jsonContent['extra']['direction']; if (!in_array($direction, array('ltr', 'rtl'))) { $this->output->addMessage(Output::FATAL, 'The direction can only be rtl or ltr.', $originFile); @@ -648,7 +648,7 @@ public function validateJsonFile($originFile) $this->output->addMessage(Output::FATAL, 'The user-lang must be defined.', $originFile); } // Check for plural-rule - if (!preg_match('^(?:[0-9]|1[0-5])$', $jsonContent['extra']['plural-rule'])) + if (!preg_match('/^(?:[0-9]|1[0-5])$/', $jsonContent['extra']['plural-rule'])) { $this->output->addMessage(Output::FATAL, 'Plural rules does not have a valid value.', $originFile); } From 42d3e748c09ded81faf3339943f8cde870fac833 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Thu, 25 Sep 2025 17:09:58 +0200 Subject: [PATCH 03/26] Repair language-iso and name check of composer.json --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 8fb3d15..6485fbd 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -560,9 +560,9 @@ public function validateJsonFile($originFile) $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); $jsonContent = json_decode($fileContents, true); - if (!$jsonContent['name'] == (substr($originFile, 21) === 'phpbb/phpbb-language-')) + if (!str_starts_with($jsonContent['name'], 'phpbb/phpbb-language-')) { - $this->output->addMessage(Output::FATAL, 'File must have name value which starts with phpbb/phpbb-language- following by the language iso code', $originFile); + $this->output->addMessage(Output::FATAL, 'Name should start with phpbb/phpbb-language- followed by the language iso code', $originFile); } if (!array_key_exists('description', $jsonContent)) @@ -617,7 +617,7 @@ public function validateJsonFile($originFile) $this->output->addMessage(Output::FATAL, 'The extra section is missing.', $originFile); } // language-iso must be valid - if (preg_match('/^(?:[a-z]*_?){0,2}[a-z]*$/', $jsonContent['extra']['language-iso'])) + if (!preg_match('/^(?:[a-z]*_?){0,2}[a-z]*$/', $jsonContent['extra']['language-iso'])) { $this->output->addMessage(Output::FATAL, 'The language-iso should only contain small letters from a to z and maximum two underscores.', $originFile); } From c8e6b9ae36851f854948f8f56595c330766865b4 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Thu, 25 Sep 2025 17:31:31 +0200 Subject: [PATCH 04/26] Remove ValidateIsoTest.php from tests/ --- tests/FileValidator/ValidateIsoTest.php | 36 ------------------------- 1 file changed, 36 deletions(-) delete mode 100644 tests/FileValidator/ValidateIsoTest.php diff --git a/tests/FileValidator/ValidateIsoTest.php b/tests/FileValidator/ValidateIsoTest.php deleted file mode 100644 index 7e4f3f3..0000000 --- a/tests/FileValidator/ValidateIsoTest.php +++ /dev/null @@ -1,36 +0,0 @@ -validator->validateIsoFile($file); - $this->assertOutputMessages($expected); - } -} From 8449fc3b62a7a853724a588bd1478ab70ad98e58 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 09:46:50 +0200 Subject: [PATCH 05/26] Change plural-rule guessing to composer.json --- README.md | 4 +- .../Validator/ValidatorRunner.php | 41 ++++++++----------- translation.php | 2 +- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 6b36133..dbd6186 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,11 @@ For the easiest results, create a directory called `4.0` in the root of the Tran phpbb-translation-validator/4.0/de/ phpbb-translation-validator/translation.php -The simplest way to validate is to then run this command (the final argument is the language you wish to test and that has already been uploaded to the `3.2` directory; eg. `fr` for French): +The simplest way to validate is to then run this command (the final argument is the language you wish to test and that has already been uploaded to the `4.0` directory; eg. `fr` for French): php translation.php validate fr -There are more arguments that can be supplied. For example, suppose you wanted to have your `3.2` directory in a different location, you wanted to explicitly specify phpBB version 3.2 (default validation is against 3.3), you wanted to run in safe mode and you wanted to see all notices displayed - you would run this command: +There are more arguments that can be supplied. For example, suppose you wanted to have your `4.x` directory in a different location, you wanted to explicitly specify phpBB version 4.x (default validation is against 4.0), you wanted to run in safe mode and you wanted to see all notices displayed - you would run this command: php translation.php validate fr --package-dir=/path/to/your/4.0 diff --git a/src/Phpbb/TranslationValidator/Validator/ValidatorRunner.php b/src/Phpbb/TranslationValidator/Validator/ValidatorRunner.php index 9bbef53..a8616c0 100644 --- a/src/Phpbb/TranslationValidator/Validator/ValidatorRunner.php +++ b/src/Phpbb/TranslationValidator/Validator/ValidatorRunner.php @@ -228,36 +228,31 @@ protected function printErrorLevel(Output $output) } /** - * Try to find the plural rule for the language + * Try to find the plural rule for the language in composer.json * @return int */ - protected function guessPluralRule() + protected function guessPluralRule(): int { - $filePath = $this->originPath . '/' . $this->originLanguagePath . 'common.php'; + // TODO: Check for safeMode and langParser integration here in that function + $filePath = $this->originPath . '/' . $this->originLanguagePath . 'composer.json'; - if (file_exists($filePath)) - { - if ($this->safeMode) - { - $lang = self::langParser($filePath); - } - - else - { - include($filePath); - } - - if (!isset($lang['PLURAL_RULE'])) - { - $this->output->writelnIfDebug("No plural rule set, falling back to plural rule #1"); - } - } + if (file_exists($filePath)) + { + + $fileContents = (string) file_get_contents($filePath); + $jsonContent = json_decode($fileContents, true); + + if (!isset($jsonContent['extra']['plural-rule'])) + { + $this->output->writelnIfDebug("No plural rule set, falling back to plural rule #1"); + } + } else { - $this->output->writelnIfDebug("Could not find common.php, falling back to plural rule #1"); + $this->output->writelnIfDebug("Could not find composer.json, falling back to plural rule #1"); } - return isset($lang['PLURAL_RULE']) ? $lang['PLURAL_RULE'] : 1; + return $jsonContent['extra']['plural-rule'] ?? 1; } /** @@ -278,7 +273,7 @@ public static function arrayParser($file) * @param string $relativePath * @return array */ - public static function langParser($filePath, $relativePath = '') + public static function langParser($filePath, string $relativePath = '') { $lang = []; $parsed = self::arrayParser($relativePath . $filePath); diff --git a/translation.php b/translation.php index 1b8b7a5..f160b62 100644 --- a/translation.php +++ b/translation.php @@ -8,7 +8,7 @@ * */ -const TRANSLATION_VALIDATOR_VERSION = '1.6.0'; +const TRANSLATION_VALIDATOR_VERSION = '2.0.0-dev'; require 'vendor/autoload.php'; From 40177ad988df47e23a6a17580e2a2081ad4769ff Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 10:06:01 +0200 Subject: [PATCH 06/26] Use a separate function for recaptcha and turnstile lang-key check --- .../Validator/FileValidator.php | 22 ++++++++++++++----- tests/FileValidator/ValidateLangTest.php | 4 ++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 6485fbd..b61a952 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -304,6 +304,7 @@ public function validate($sourceFile, $originFile) else if ($originFile === $this->originLanguagePath . 'composer.json') { $this->validateJsonFile($originFile); + $this->validateCaptchaValues($originFile); } else if (substr($originFile, -4) === '.css') { @@ -547,8 +548,7 @@ public function validateIndexFile($originFile) * name, description, type, version, homepage, license * Authors: name (optional: email and homepage) * Extra: language-iso, english-name, local-name, - * phpbb-version, direction, user-lang, plural-rule, - * recaptcha-lang, turnstile-lang + * phpbb-version, direction, user-lang, plural-rule * Optional: * Support: urls to: forum, wiki, issues etc * @@ -652,15 +652,27 @@ public function validateJsonFile($originFile) { $this->output->addMessage(Output::FATAL, 'Plural rules does not have a valid value.', $originFile); } + } + + /** + * Check that the reCaptcha and Turnstile key provided is allowed + * @param $originFile + */ + public function validateCaptchaValues($originFile) + { + $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); + $jsonContent = json_decode($fileContents, true); + // The key 'RECAPTCHA_LANG' must match the list provided by Google, or be left empty // Check for valid recaptcha-lang: en-GB if (!in_array($jsonContent['extra']['recaptcha-lang'], $this->reCaptchaLanguages)) { - $this->output->addMessage(Output::ERROR, 'reCaptcha must match a language/country code on https://developers.google.com/recaptcha/docs/language - if no code exists for your language you can use "en" or leave the string empty', $originFile); + $this->output->addMessage(Output::ERROR, 'reCaptcha must match a language/country code on https://developers.google.com/recaptcha/docs/language - if no code exists for your language you can use "en".', $originFile); } - // Check for valid turnstile-lang: en (should be in: https://developers.cloudflare.com/turnstile/reference/supported-languages/ ) + // Check for valid turnstile-lang: en + // (should be in: https://developers.cloudflare.com/turnstile/reference/supported-languages/ ) if (!in_array($jsonContent['extra']['turnstile-lang'], $this->reTurnstilesLanguages)) { - $this->output->addMessage(Output::ERROR, 'Turnstile must match a 2-digit-language code from https://developers.cloudflare.com/turnstile/reference/supported-languages/ ', $originFile); + $this->output->addMessage(Output::ERROR, 'Turnstile must match a 2-digit-language code from https://developers.cloudflare.com/turnstile/reference/supported-languages/ - if no code exists for your language you can use "en".', $originFile); } } diff --git a/tests/FileValidator/ValidateLangTest.php b/tests/FileValidator/ValidateLangTest.php index cc9316b..4ae7c47 100644 --- a/tests/FileValidator/ValidateLangTest.php +++ b/tests/FileValidator/ValidateLangTest.php @@ -45,7 +45,7 @@ public function testValidateLangReCaptcha() { // Failure - as we supply a key that isn't valid $reCaptchaLanguage = ['RECAPTCHA_LANG' => 'incorrect']; - $this->validator->validateReCaptchaValue('', $reCaptchaLanguage); + $this->validator->validateCaptchaValues('', $reCaptchaLanguage); $output = $this->output->getMessages(); $expected = Output::ERROR . '-reCaptcha must match a language/country code on https://developers.google.com/recaptcha/docs/language - if no code exists for your language you can use "en" or leave the string empty--RECAPTCHA_LANG'; @@ -55,7 +55,7 @@ public function testValidateLangReCaptcha() // Pass - as 'en' is valid $reCaptchaLanguage['RECAPTCHA_LANG'] = 'en'; - $this->validator->validateReCaptchaValue('', $reCaptchaLanguage); + $this->validator->validateCaptchaValues('', $reCaptchaLanguage); $this->assertEquals($this->output->getMessageCount(Output::ERROR), 1); // Shouldn't change in size as no error added } From 06cc5ae629e2b44805024a3b03b6b17b2af61560 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 10:33:58 +0200 Subject: [PATCH 07/26] Use a dedi function to open the composer.json --- .../Validator/FileValidator.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index b61a952..9590baf 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -268,6 +268,16 @@ public function setSafeMode($safeMode) return $this; } + /** + * Open the composer.json of the language pack and + * save it to an array, accessible for the following functions + */ + public function openComposerJson($originFile) + { + $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); + return json_decode($fileContents, true); + } + /** * Decides which validation function to use * @@ -557,8 +567,7 @@ public function validateIndexFile($originFile) */ public function validateJsonFile($originFile) { - $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); - $jsonContent = json_decode($fileContents, true); + $jsonContent = $this->openComposerJson($originFile); if (!str_starts_with($jsonContent['name'], 'phpbb/phpbb-language-')) { @@ -660,8 +669,8 @@ public function validateJsonFile($originFile) */ public function validateCaptchaValues($originFile) { - $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); - $jsonContent = json_decode($fileContents, true); + $jsonContent = $this->openComposerJson($originFile); + // The key 'RECAPTCHA_LANG' must match the list provided by Google, or be left empty // Check for valid recaptcha-lang: en-GB if (!in_array($jsonContent['extra']['recaptcha-lang'], $this->reCaptchaLanguages)) From 1451e78519be531f33897ecac2ffa47036a9c25b Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 10:50:26 +0200 Subject: [PATCH 08/26] Fix tests for Validate Captchas --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 7 ++++++- tests/FileValidator/ValidateLangTest.php | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 9590baf..13e42a2 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -667,10 +667,15 @@ public function validateJsonFile($originFile) * Check that the reCaptcha and Turnstile key provided is allowed * @param $originFile */ - public function validateCaptchaValues($originFile) + public function validateCaptchaValues($originFile, $optParams = '') { $jsonContent = $this->openComposerJson($originFile); + if (!$optParams == '') + { + $jsonContent['extra']['recaptcha-lang'] = $optParams; + //$jsonContent['extra']['turnstile-lang'] = $optParams; + } // The key 'RECAPTCHA_LANG' must match the list provided by Google, or be left empty // Check for valid recaptcha-lang: en-GB if (!in_array($jsonContent['extra']['recaptcha-lang'], $this->reCaptchaLanguages)) diff --git a/tests/FileValidator/ValidateLangTest.php b/tests/FileValidator/ValidateLangTest.php index 4ae7c47..9531177 100644 --- a/tests/FileValidator/ValidateLangTest.php +++ b/tests/FileValidator/ValidateLangTest.php @@ -41,10 +41,10 @@ public function testValidateLangFile($file, $expected) /** * Test the reCaptcha checks */ - public function testValidateLangReCaptcha() + public function testValidateLangCaptchas() { // Failure - as we supply a key that isn't valid - $reCaptchaLanguage = ['RECAPTCHA_LANG' => 'incorrect']; + $reCaptchaLanguage = 'incorrect'; $this->validator->validateCaptchaValues('', $reCaptchaLanguage); $output = $this->output->getMessages(); @@ -54,7 +54,7 @@ public function testValidateLangReCaptcha() $this->assertEquals($output[0], $expected); // Pass - as 'en' is valid - $reCaptchaLanguage['RECAPTCHA_LANG'] = 'en'; + $reCaptchaLanguage = 'en'; $this->validator->validateCaptchaValues('', $reCaptchaLanguage); $this->assertEquals($this->output->getMessageCount(Output::ERROR), 1); // Shouldn't change in size as no error added From de4638279a661343f425db6a37372f9f34a175e1 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 11:46:41 +0200 Subject: [PATCH 09/26] Add check for valid language iso in composer.json --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 13e42a2..095c494 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -630,6 +630,10 @@ public function validateJsonFile($originFile) { $this->output->addMessage(Output::FATAL, 'The language-iso should only contain small letters from a to z and maximum two underscores.', $originFile); } + elseif ($jsonContent['extra']['language-iso'] != $this->originIso) + { + $this->output->addMessage(Output::FATAL, 'Language iso is not valid', $originFile); + } // Check for english name if ($jsonContent['extra']['english-name'] == '' || preg_match('/^[a-zA-Z\s]+$/', $jsonContent['extra']['english-name'])) { From a107d4667930c14abdf57c76d4ec562478ac4ef2 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 11:55:54 +0200 Subject: [PATCH 10/26] Change required license to GPL-2.0-only --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 095c494..61f9674 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -602,9 +602,9 @@ public function validateJsonFile($originFile) $this->output->addMessage(Output::FATAL, 'The homepage value is missing, can be an empty string.', $originFile); } // Check for the correct license value - if (!$jsonContent['license'] == 'GPL-2.0') + if ($jsonContent['license'] != 'GPL-2.0-only') { - $this->output->addMessage(Output::FATAL, 'The license value has to be "GPL-2.0"', $originFile); + $this->output->addMessage(Output::FATAL, 'The license value has to be "GPL-2.0-only"', $originFile); } // Check for the authors if (!array_key_exists('authors', $jsonContent)) From 46a206b477f943c380004ac5be19c1fe5662b4ba Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 11:56:54 +0200 Subject: [PATCH 11/26] Add 4.0/ to ignored directories --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 18dfb74..0f0313b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /vendor/ /.idea/ /bin/ -/3.2/ -/3.3/ +/4.0/ From 48177df21dd096753752fd80d842bd9483017837 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 12:28:45 +0200 Subject: [PATCH 12/26] Repair version format check --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 61f9674..8e3c642 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -592,7 +592,7 @@ public function validateJsonFile($originFile) { $this->output->addMessage(Output::FATAL, 'The defined version should not be empty.', $originFile); } - elseif (preg_match('/^(\d+\.)?(\d+\.)?(\*|\d+)$/', $jsonContent['version'])) + elseif (!preg_match('/^(\d+\.)?(\d+\.)?(\*|\d+)$/', $jsonContent['version'])) { $this->output->addMessage(Output::FATAL, 'The defined version is in the wrong format.', $originFile); } From 8b4bbad85113d943a2e2be2144d292cbbc2ef5ed Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 13:49:28 +0200 Subject: [PATCH 13/26] Check for correct type --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 8e3c642..963cd84 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -579,7 +579,7 @@ public function validateJsonFile($originFile) $this->output->addMessage(Output::FATAL, 'File must contain a description value', $originFile); } // Check if the type is correctly defined - if (!$jsonContent['type'] == 'phpbb-language') + if ($jsonContent['type'] != 'phpbb-language') { $this->output->addMessage(Output::FATAL, 'File must contain a type with the value "phpbb-language"', $originFile); } From 616a8a76369d8e097f325743ac91a54ae1b6f7ba Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 14:21:00 +0200 Subject: [PATCH 14/26] Add URL check for homepage --- .../Validator/FileValidator.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 963cd84..ea94179 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -573,10 +573,15 @@ public function validateJsonFile($originFile) { $this->output->addMessage(Output::FATAL, 'Name should start with phpbb/phpbb-language- followed by the language iso code', $originFile); } - - if (!array_key_exists('description', $jsonContent)) + // Check for an existing description + if (!array_key_exists('description', $jsonContent) || $jsonContent['description'] == '') + { + $this->output->addMessage(Output::FATAL, 'Description is missing', $originFile); + } + // Check if the description contains only words and punctuation, not URLs. + elseif (preg_match('/\b(?:www|https)\b|(?:\.[a-z]{2,})/i', $jsonContent['description'])) { - $this->output->addMessage(Output::FATAL, 'File must contain a description value', $originFile); + $this->output->addMessage(Output::FATAL, 'The description should only contain words - no URLs.', $originFile); } // Check if the type is correctly defined if ($jsonContent['type'] != 'phpbb-language') @@ -597,9 +602,9 @@ public function validateJsonFile($originFile) $this->output->addMessage(Output::FATAL, 'The defined version is in the wrong format.', $originFile); } // Homepage should be at least an empty string - if (!array_key_exists('homepage', $jsonContent)) + if (!preg_match('/(?:https?:\/\/|www\.)[^\s]+|(?:\b[a-z0-9-]+\.(?:com|net|org|info|io|co|biz|me|xyz|ai|app|dev|tech|tv|us|uk|de|fr|ru|jp|cn|in)\b)/i', $jsonContent['homepage']) && $jsonContent['homepage'] != '') { - $this->output->addMessage(Output::FATAL, 'The homepage value is missing, can be an empty string.', $originFile); + $this->output->addMessage(Output::FATAL, 'The homepage value allows only URLs or can be left empty.', $originFile); } // Check for the correct license value if ($jsonContent['license'] != 'GPL-2.0-only') From 9d218184b219e0df78761345960368749f1c9dbc Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 14:26:13 +0200 Subject: [PATCH 15/26] Check text direction has 1 of 2 valid values --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index ea94179..0ef46e7 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -655,8 +655,8 @@ public function validateJsonFile($originFile) $this->output->addMessage(Output::FATAL, 'The phpbb-version value should not be empty and contain a valid version number.', $originFile); } // Check for valid direction - $direction = $jsonContent['extra']['direction']; - if (!in_array($direction, array('ltr', 'rtl'))) + $textDirection = $jsonContent['extra']['direction']; + if (!in_array($textDirection, array('ltr', 'rtl'))) { $this->output->addMessage(Output::FATAL, 'The direction can only be rtl or ltr.', $originFile); } From a57fd86bf61b4452ce6bb0385a7f98b050872f8b Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 14:30:58 +0200 Subject: [PATCH 16/26] Change some JSON-check error levels and messages --- .../Validator/FileValidator.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 0ef46e7..1c0935a 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -581,12 +581,12 @@ public function validateJsonFile($originFile) // Check if the description contains only words and punctuation, not URLs. elseif (preg_match('/\b(?:www|https)\b|(?:\.[a-z]{2,})/i', $jsonContent['description'])) { - $this->output->addMessage(Output::FATAL, 'The description should only contain words - no URLs.', $originFile); + $this->output->addMessage(Output::ERROR, 'The description should only contain words - no URLs.', $originFile); } // Check if the type is correctly defined if ($jsonContent['type'] != 'phpbb-language') { - $this->output->addMessage(Output::FATAL, 'File must contain a type with the value "phpbb-language"', $originFile); + $this->output->addMessage(Output::FATAL, 'Type must be exactly: "phpbb-language"', $originFile); } // Check if there is a valid version definition if (!array_key_exists('version', $jsonContent)) @@ -599,12 +599,12 @@ public function validateJsonFile($originFile) } elseif (!preg_match('/^(\d+\.)?(\d+\.)?(\*|\d+)$/', $jsonContent['version'])) { - $this->output->addMessage(Output::FATAL, 'The defined version is in the wrong format.', $originFile); + $this->output->addMessage(Output::ERROR, 'The defined version is in the wrong format.', $originFile); } // Homepage should be at least an empty string if (!preg_match('/(?:https?:\/\/|www\.)[^\s]+|(?:\b[a-z0-9-]+\.(?:com|net|org|info|io|co|biz|me|xyz|ai|app|dev|tech|tv|us|uk|de|fr|ru|jp|cn|in)\b)/i', $jsonContent['homepage']) && $jsonContent['homepage'] != '') { - $this->output->addMessage(Output::FATAL, 'The homepage value allows only URLs or can be left empty.', $originFile); + $this->output->addMessage(Output::ERROR, 'The homepage value allows only URLs or can be left empty.', $originFile); } // Check for the correct license value if ($jsonContent['license'] != 'GPL-2.0-only') @@ -614,16 +614,16 @@ public function validateJsonFile($originFile) // Check for the authors if (!array_key_exists('authors', $jsonContent)) { - $this->output->addMessage(Output::FATAL, 'The authors value is missing.', $originFile); + $this->output->addMessage(Output::ERROR, 'The authors value is missing.', $originFile); } // Check for support, authors should at least give one contact option! if (!array_key_exists('support', $jsonContent)) { - $this->output->addMessage(Output::FATAL, 'The support value is missing.', $originFile); + $this->output->addMessage(Output::ERROR, 'The support value is missing.', $originFile); } elseif (count ($jsonContent['support']) < 1) { - $this->output->addMessage(Output::FATAL, 'The support value has not sub values. Please provide at least one contact option e.g. forum, email.', $originFile); + $this->output->addMessage(Output::ERROR, 'The support value has not sub values. Please provide at least one contact option e.g. forum, email.', $originFile); } // Check for the extra-section if (!array_key_exists('extra', $jsonContent)) From 2f5d75e3481b7d613f8919136452b4b084281a94 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 14:49:12 +0200 Subject: [PATCH 17/26] Repair tests for Recaptcha --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 3 +-- tests/FileValidator/ValidateLangTest.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 1c0935a..c500235 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -680,10 +680,9 @@ public function validateCaptchaValues($originFile, $optParams = '') { $jsonContent = $this->openComposerJson($originFile); - if (!$optParams == '') + if ($optParams != '') { $jsonContent['extra']['recaptcha-lang'] = $optParams; - //$jsonContent['extra']['turnstile-lang'] = $optParams; } // The key 'RECAPTCHA_LANG' must match the list provided by Google, or be left empty // Check for valid recaptcha-lang: en-GB diff --git a/tests/FileValidator/ValidateLangTest.php b/tests/FileValidator/ValidateLangTest.php index 9531177..dd9b1e1 100644 --- a/tests/FileValidator/ValidateLangTest.php +++ b/tests/FileValidator/ValidateLangTest.php @@ -48,7 +48,7 @@ public function testValidateLangCaptchas() $this->validator->validateCaptchaValues('', $reCaptchaLanguage); $output = $this->output->getMessages(); - $expected = Output::ERROR . '-reCaptcha must match a language/country code on https://developers.google.com/recaptcha/docs/language - if no code exists for your language you can use "en" or leave the string empty--RECAPTCHA_LANG'; + $expected = Output::ERROR . '-reCaptcha must match a language/country code on https://developers.google.com/recaptcha/docs/language - if no code exists for your language you can use "en".--'; $this->assertEquals($this->output->getMessageCount(Output::ERROR), 1); $this->assertEquals($output[0], $expected); From 44453b79ba3fbd20d66e830689a3fb01b4e1e36e Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 18:36:47 +0200 Subject: [PATCH 18/26] Update Readme.md for better looks and recent status --- README.md | 59 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index dbd6186..ab906e2 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,40 @@ -# phpBB Translation Validator - master-dev +# phpBB Translation Validator -This console application allows you to validate [phpBB](https://www.phpbb.com) language packages. +With the help of this command line application you are able +to validate [phpBB](https://www.phpbb.com) language packs. +This application runs on your local machine and can be integrated +into a [GitHub](https://www.github.com) repository. -## Requirements +## πŸ“‹Requirements -This tool requires PHP 8.1 or above. +This tool requires PHP 8.1 or above. In addition it needs several +symfony and other packages, which need to be downloaded and installed with [Composer](https://getcomposer.org). -### Installation -Firstly, download the latest British English (`en`) [language pack from phpBB.com](http://www.phpbb.com/customise/db/translation/british_english/) as this is the default source language. Then clone this repository and download the dependencies: +## πŸ—οΈ Installation + +Clone this repository: git clone https://github.com/phpbb/phpbb-translation-validator.git + +Install the dependencies with Composer: + composer.phar install -For the easiest results, create a directory called `4.0` in the root of the Translation Validator. Upload the `en` language page into this directory, along with the languages you wish to test. Which leads e.g. to: +Create a directory called `4.0` in the root of the Translation Validator. Afterwards download +the [British English language pack](http://www.phpbb.com/customise/db/translation/british_english/) +and put its content into ``4.0/en/``. Do the same with the languages you wish to test. Which leads e.g. to: phpbb-translation-validator/4.0/en/ phpbb-translation-validator/4.0/de/ + phpbb-translation-validator/4.0/fr/ phpbb-translation-validator/translation.php -The simplest way to validate is to then run this command (the final argument is the language you wish to test and that has already been uploaded to the `4.0` directory; eg. `fr` for French): +## βš—οΈ Validate language packs + +The simplest way to validate this language packages, +is to open a command line tool in the validator directory. +Then run this command (the final argument is the language you wish to test and that has already been stored to the `4.0` directory; e.g. `fr` for French): php translation.php validate fr @@ -31,15 +46,15 @@ There are more arguments that can be supplied. For example, suppose you wanted t --safe-mode --display-notices -The `--safe-mode` flag indicates that you want to parse files instead of directly including them. This is useful if you want to run validations on a web server. +The `--safe-mode` flag indicates that you want to parse files instead of directly including them. +This is useful if you want to run validations on a web server. -If you are missing the English language files for the official Viglink extension, they can be easily donwloaded using this command: +If you are missing the English language files for the official Viglink extension, +they can be easily donwloaded using this command: php translation.php download --files=phpbb-extensions/viglink --phpbb-version=4.0 -## Tests - -![GitHub Actions CI](https://github.com/phpbb/phpbb-translation-validator/actions/workflows/phpunit.yaml/badge.svg?branch=master) +## πŸ› οΈ Integration to your Repository In your project you can add phpBB Translation Validator as a dependency: @@ -53,18 +68,24 @@ Then add a `php vendor/bin/translation.php` call to your workflow. We use GitHub Actions as a continuous integration server and phpunit for our unit testing. +### 🏠 Local phpunit execution + To run the unit tests locally, use this command: php vendor/phpunit/phpunit/phpunit tests/ -## Contributing +## πŸ€– Tests + +![GitHub Actions CI](https://github.com/phpbb/phpbb-translation-validator/actions/workflows/phpunit.yaml/badge.svg?branch=master) + +## πŸ§‘β€πŸ’» Contributing -If you notice any problems with this application, please raise an issue at https://github.com/phpbb/phpbb-translation-validator/issues. +If you notice any problems with this application, please raise an issue at the [Github-Repository](https://github.com/phpbb/phpbb-translation-validator/issues). -To submit your own code contributions, please fork the project and submit a pull request at https://github.com/phpbb/phpbb-translation-validator/pulls. +To submit your own code contributions, please fork the project and submit a pull request at [Github-Repository](https://github.com/phpbb/phpbb-translation-validator/pulls). -When a new version is released, the version number will be updated in `composer.json` and `translation.php`. A new tag will be created and the package will become available at https://packagist.org/packages/phpbb/translation-validator. +When a new version is released, the version number will be updated in `composer.json` and `translation.php`. A new tag will be created and the package will become available at [Packagist](https://packagist.org/packages/phpbb/translation-validator). -## License +## πŸ“œ License -[GPLv2](license.txt) +[GNU General Public License v2](license.txt) From c4d3d6cfee081c8d9cfd8478a8616633865391cd Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 18:57:10 +0200 Subject: [PATCH 19/26] Formatting and typo fixes --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index c500235..0d2c1e8 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -274,7 +274,8 @@ public function setSafeMode($safeMode) */ public function openComposerJson($originFile) { - $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); + $fileContents = (string) file_get_contents($this->originPath . '/' . $originFile); + return json_decode($fileContents, true); } @@ -623,7 +624,7 @@ public function validateJsonFile($originFile) } elseif (count ($jsonContent['support']) < 1) { - $this->output->addMessage(Output::ERROR, 'The support value has not sub values. Please provide at least one contact option e.g. forum, email.', $originFile); + $this->output->addMessage(Output::ERROR, 'The support category has no values. Please provide at least one contact option e.g. forum or email.', $originFile); } // Check for the extra-section if (!array_key_exists('extra', $jsonContent)) From ca6c80cfb829138c542f070479449e0886d4185a Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 18:59:26 +0200 Subject: [PATCH 20/26] Add safe-mode functionality again to guessPluralRule() --- .../Validator/ValidatorRunner.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/ValidatorRunner.php b/src/Phpbb/TranslationValidator/Validator/ValidatorRunner.php index a8616c0..30b0c30 100644 --- a/src/Phpbb/TranslationValidator/Validator/ValidatorRunner.php +++ b/src/Phpbb/TranslationValidator/Validator/ValidatorRunner.php @@ -233,14 +233,20 @@ protected function printErrorLevel(Output $output) */ protected function guessPluralRule(): int { - // TODO: Check for safeMode and langParser integration here in that function $filePath = $this->originPath . '/' . $this->originLanguagePath . 'composer.json'; if (file_exists($filePath)) { - - $fileContents = (string) file_get_contents($filePath); - $jsonContent = json_decode($fileContents, true); + // Safe mode for safe execution on a server + if ($this->safeMode) + { + $jsonContent = self::langParser($filePath); + } + else + { + $fileContents = (string) file_get_contents($filePath); + $jsonContent = json_decode($fileContents, true); + } if (!isset($jsonContent['extra']['plural-rule'])) { From b1e4668a991e989bc700874668012af29903b9a3 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 19:10:33 +0200 Subject: [PATCH 21/26] Correct some idents --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index 0d2c1e8..e59b0d0 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -315,7 +315,7 @@ public function validate($sourceFile, $originFile) else if ($originFile === $this->originLanguagePath . 'composer.json') { $this->validateJsonFile($originFile); - $this->validateCaptchaValues($originFile); + $this->validateCaptchaValues($originFile); } else if (substr($originFile, -4) === '.css') { From abf36b6312b58d5beb9c996d1619b8c9db8815b5 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 19:45:50 +0200 Subject: [PATCH 22/26] Fix direction for FileListValidator.php --- .../Validator/FileListValidator.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileListValidator.php b/src/Phpbb/TranslationValidator/Validator/FileListValidator.php index b4ce3c0..d02f0d9 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileListValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileListValidator.php @@ -137,20 +137,21 @@ public function validate() $sourceFiles[] = $this->sourceLanguagePath . 'LICENSE'; $sourceFiles = array_unique($sourceFiles); - // Get $lang['direction'] of translation to allow additional rtl-files for rtl-translations - $filePath = $this->originPath . '/' . $this->originLanguagePath . 'common.php'; + // Get extra->direction from composer.json to allow additional rtl-files for rtl-translations + $filePath = $this->originPath . '/' . $this->originLanguagePath . 'composer.json'; + // Safe mode for safe execution on a server if ($this->safeMode) { - $lang = ValidatorRunner::langParser($filePath); + $jsonContent = self::langParser($filePath); } - else { - include($filePath); + $fileContents = (string) file_get_contents($filePath); + $jsonContent = json_decode($fileContents, true); } - $this->direction = $lang['DIRECTION']; + $this->direction = $jsonContent['extra']['direction']; // Throw error, if invalid direction is used if (!in_array($this->direction, array('rtl', 'ltr'))) { @@ -159,7 +160,6 @@ public function validate() $originFiles = $this->getFileList($this->originPath); - $missingSubsilver2Files = $availableSubsilver2Files = array(); $validFiles = array(); foreach ($sourceFiles as $sourceFile) { From a78a007caf6b95a965eb2a232752e7d1b3c5d3c9 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Fri, 26 Sep 2025 19:51:51 +0200 Subject: [PATCH 23/26] Add a ! to preg_match of english-name value check --- src/Phpbb/TranslationValidator/Validator/FileValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Phpbb/TranslationValidator/Validator/FileValidator.php b/src/Phpbb/TranslationValidator/Validator/FileValidator.php index e59b0d0..9a49c15 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileValidator.php @@ -641,7 +641,7 @@ public function validateJsonFile($originFile) $this->output->addMessage(Output::FATAL, 'Language iso is not valid', $originFile); } // Check for english name - if ($jsonContent['extra']['english-name'] == '' || preg_match('/^[a-zA-Z\s]+$/', $jsonContent['extra']['english-name'])) + if ($jsonContent['extra']['english-name'] == '' || !preg_match('/^[a-zA-Z\s]+$/', $jsonContent['extra']['english-name'])) { $this->output->addMessage(Output::ERROR, 'The english-name value should only contain letters aA-zZ and spaces.', $originFile); } From 9111275778ed5d7b1a1373c05630bf3a44267909 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Sat, 27 Sep 2025 10:05:52 +0200 Subject: [PATCH 24/26] Repair tests for 4.0 in FileListValidator --- .../TranslationValidator/Command/DownloadCommand.php | 3 +-- .../Validator/FileListValidator.php | 4 ---- .../Validator/LangKeyValidator.php | 10 +--------- tests/FileListValidator/FileListTest.php | 2 +- .../fixtures/{3.2 => 4.0}/origin/additional.php | 0 .../fixtures/{3.2 => 4.0}/origin/additional.txt | 0 .../fixtures/{3.2 => 4.0}/origin/file.php | 0 .../{3.2 => 4.0}/origin/language/origin/AUTHORS | 0 .../{3.2 => 4.0}/origin/language/origin/AUTHORS.md | 0 .../{3.2 => 4.0}/origin/language/origin/CHANGELOG | 0 .../{3.2 => 4.0}/origin/language/origin/CHANGELOG.md | 0 .../{3.2 => 4.0}/origin/language/origin/README | 0 .../{3.2 => 4.0}/origin/language/origin/README.md | 0 .../{3.2 => 4.0}/origin/language/origin/VERSION | 0 .../{3.2 => 4.0}/origin/language/origin/VERSION.md | 0 .../{3.2 => 4.0}/origin/language/origin/common.php | 0 .../{3.2 => 4.0}/origin/language/origin/index.htm | 0 .../fixtures/{3.2 => 4.0}/origin/subdir/additional.php | 0 .../fixtures/{3.2 => 4.0}/origin/subdir/file.php | 0 .../fixtures/{3.2 => 4.0}/source/file.php | 0 .../{3.2 => 4.0}/source/language/source/common.php | 0 .../fixtures/{3.2 => 4.0}/source/missing.php | 0 .../fixtures/{3.2 => 4.0}/source/missing.txt | 0 .../fixtures/{3.2 => 4.0}/source/subdir/file.php | 0 .../fixtures/{3.2 => 4.0}/source/subdir/missing.php | 0 tests/FileValidator/ValidateNoPhpClosingTagTest.php | 2 +- tests/LangKeyValidator/TestBase.php | 2 +- 27 files changed, 5 insertions(+), 18 deletions(-) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/additional.php (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/additional.txt (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/file.php (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/AUTHORS (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/AUTHORS.md (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/CHANGELOG (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/CHANGELOG.md (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/README (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/README.md (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/VERSION (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/VERSION.md (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/common.php (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/language/origin/index.htm (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/subdir/additional.php (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/origin/subdir/file.php (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/source/file.php (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/source/language/source/common.php (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/source/missing.php (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/source/missing.txt (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/source/subdir/file.php (100%) rename tests/FileListValidator/fixtures/{3.2 => 4.0}/source/subdir/missing.php (100%) diff --git a/src/Phpbb/TranslationValidator/Command/DownloadCommand.php b/src/Phpbb/TranslationValidator/Command/DownloadCommand.php index 9f7310a..00bf9f0 100644 --- a/src/Phpbb/TranslationValidator/Command/DownloadCommand.php +++ b/src/Phpbb/TranslationValidator/Command/DownloadCommand.php @@ -31,9 +31,8 @@ protected function configure() ->setName('download') ->setDescription('If you are missing important files, this tool can automatically download them for you.') ->addOption('files', null, InputOption::VALUE_REQUIRED, 'Which files do you want to download?', 'phpbb-extensions/viglink') - ->addOption('phpbb-version', null, InputOption::VALUE_OPTIONAL, 'The phpBB version you use to validate against', '3.3'); + ->addOption('phpbb-version', null, InputOption::VALUE_OPTIONAL, 'The phpBB version you use to validate against', '4.0'); } - protected function execute(InputInterface $input, OutputInterface $output) { $files = $input->getOption('files'); diff --git a/src/Phpbb/TranslationValidator/Validator/FileListValidator.php b/src/Phpbb/TranslationValidator/Validator/FileListValidator.php index d02f0d9..14036c1 100644 --- a/src/Phpbb/TranslationValidator/Validator/FileListValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/FileListValidator.php @@ -194,10 +194,6 @@ public function validate() { $level = Output::NOTICE; } - else if ($this->phpbbVersion === '3.2' && strpos($origin_file, 'styles/subsilver2/') === 0) - { - $level = Output::FATAL; - } else if (in_array(substr($origin_file, -4), array('.gif', '.png')) && $this->direction === 'rtl') { $level = Output::WARNING; diff --git a/src/Phpbb/TranslationValidator/Validator/LangKeyValidator.php b/src/Phpbb/TranslationValidator/Validator/LangKeyValidator.php index eff3492..9c8a9f3 100644 --- a/src/Phpbb/TranslationValidator/Validator/LangKeyValidator.php +++ b/src/Phpbb/TranslationValidator/Validator/LangKeyValidator.php @@ -619,10 +619,7 @@ public function validateHtml($file, $key, $sourceString, $originString) 'SUPPORT_BODY', 'UPDATE_INSTALLATION_EXPLAIN', 'OVERVIEW_BODY', - )) || ($this->phpbbVersion == '3.2' && ($this->originLanguagePath . 'ucp.php' === $file && in_array($key, array( //Check for 3.2 - 'TERMS_OF_USE_CONTENT', - 'PRIVACY_POLICY', - ))))) + ))) { $sourceString = '

' . $sourceString . '

'; $originString = '

' . $originString . '

'; @@ -729,11 +726,6 @@ public function validateHtml($file, $key, $sourceString, $originString) } } - if ($this->originLanguagePath . 'ucp.php' === $file && in_array($key, array('TERMS_OF_USE_CONTENT', 'PRIVACY_POLICY')) && ($this->phpbbVersion != '3.2')) - { - $level = Output::ERROR; - } - $this->output->addMessage($level, 'String is using additional html: ' . $possibleHtml, $file, $key); } } diff --git a/tests/FileListValidator/FileListTest.php b/tests/FileListValidator/FileListTest.php index 2000958..d1eda44 100644 --- a/tests/FileListValidator/FileListTest.php +++ b/tests/FileListValidator/FileListTest.php @@ -26,7 +26,7 @@ public function validateFileListData() { return array( array( - '3.2', + '4.0', array( Output::FATAL . '-Missing required file-missing.php-', Output::FATAL . '-Missing required file-missing.txt-', diff --git a/tests/FileListValidator/fixtures/3.2/origin/additional.php b/tests/FileListValidator/fixtures/4.0/origin/additional.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/additional.php rename to tests/FileListValidator/fixtures/4.0/origin/additional.php diff --git a/tests/FileListValidator/fixtures/3.2/origin/additional.txt b/tests/FileListValidator/fixtures/4.0/origin/additional.txt similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/additional.txt rename to tests/FileListValidator/fixtures/4.0/origin/additional.txt diff --git a/tests/FileListValidator/fixtures/3.2/origin/file.php b/tests/FileListValidator/fixtures/4.0/origin/file.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/file.php rename to tests/FileListValidator/fixtures/4.0/origin/file.php diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/AUTHORS b/tests/FileListValidator/fixtures/4.0/origin/language/origin/AUTHORS similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/AUTHORS rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/AUTHORS diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/AUTHORS.md b/tests/FileListValidator/fixtures/4.0/origin/language/origin/AUTHORS.md similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/AUTHORS.md rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/AUTHORS.md diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/CHANGELOG b/tests/FileListValidator/fixtures/4.0/origin/language/origin/CHANGELOG similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/CHANGELOG rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/CHANGELOG diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/CHANGELOG.md b/tests/FileListValidator/fixtures/4.0/origin/language/origin/CHANGELOG.md similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/CHANGELOG.md rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/CHANGELOG.md diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/README b/tests/FileListValidator/fixtures/4.0/origin/language/origin/README similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/README rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/README diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/README.md b/tests/FileListValidator/fixtures/4.0/origin/language/origin/README.md similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/README.md rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/README.md diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/VERSION b/tests/FileListValidator/fixtures/4.0/origin/language/origin/VERSION similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/VERSION rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/VERSION diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/VERSION.md b/tests/FileListValidator/fixtures/4.0/origin/language/origin/VERSION.md similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/VERSION.md rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/VERSION.md diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/common.php b/tests/FileListValidator/fixtures/4.0/origin/language/origin/common.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/common.php rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/common.php diff --git a/tests/FileListValidator/fixtures/3.2/origin/language/origin/index.htm b/tests/FileListValidator/fixtures/4.0/origin/language/origin/index.htm similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/language/origin/index.htm rename to tests/FileListValidator/fixtures/4.0/origin/language/origin/index.htm diff --git a/tests/FileListValidator/fixtures/3.2/origin/subdir/additional.php b/tests/FileListValidator/fixtures/4.0/origin/subdir/additional.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/subdir/additional.php rename to tests/FileListValidator/fixtures/4.0/origin/subdir/additional.php diff --git a/tests/FileListValidator/fixtures/3.2/origin/subdir/file.php b/tests/FileListValidator/fixtures/4.0/origin/subdir/file.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/origin/subdir/file.php rename to tests/FileListValidator/fixtures/4.0/origin/subdir/file.php diff --git a/tests/FileListValidator/fixtures/3.2/source/file.php b/tests/FileListValidator/fixtures/4.0/source/file.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/source/file.php rename to tests/FileListValidator/fixtures/4.0/source/file.php diff --git a/tests/FileListValidator/fixtures/3.2/source/language/source/common.php b/tests/FileListValidator/fixtures/4.0/source/language/source/common.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/source/language/source/common.php rename to tests/FileListValidator/fixtures/4.0/source/language/source/common.php diff --git a/tests/FileListValidator/fixtures/3.2/source/missing.php b/tests/FileListValidator/fixtures/4.0/source/missing.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/source/missing.php rename to tests/FileListValidator/fixtures/4.0/source/missing.php diff --git a/tests/FileListValidator/fixtures/3.2/source/missing.txt b/tests/FileListValidator/fixtures/4.0/source/missing.txt similarity index 100% rename from tests/FileListValidator/fixtures/3.2/source/missing.txt rename to tests/FileListValidator/fixtures/4.0/source/missing.txt diff --git a/tests/FileListValidator/fixtures/3.2/source/subdir/file.php b/tests/FileListValidator/fixtures/4.0/source/subdir/file.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/source/subdir/file.php rename to tests/FileListValidator/fixtures/4.0/source/subdir/file.php diff --git a/tests/FileListValidator/fixtures/3.2/source/subdir/missing.php b/tests/FileListValidator/fixtures/4.0/source/subdir/missing.php similarity index 100% rename from tests/FileListValidator/fixtures/3.2/source/subdir/missing.php rename to tests/FileListValidator/fixtures/4.0/source/subdir/missing.php diff --git a/tests/FileValidator/ValidateNoPhpClosingTagTest.php b/tests/FileValidator/ValidateNoPhpClosingTagTest.php index 60f73d7..3a79c1b 100644 --- a/tests/FileValidator/ValidateNoPhpClosingTagTest.php +++ b/tests/FileValidator/ValidateNoPhpClosingTagTest.php @@ -15,7 +15,7 @@ class ValidateNoPhpClosingTagTest extends TestBase public function validateNoPhpClosingTagData() { return array( - array('3.2', 'nophpclosingtag/shortarraysyntax.php', array()), + array('4.0', 'nophpclosingtag/shortarraysyntax.php', array()), ); } diff --git a/tests/LangKeyValidator/TestBase.php b/tests/LangKeyValidator/TestBase.php index 7aa799c..f7bc0f1 100644 --- a/tests/LangKeyValidator/TestBase.php +++ b/tests/LangKeyValidator/TestBase.php @@ -20,7 +20,7 @@ public function setUp(): void $this->validator = new \Phpbb\TranslationValidator\Validator\LangKeyValidator($this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock(), $this->output); $this->validator->setOrigin('origin', dirname(__FILE__) . '/fixtures/origin', 'language/origin/') ->setSource('source', dirname(__FILE__) . '/fixtures/source', 'language/source/') - ->setPhpbbVersion('3.2') + ->setPhpbbVersion('4.0') ->setPluralRule(1); } } From 45f3e8e80d19016348f4c5a2fa72fec41dce044f Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Sat, 27 Sep 2025 10:50:24 +0200 Subject: [PATCH 25/26] Add a composer.json to fixtures for direction --- .../4.0/origin/language/origin/common.php | 37 ------------------- .../4.0/origin/language/origin/composer.json | 5 +++ 2 files changed, 5 insertions(+), 37 deletions(-) delete mode 100644 tests/FileListValidator/fixtures/4.0/origin/language/origin/common.php create mode 100644 tests/FileListValidator/fixtures/4.0/origin/language/origin/composer.json diff --git a/tests/FileListValidator/fixtures/4.0/origin/language/origin/common.php b/tests/FileListValidator/fixtures/4.0/origin/language/origin/common.php deleted file mode 100644 index 9175202..0000000 --- a/tests/FileListValidator/fixtures/4.0/origin/language/origin/common.php +++ /dev/null @@ -1,37 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -if (empty($lang) || !is_array($lang)) -{ - $lang = array(); -} - -// DEVELOPERS PLEASE NOTE -// -// All language files should use UTF-8 as their encoding and the files must not contain a BOM. -// -// Placeholders can now contain order information, e.g. instead of -// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows -// translators to re-order the output of data while ensuring it remains correct -// -// You do not need this where single placeholders are used, e.g. 'Message %d' is fine -// equally where a string contains only two placeholders which are used to wrap text -// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine -// -// Some characters you may want to copy&paste: -// ’ Β» β€œ ” … -// - -$lang = array_merge($lang, array( - 'DIRECTION' => 'ltr', -)); diff --git a/tests/FileListValidator/fixtures/4.0/origin/language/origin/composer.json b/tests/FileListValidator/fixtures/4.0/origin/language/origin/composer.json new file mode 100644 index 0000000..404e01b --- /dev/null +++ b/tests/FileListValidator/fixtures/4.0/origin/language/origin/composer.json @@ -0,0 +1,5 @@ +{ + "extra": { + "direction": "ltr" + } +} From fe6e927c1478dff9309755e9be4e9c2addd3a2f2 Mon Sep 17 00:00:00 2001 From: Christian Schnegelberger Date: Sat, 27 Sep 2025 10:56:24 +0200 Subject: [PATCH 26/26] Add composer.json to source and remove common.php --- .../4.0/source/language/source/common.php | 37 ------------------- .../4.0/source/language/source/composer.json | 5 +++ 2 files changed, 5 insertions(+), 37 deletions(-) delete mode 100644 tests/FileListValidator/fixtures/4.0/source/language/source/common.php create mode 100644 tests/FileListValidator/fixtures/4.0/source/language/source/composer.json diff --git a/tests/FileListValidator/fixtures/4.0/source/language/source/common.php b/tests/FileListValidator/fixtures/4.0/source/language/source/common.php deleted file mode 100644 index 9175202..0000000 --- a/tests/FileListValidator/fixtures/4.0/source/language/source/common.php +++ /dev/null @@ -1,37 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -if (empty($lang) || !is_array($lang)) -{ - $lang = array(); -} - -// DEVELOPERS PLEASE NOTE -// -// All language files should use UTF-8 as their encoding and the files must not contain a BOM. -// -// Placeholders can now contain order information, e.g. instead of -// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows -// translators to re-order the output of data while ensuring it remains correct -// -// You do not need this where single placeholders are used, e.g. 'Message %d' is fine -// equally where a string contains only two placeholders which are used to wrap text -// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine -// -// Some characters you may want to copy&paste: -// ’ Β» β€œ ” … -// - -$lang = array_merge($lang, array( - 'DIRECTION' => 'ltr', -)); diff --git a/tests/FileListValidator/fixtures/4.0/source/language/source/composer.json b/tests/FileListValidator/fixtures/4.0/source/language/source/composer.json new file mode 100644 index 0000000..404e01b --- /dev/null +++ b/tests/FileListValidator/fixtures/4.0/source/language/source/composer.json @@ -0,0 +1,5 @@ +{ + "extra": { + "direction": "ltr" + } +}