diff --git a/.github/scripts/continuous-integration b/.github/scripts/continuous-integration new file mode 100644 index 00000000..5b6a2229 --- /dev/null +++ b/.github/scripts/continuous-integration @@ -0,0 +1,78 @@ +#!/usr/bin/env php +`_. @@ -15,9 +15,9 @@ directly ... see the `User Guide `_. Each translation set would go inside a folder named following the two-letter language code from here. -Localization variants are provided for, as folders named with the two-letter ISO 639-1 language code in lowercase, -followed by the two-letter `ISO 3166 country code `_ capitalized, -and with the two parts separated by a hyphen. +Localization variants are provided for, as folders named with the two-letter ISO 639-1 language code in lowercase, +followed by the two-letter `ISO 3166 country code `_ capitalized, +and with the two parts separated by a hyphen. An example would be "en" for English, and "en-US" for the variations appropriate to the United States. ********************** @@ -47,7 +47,7 @@ ko Korean 4.0.0* Timothy-Y-H-Lee Timothy-Y-H-Lee lt Lithuanian 4.0.0* dgvirtual Donatas Glodenis lv Latvian 4.0.0* davislasis Dāvis Lasis ml Malayalam 4.0.0 rakheshthayyur Rakhesh Thayyur -nl Dutch 4.0.0 JohanSmolders JohanSmolders +nl Dutch 4.0.0 JohanSmolders JohanSmolders no Norwegian 4.0.0 LA3QMA Kai Günter Brandt pl Polish 4.0.0 DEVELPL Maciej Jasiewicz pt Portugese 4.0.0 rbm0407 Rodrigo Borges @@ -72,5 +72,3 @@ License ******* These translations are licensed under the `MIT license `_. - -`Jim Parry `_ diff --git a/composer.json b/composer.json index 05a1ddb4..3ff80961 100644 --- a/composer.json +++ b/composer.json @@ -5,21 +5,38 @@ "homepage": "https://codeigniter.com", "license": "MIT", "require": { - "php": ">=7.2", + "php": "^7.2", "ext-intl": "*" }, + "require-dev": { + "codeigniter4/codeigniter4": "dev-develop", + "phpunit/phpunit": "^9.4" + }, + "config": { + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true + }, "autoload": { "psr-4": { - "Translations\\": "" + "CodeIgniter\\Language\\": "Language/" } }, + "autoload-dev": { + "psr-4": { + "CodeIgniter\\Language\\": "tests/Language/" + } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/codeigniter4/CodeIgniter4", + "canonical": true + } + ], "support": { "forum": "http://forum.codeigniter.com/", "source": "https://github.com/codeigniter4/translations", "slack": "https://codeigniterchat.slack.com" - }, - "require-dev": { - "codeigniter4/framework": "dev-master", - "phpunit/phpunit": "^7.0" } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 0b5897ad..a0f07364 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,21 +1,31 @@ - + - - ./tests/system + + tests/Language + + + Language + + + - + diff --git a/tests/Language/AbstractTranslationTestCase.php b/tests/Language/AbstractTranslationTestCase.php new file mode 100644 index 00000000..4ec4f23e --- /dev/null +++ b/tests/Language/AbstractTranslationTestCase.php @@ -0,0 +1,361 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +use PHPUnit\Framework\TestCase; + +/** + * This abstract test class does the heavy testing of the sufficiency + * and precision of provided per-locale translations. + * + * New tests for new locales should extend this class and marked as "final". + * + * @internal + */ +abstract class AbstractTranslationTestCase extends TestCase +{ + /** + * Relative path to the main language folder in main repository. + * + * @var string + */ + private const MAIN_LANGUAGE_REPO = '/vendor/codeigniter4/codeigniter4/system/Language/en/'; + + /** + * Collection of all locale codes mapped from the + * individual locale translation test case. + * + * **NOTE: Do not include `AllLocalesTranslationTest` in + * this collection.** + * + * @var array + */ + public static $locales = [ + ArabicTranslationTest::class => 'ar', + CzechTranslationTest::class => 'cs', + GermanTranslationTest::class => 'de', + SpanishTranslationTest::class => 'es', + FarsiTranslationTest::class => 'fa', + FrenchTranslationTest::class => 'fr', + IndonesianTranslationTest::class => 'id', + ItalianTranslationTest::class => 'it', + JapaneseTranslationTest::class => 'ja', + KoreanTranslationTest::class => 'ko', + LithuanianTranslationTest::class => 'lt', + LatvianTranslationTest::class => 'lv', + MalayalamTranslationTest::class => 'ml', + DutchTranslationTest::class => 'nl', + NorwegianTranslationTest::class => 'no', + PolishTranslationTest::class => 'pl', + PortugueseTranslationTest::class => 'pt', + BrazilianTranslationTest::class => 'pt-BR', + RussianTranslationTest::class => 'ru', + SlovakTranslationTest::class => 'sk', + TurkishTranslationTest::class => 'tr', + UkrainianTranslationTest::class => 'uk', + VietnameseTranslationTest::class => 'vi', + SimpleChineseTranslationTest::class => 'zh-CN', + TraditionalChineseTranslationTest::class => 'zh-TW', + ]; + + //------------------------------------------------------------------------- + // TESTS + //------------------------------------------------------------------------- + + /** + * This tests that all language files configured in the main CI4 repository + * have a corresponding language file in the current locale. + * + * @dataProvider localesProvider + * + * @param string $locale + * + * @return void + */ + final public function testAllConfiguredLanguageFilesAreTranslated(string $locale): void + { + // These localisation variants are usually independent on their own and have no single + // parent locale to compare with so they are treated as if a parent locale + static $excludedLocales = [ + 'pt-BR', + 'sv-SE', + 'sv-FI', + 'zh-CN', + 'zh-TW', + ]; + + $filesNotTranslated = []; + + if (strlen($locale) === 2 || (strlen($locale) > 2 && in_array($locale, $excludedLocales, true))) + { + $filesNotTranslated = array_diff( + $this->expectedSets(), + $this->foundSets($locale) + ); + } + + sort($filesNotTranslated); + $count = count($filesNotTranslated); + + $this->assertEmpty($filesNotTranslated, sprintf( + 'Failed asserting that language %s "%s" in the main repository %s translated in "%s" locale.', + $count > 1 ? 'files' : 'file', + implode('", "', $filesNotTranslated), + $count > 1 ? 'are' : 'is', + $locale + )); + } + + /** + * This tests that all translated language files in the current locale have a + * corresponding language file in the main CI4 repository. + * + * @dataProvider localesProvider + * + * @param string $locale + * + * @return void + */ + final public function testAllTranslatedLanguageFilesAreConfigured(string $locale): void + { + $filesNotConfigured = array_diff( + $this->foundSets($locale), + $this->expectedSets() + ); + + sort($filesNotConfigured); + $count = count($filesNotConfigured); + + $this->assertEmpty($filesNotConfigured, sprintf( + 'Failed asserting that translated language %s "%s" in "%s" locale %s configured in the main repository.', + $count > 1 ? 'files' : 'file', + implode('", "', $filesNotConfigured), + $locale, + $count > 1 ? 'are' : 'is' + )); + } + + /** + * This tests that all language keys defined by a language file in the main CI4 + * repository have corresponding keys in the current locale. + * + * @dataProvider localesProvider + * + * @param string $locale + * + * @return void + */ + final public function testAllConfiguredLanguageKeysAreIncluded(string $locale): void + { + $availableSets = array_intersect($this->expectedSets(), $this->foundSets($locale)); + $keysNotIncluded = []; + + foreach ($availableSets as $file) + { + $missing = array_diff_key( + $this->loadFile($file), + $this->loadFile($file, $locale) + ); + + foreach (array_keys($missing) as $key) + { + $keysNotIncluded[] = substr($file, 0, -4) . '.' . $key; + } + } + + sort($keysNotIncluded); + $count = count($keysNotIncluded); + + $this->assertEmpty($keysNotIncluded, sprintf( + 'Failed asserting that the language %s "%s" in the main repository %s included for translation in "%s" locale.', + $count > 1 ? 'keys' : 'key', + implode('", "', $keysNotIncluded), + $count > 1 ? 'are' : 'is', + $locale + )); + } + + /** + * This tests that all included language keys in a language file for the current + * locale have corresponding keys in the main CI4 repository. + * + * @dataProvider localesProvider + * + * @param string $locale + * + * @return void + */ + final public function testAllIncludedLanguageKeysAreConfigured(string $locale): void + { + $availableSets = array_intersect($this->expectedSets(), $this->foundSets($locale)); + $keysNotConfigured = []; + + foreach ($availableSets as $file) + { + $extra = array_diff_key( + $this->loadFile($file, $locale), + $this->loadFile($file) + ); + + foreach (array_keys($extra) as $key) + { + $keysNotConfigured[] = substr($file, 0, -4) . '.' . $key; + } + } + + sort($keysNotConfigured); + $count = count($keysNotConfigured); + + $this->assertEmpty($keysNotConfigured, sprintf( + 'Failed asserting that the translated language %s "%s" in "%s" locale %s configured in the main repository.', + $count > 1 ? 'keys' : 'key', + implode('", "', $keysNotConfigured), + $locale, + $count > 1 ? 'are' : 'is' + )); + } + + final public function localesProvider(): iterable + { + helper('filesystem'); + $locale = self::$locales[static::class] ?? $this->translationKeys(); + + if (! is_array($locale)) + { + $locale = [$locale => [$locale]]; + } + + return $locale; + } + + final public function testAllLocalesHaveCorrespondingTestCaseInArray(): void + { + $untestedLocales = array_diff( + array_keys($this->translationKeys()), + array_values(self::$locales) + ); + + sort($untestedLocales); + $count = count($untestedLocales); + + $this->assertEmpty($untestedLocales, sprintf( + 'Failed asserting that %s "%s" %s corresponding test %s in %s::$locales array.', + $count > 1 ? 'locales' : 'locale', + implode('", "', $untestedLocales), + $count > 1 ? 'have' : 'has a', + $count > 1 ? 'cases' : 'case', + self::class + )); + } + + /** + * @dataProvider localeTestCaseProvider + * + * @param string $class + * + * @return void + */ + final public function testAllLocalesHaveCorrespondingTestCaseFiles(string $class): void + { + $this->assertTrue(class_exists($class, false), sprintf( + 'Failed asserting that test class "%s" is existing.', + $class + )); + } + + final public function localeTestCaseProvider(): iterable + { + $set = []; + + foreach (self::$locales as $class => $locale) + { + $set[$locale] = [$class]; + } + + return $set; + } + + //------------------------------------------------------------------------- + // UTILITIES + //------------------------------------------------------------------------- + + /** + * Get all the ISO 639-1 and 639-2 locale codes. + * + * @return array> + */ + final public function translationKeys(): array + { + $sets = []; + $dirs = directory_map(getcwd() . '/Language', 1); + + foreach ($dirs as $dir) + { + $dir = trim($dir, '\\/'); + $sets[$dir] = [$dir]; + } + + return $sets; + } + + final public function expectedSets(): array + { + static $expected; + + if (null === $expected) + { + $expected = $this->translationSets(); + } + + return $expected; + } + + final public function foundSets(string $locale): array + { + return $this->translationSets($locale); + } + + final public function loadFile(string $file, ?string $locale = null): array + { + $folder = $locale + ? getcwd() . "/Language/{$locale}/" + : getcwd() . self::MAIN_LANGUAGE_REPO; + + $file = $folder . $file; + + return require $file; + } + + /** + * Gets the set of language files for each location. + * + * @param string|null $locale + * + * @return array + */ + private function translationSets(?string $locale = null): array + { + $location = $locale + ? getcwd() . "/Language/{$locale}/" + : getcwd() . self::MAIN_LANGUAGE_REPO; + + $sets = []; + $files = directory_map($location, 1); + + foreach ($files as $file) + { + $sets[$file] = $file; + } + + return $sets; + } +} diff --git a/tests/Language/AllLocalesTranslationTest.php b/tests/Language/AllLocalesTranslationTest.php new file mode 100644 index 00000000..3c21f298 --- /dev/null +++ b/tests/Language/AllLocalesTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class AllLocalesTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/ArabicTranslationTest.php b/tests/Language/ArabicTranslationTest.php new file mode 100644 index 00000000..65b33a07 --- /dev/null +++ b/tests/Language/ArabicTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class ArabicTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/BrazilianTranslationTest.php b/tests/Language/BrazilianTranslationTest.php new file mode 100644 index 00000000..70bd4cbc --- /dev/null +++ b/tests/Language/BrazilianTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class BrazilianTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/CzechTranslationTest.php b/tests/Language/CzechTranslationTest.php new file mode 100644 index 00000000..a8531623 --- /dev/null +++ b/tests/Language/CzechTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class CzechTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/DutchTranslationTest.php b/tests/Language/DutchTranslationTest.php new file mode 100644 index 00000000..fe1f9486 --- /dev/null +++ b/tests/Language/DutchTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class DutchTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/FarsiTranslationTest.php b/tests/Language/FarsiTranslationTest.php new file mode 100644 index 00000000..eda7d02d --- /dev/null +++ b/tests/Language/FarsiTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class FarsiTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/FrenchTranslationTest.php b/tests/Language/FrenchTranslationTest.php new file mode 100644 index 00000000..7df3df25 --- /dev/null +++ b/tests/Language/FrenchTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class FrenchTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/GermanTranslationTest.php b/tests/Language/GermanTranslationTest.php new file mode 100644 index 00000000..72601fa5 --- /dev/null +++ b/tests/Language/GermanTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class GermanTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/IndonesianTranslationTest.php b/tests/Language/IndonesianTranslationTest.php new file mode 100644 index 00000000..d401d01e --- /dev/null +++ b/tests/Language/IndonesianTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class IndonesianTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/ItalianTranslationTest.php b/tests/Language/ItalianTranslationTest.php new file mode 100644 index 00000000..7f511ea9 --- /dev/null +++ b/tests/Language/ItalianTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class ItalianTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/JapaneseTranslationTest.php b/tests/Language/JapaneseTranslationTest.php new file mode 100644 index 00000000..952d8e08 --- /dev/null +++ b/tests/Language/JapaneseTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class JapaneseTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/KoreanTranslationTest.php b/tests/Language/KoreanTranslationTest.php new file mode 100644 index 00000000..79195c00 --- /dev/null +++ b/tests/Language/KoreanTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class KoreanTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/LatvianTranslationTest.php b/tests/Language/LatvianTranslationTest.php new file mode 100644 index 00000000..53e0d13f --- /dev/null +++ b/tests/Language/LatvianTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class LatvianTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/LithuanianTranslationTest.php b/tests/Language/LithuanianTranslationTest.php new file mode 100644 index 00000000..1c7868ee --- /dev/null +++ b/tests/Language/LithuanianTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class LithuanianTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/MalayalamTranslationTest.php b/tests/Language/MalayalamTranslationTest.php new file mode 100644 index 00000000..f8e340cd --- /dev/null +++ b/tests/Language/MalayalamTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class MalayalamTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/NorwegianTranslationTest.php b/tests/Language/NorwegianTranslationTest.php new file mode 100644 index 00000000..28e3417f --- /dev/null +++ b/tests/Language/NorwegianTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class NorwegianTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/PolishTranslationTest.php b/tests/Language/PolishTranslationTest.php new file mode 100644 index 00000000..8d7ca233 --- /dev/null +++ b/tests/Language/PolishTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class PolishTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/PortugueseTranslationTest.php b/tests/Language/PortugueseTranslationTest.php new file mode 100644 index 00000000..e7afecbc --- /dev/null +++ b/tests/Language/PortugueseTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class PortugueseTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/RussianTranslationTest.php b/tests/Language/RussianTranslationTest.php new file mode 100644 index 00000000..a67077f0 --- /dev/null +++ b/tests/Language/RussianTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class RussianTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/SimpleChineseTranslationTest.php b/tests/Language/SimpleChineseTranslationTest.php new file mode 100644 index 00000000..615c9f6b --- /dev/null +++ b/tests/Language/SimpleChineseTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class SimpleChineseTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/SlovakTranslationTest.php b/tests/Language/SlovakTranslationTest.php new file mode 100644 index 00000000..d4793ad4 --- /dev/null +++ b/tests/Language/SlovakTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class SlovakTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/SpanishTranslationTest.php b/tests/Language/SpanishTranslationTest.php new file mode 100644 index 00000000..4f64e8d1 --- /dev/null +++ b/tests/Language/SpanishTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class SpanishTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/TraditionalChineseTranslationTest.php b/tests/Language/TraditionalChineseTranslationTest.php new file mode 100644 index 00000000..48e7364a --- /dev/null +++ b/tests/Language/TraditionalChineseTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class TraditionalChineseTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/TurkishTranslationTest.php b/tests/Language/TurkishTranslationTest.php new file mode 100644 index 00000000..afdb751c --- /dev/null +++ b/tests/Language/TurkishTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class TurkishTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/UkrainianTranslationTest.php b/tests/Language/UkrainianTranslationTest.php new file mode 100644 index 00000000..a1ba3f26 --- /dev/null +++ b/tests/Language/UkrainianTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class UkrainianTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/Language/VietnameseTranslationTest.php b/tests/Language/VietnameseTranslationTest.php new file mode 100644 index 00000000..dac09103 --- /dev/null +++ b/tests/Language/VietnameseTranslationTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace CodeIgniter\Language; + +/** + * @internal + */ +final class VietnameseTranslationTest extends AbstractTranslationTestCase +{ +} diff --git a/tests/README.md b/tests/README.md index 9ece18fc..28df75e9 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,72 +1,34 @@ -# Running System Tests +# Running Translations Tests -This is the quick-start to CodeIgniter testing. Its intent is to describe what -it takes to get your system setup and ready to run the system tests. -It is not intended to be a full description of the test features that you can -use to test your application, since that can be found in the documentation. +This is the quick-start to CodeIgniter testing. Its intent is to describe what +it takes to get your system setup and ready to run the system tests. +It is not intended to be a full description of the test features that you can +use to test your application, since that can be found in the documentation. ## Requirements -It is recommended to use the latest version of PHPUnit. At the time of this -writing we are running version 7.5.1. Support for this has been built into the -**composer.json** file that ships with CodeIgniter, and can easily be installed +It is recommended to use the latest version of PHPUnit. At the time of this +writing we are running version `9.x`. Support for this has been built into the +**composer.json** file that ships with CodeIgniter, and can easily be installed via [Composer](https://getcomposer.org/) if you don't already have it installed globally. - > composer install + composer update If running under OS X or Linux, you can create a symbolic link to make running tests a touch nicer. - > ln -s ./vendor/bin/phpunit ./phpunit + ln -s ./vendor/bin/phpunit ./phpunit -You also need to install [XDebug](https://xdebug.org/index.php) in order -for the unit tests to successfully complete. +## Running the Tests -## Setup +The entire test suite can be ran by simply running the command below: -A number of the tests that are ran during the test suite are ran against a running database. -In order to setup the database used here, edit the details for the `tests` database -group in **app/Config/Database.php**. Make sure that you provide a database engine -that is currently running, and have already created a table that you can use only -for these tests, as it will be wiped and refreshed often while running the test suite. + ./phpunit --filter AllLocalesTranslationTest -If you want to run the tests without running the live database tests, -you can exclude @DatabaseLive group. Or make a copy of **phpunit.dist.xml**, -call it **phpunit.xml**, and un-comment the line within the testsuite that excludes -the **tests/system/Database/Live** directory. This will make the tests run quite a bit faster. +To run the specific test suite for a locale, simply provide the class name of the locale-specific test: -## Running the tests + ./phpunit --filter FrenchTranslationTest -The entire test suite can be ran by simply typing one command from the command line within the main directory. - - > ./phpunit - -You can limit tests to those within a single test directory by specifying the -directory name after phpunit. All core tests are stored under **tests/system**. - - > ./phpunit tests/system/HTTP/ - -Individual tests can be ran by including the relative path to the test file. - - > ./phpunit tests/system/HTTP/RequestTest - -You can run the tests without running the live database tests. - - > ./phpunit --exclude-group DatabaseLive - -## Generating Code Coverage - -To generate coverage information, including HTML reports you can view in your browser, -you can use the following command: - - > ./phpunit --colors --coverage-text=tests/coverage.txt --coverage-html=tests/coverage/ -d memory_limit=1024m - -This runs all of the tests again, collecting information about how many lines, -functions, and files are tested, and the percent of the code that is covered by the tests. -It is collected in two formats: a simple text file that provides an overview, -as well as comprehensive collection of HTML files that show the status of every line of code in the project. - -The text file can be found at **tests/coverage.txt**. -The HTML files can be viewed by opening **tests/coverage/index.html** in your favorite browser. +Locale-specific test class names follow the named regex pattern `/^(?P[A-Za-z]+)TranslationTest$/`. ## PHPUnit XML Configuration @@ -74,8 +36,5 @@ The repository has a ``phpunit.xml.dist`` file in the project root, used for PHPUnit configuration. This is used as a default configuration if you do not have your own ``phpunit.xml`` in the project root. -The normal practice would be to copy ``phpunit.xml.dist`` to ``phpunit.xml`` -(which is git ignored), and to tailor yours as you see fit. -For instance, you might wish to exclude database tests -or automatically generate HTML code coverage reports. - +The normal practice would be to copy ``phpunit.xml.dist`` to ``phpunit.xml`` (which is git ignored), +and to tailor yours as you see fit. diff --git a/tests/_support/CIUnitTestCase.php b/tests/_support/CIUnitTestCase.php deleted file mode 100644 index b475b62e..00000000 --- a/tests/_support/CIUnitTestCase.php +++ /dev/null @@ -1,8 +0,0 @@ -language[$locale ?? $this->locale][$file] = $data; - - return $this; - } - - //-------------------------------------------------------------------- - - /** - * Provides an override that allows us to set custom - * data to be returned easily during testing. - * - * @param string $path - * - * @return array|mixed - */ - protected function requireFile(string $path): array - { - return $this->data ?? []; - } - - //-------------------------------------------------------------------- - - /** - * Arbitrarily turnoff internationalization support for testing - */ - public function disableIntlSupport() - { - $this->intlSupport = false; - } - -} diff --git a/tests/_support/Language/SecondMockLanguage.php b/tests/_support/Language/SecondMockLanguage.php deleted file mode 100644 index 71428854..00000000 --- a/tests/_support/Language/SecondMockLanguage.php +++ /dev/null @@ -1,27 +0,0 @@ -load($file, $locale, $return); - } - - //-------------------------------------------------------------------- - - /** - * Expose the loaded language files - */ - public function loaded(string $locale = 'en') - { - return $this->loadedFiles[$locale]; - } - -} diff --git a/tests/_support/Language/ab-CD/Allin.php b/tests/_support/Language/ab-CD/Allin.php deleted file mode 100644 index 3b153883..00000000 --- a/tests/_support/Language/ab-CD/Allin.php +++ /dev/null @@ -1,8 +0,0 @@ - 'Pyramid of Giza', - 'tre' => 'Colossus of Rhodes', - 'fiv' => 'Temple of Artemis', - 'sev' => 'Hanging Gardens of Babylon', -]; diff --git a/tests/_support/Language/ab/Allin.php b/tests/_support/Language/ab/Allin.php deleted file mode 100644 index 69120758..00000000 --- a/tests/_support/Language/ab/Allin.php +++ /dev/null @@ -1,8 +0,0 @@ - 'gluttony', - 'tre' => 'greed', - 'six' => 'envy', - 'sev' => 'pride', -]; diff --git a/tests/_support/Language/en-ZZ/More.php b/tests/_support/Language/en-ZZ/More.php deleted file mode 100644 index 66810205..00000000 --- a/tests/_support/Language/en-ZZ/More.php +++ /dev/null @@ -1,6 +0,0 @@ - 'These are not the droids you are looking for', - 'notaMoon' => "It's made of cheese", - 'wisdom' => 'There is no try', -]; diff --git a/tests/_support/Language/en/Allin.php b/tests/_support/Language/en/Allin.php deleted file mode 100644 index 6a10dcc7..00000000 --- a/tests/_support/Language/en/Allin.php +++ /dev/null @@ -1,8 +0,0 @@ - 'four calling birds', - 'fiv' => 'five golden rings', - 'six' => 'six geese a laying', - 'sev' => 'seven swans a swimming', -]; diff --git a/tests/_support/Language/en/Core.php b/tests/_support/Language/en/Core.php deleted file mode 100644 index b2fc4c18..00000000 --- a/tests/_support/Language/en/Core.php +++ /dev/null @@ -1,20 +0,0 @@ - '{0} extension could not be found.', - 'bazillion' => 'billions and billions', // adds a new setting -]; diff --git a/tests/_support/Language/en/More.php b/tests/_support/Language/en/More.php deleted file mode 100644 index 5b4eaea5..00000000 --- a/tests/_support/Language/en/More.php +++ /dev/null @@ -1,7 +0,0 @@ - 'These are not the droids you are looking for', - 'notaMoon' => "That's no moon... it's a space station", - 'cannotMove' => 'I have a very bad feeling about this', -]; diff --git a/tests/_support/Language/ru/Language.php b/tests/_support/Language/ru/Language.php deleted file mode 100644 index d6c6632b..00000000 --- a/tests/_support/Language/ru/Language.php +++ /dev/null @@ -1,5 +0,0 @@ - 'Whatever this would be, translated', -]; diff --git a/tests/_support/MockCodeIgniter.php b/tests/_support/MockCodeIgniter.php deleted file mode 100644 index 3e31d001..00000000 --- a/tests/_support/MockCodeIgniter.php +++ /dev/null @@ -1,11 +0,0 @@ -expected = $this->expectedSets(); - } - - /** - * Identify all the locales in the translations repo. - * - * @return [][] - */ - public function translations() - { - $dir = getcwd() . '/Language/'; - $dh = opendir($dir); - $sets = []; - while (($file = readdir($dh)) !== false) - { - if (substr($file, 0, 1) != '.') - $sets[$file] = [$file]; - } - closedir($dh); - ksort($sets); - return $sets; - } - - /** - * For a given translation locale found, make sure that all of - * the translation sets (individual files) are there. - * This is relaxed for sublocales (eg fr-CA), which are only - * expected to provide variations for a parent locale. - * - * @dataProvider translations - */ - public function testMissingFiles($locale) - { - $diff = (strlen($locale) > 2) ? [] : array_diff($this->expected, $this->foundSets($locale)); - if (count($diff) > 0) - $this->fail($locale . ' is missing: ' . implode(' ', $diff)); - else - $this->assertTrue(true); - } - - /** - * For a given translation locale found, make sure that there - * are no extra (unneeded) translation sets provided. - * - * @dataProvider translations - */ - public function testExtraFiles($locale) - { - $diff = array_diff($this->foundSets($locale), $this->expected); - if (count($diff) > 0) - $this->fail($locale . ' has extra files: ' . implode(' ', $diff)); - else - $this->assertTrue(true); - } - - /** - * For a given translation locale found, make sure that each translation - * set has the appropriate keys for a complete translation. - * This is relaxed for sublocales (eg fr-CA), which are only - * expected to provide variations for a parent locale. - * - * @dataProvider translations - */ - public function testMissingKeys($locale) - { - $found = array_intersect($this->foundSets($locale),$this->expected); - $diff = []; - foreach ($found as $keyset) - { - $group = substr($keyset, 0, -4); - $expected = $this->loadKeys($keyset); - $actual = $this->loadKeys($keyset, $locale); - $missing = array_diff_key($expected, $actual); - foreach ($missing as $key => $value) - $diff[] = $group . '.' . $key; - } - if (count($diff) > 0) - $this->fail($locale . ' is missing keys: ' . implode(' ', $diff)); - else - $this->assertTrue(true); - } - - /** - * For a given translation locale found, make sure that each translation - * doesn't have extra (un-needed) keys defined.. - * - * @dataProvider translations - */ - public function testExtraKeys($locale) - { - $found = array_intersect($this->foundSets($locale),$this->expected); - $diff = []; - foreach ($found as $keyset) - { - $group = substr($keyset, 0, -4); - $expected = $this->loadKeys($keyset); - $actual = $this->loadKeys($keyset, $locale); - $missing = array_diff_key($actual,$expected); - foreach ($missing as $key => $value) - $diff[] = $group . '.' . $key; - } - if (count($diff) > 0) - $this->fail($locale . ' has extra keys: ' . implode(' ', $diff)); - else - $this->assertTrue(true); - } - - /** - * Identify all the translation sets in system/Language/en - * - * @return [] - */ - public function expectedSets() - { - $dir = getcwd() . '/vendor/codeigniter4/framework/system/Language/en/'; - $dh = opendir($dir); - $sets = []; - while (($file = readdir($dh)) !== false) - { - if (substr($file, 0, 1) != '.') - $sets[] = $file; - } - closedir($dh); - ksort($sets); - return $sets; - } - - /** - * Identify all the translation sets found for a given locale - * - * @return [] - */ - public function foundSets($locale) - { - $dir = getcwd() . '/Language/' . $locale . '/'; - $dh = opendir($dir); - $sets = []; - while (($file = readdir($dh)) !== false) - { - if (substr($file, 0, 1) != '.') - $sets[] = $file; - } - closedir($dh); - ksort($sets); - return $sets; - } - - /** - * Load a set of translations, from the repo or "stock". - * - * @return [] - */ - public function loadKeys($which, $locale = null) - { - $folder = $locale ? getcwd() . '/Language/' . $locale . '/' : - getcwd() . '/vendor/codeigniter4/framework/system/Language/en/'; - $file = $folder . $which; - $keys = require $file; - return $keys; - } - -}