diff --git a/docs/README.md b/docs/README.md index 49a3eca4..8c486db1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -32,6 +32,7 @@ - [Psl\Interface](./component/interface.md) - [Psl\Iter](./component/iter.md) - [Psl\Json](./component/json.md) +- [Psl\Locale](./component/locale.md) - [Psl\Math](./component/math.md) - [Psl\Network](./component/network.md) - [Psl\OS](./component/os.md) diff --git a/docs/component/locale.md b/docs/component/locale.md new file mode 100644 index 00000000..d3b714ee --- /dev/null +++ b/docs/component/locale.md @@ -0,0 +1,17 @@ + + +[*index](./../README.md) + +--- + +### `Psl\Locale` Component + +#### `Enums` + +- [Locale](./../../src/Psl/Locale/Locale.php#L12) + + diff --git a/docs/documenter.php b/docs/documenter.php index e9802ea7..40ec38c0 100644 --- a/docs/documenter.php +++ b/docs/documenter.php @@ -225,6 +225,7 @@ function get_all_components(): array 'Psl\\Trait', 'Psl\\Type', 'Psl\\Unix', + 'Psl\\Locale', 'Psl\\Vec', ]; diff --git a/src/Psl/Internal/Loader.php b/src/Psl/Internal/Loader.php index d8b78fbf..70b722dd 100644 --- a/src/Psl/Internal/Loader.php +++ b/src/Psl/Internal/Loader.php @@ -829,6 +829,7 @@ final class Loader 'Psl\\OS\\OperatingSystemFamily' => 'Psl/OS/OperatingSystemFamily.php', 'Psl\\Password\\Algorithm' => 'Psl/Password/Algorithm.php', 'Psl\\Shell\\ErrorOutputBehavior' => 'Psl/Shell/ErrorOutputBehavior.php', + 'Psl\\Locale\\Locale' => 'Psl/Locale/Locale.php', ]; public const TYPE_CONSTANTS = 1; diff --git a/src/Psl/Locale/Locale.php b/src/Psl/Locale/Locale.php new file mode 100644 index 00000000..96a23fcd --- /dev/null +++ b/src/Psl/Locale/Locale.php @@ -0,0 +1,896 @@ +value, $locale?->value ?? $this->value); + } + + /** + * Get the language code part of the locale. + * + * @return non-empty-string The language code. + * + * @mutation-free + */ + public function getLanguage(): string + { + /** @var non-empty-string */ + return NativeLocale::getPrimaryLanguage($this->value); + } + + /** + * Get the display name of the language for the locale. + * + * @param Locale|null $locale The locale for which to get the language name. Defaults to the current locale if not specified. + * + * @return non-empty-string The display name of the language. + * + * @mutation-free + */ + public function getDisplayLanguage(?Locale $locale = null): string + { + /** @var non-empty-string */ + return NativeLocale::getDisplayLanguage($this->value, $locale?->value ?? $this->value); + } + + /** + * Checks if the locale has a script specified. + * + * @return bool True if the locale has a script, false otherwise. + * + * @mutation-free + */ + public function hasScript(): bool + { + return $this->getScript() !== null; + } + + /** + * Get the script of the locale. + * + * @return non-empty-string|null The script of the locale, or null if not applicable. + * + * @mutation-free + */ + public function getScript(): ?string + { + return NativeLocale::getScript($this->value) ?: null; + } + + /** + * Checks if the locale has a region specified. + * + * @return bool True if the locale has a region, false otherwise. + * + * @mutation-free + */ + public function hasRegion(): bool + { + return $this->getRegion() !== null; + } + + /** + * Get the display name of the region for the locale. + * + * @param Locale|null $locale The locale for which to get the region name. Defaults to the current locale if not specified. + * + * @return non-empty-string|null The display name of the region, or null if not applicable. + * + * @mutation-free + */ + public function getDisplayRegion(?Locale $locale = null): ?string + { + return NativeLocale::getDisplayRegion($this->value, $locale?->value ?? $this->value) ?: null; + } + + /** + * Get the alpha-2 country code part of the locale, if present. + * + * @return non-empty-string|null The alpha-2 country code, or null if not present. + * + * @mutation-free + */ + public function getRegion(): ?string + { + return NativeLocale::getRegion($this->value) ?: null; + } +} diff --git a/tests/unit/Locale/LocaleTest.php b/tests/unit/Locale/LocaleTest.php new file mode 100644 index 00000000..dc7d593d --- /dev/null +++ b/tests/unit/Locale/LocaleTest.php @@ -0,0 +1,127 @@ + + */ + public function getAllLocales(): Generator + { + foreach (Locale::cases() as $locale) { + yield $locale->value => [$locale]; + } + } + + /** + * @dataProvider getAllLocales + */ + public function testItReturnsTheLanguageAndHumanReadableName(Locale $locale): void + { + $display_language = $locale->getDisplayLanguage(Locale::English); + $language = $locale->getLanguage(); + $display_name = $locale->getDisplayName(Locale::English); + + static::assertNotEmpty($display_language); + static::assertStringContainsString($language, $locale->value); + + static::assertStringContainsString($display_language, $display_name); + if ($locale->hasRegion()) { + $region = $locale->getDisplayRegion(Locale::English); + $region = Str\replace_every($region, [ + '(' => '[', + ')' => ']', + ]); + + static::assertStringContainsString($region, $display_name); + } + } + + /** + * @return Generator + */ + public function getLocalesWithScript(): Generator + { + foreach (Locale::cases() as $locale) { + if ($locale->hasScript()) { + yield $locale->value => [$locale]; + } + } + } + + /** + * @dataProvider getLocalesWithScript + */ + public function testItReturnsTheScript(Locale $locale): void + { + static::assertNotEmpty($locale->getScript()); + } + + /** + * @return Generator + */ + public function getLocalesWithoutScript(): Generator + { + foreach (Locale::cases() as $locale) { + if (!$locale->hasScript()) { + yield $locale->value => [$locale]; + } + } + } + /** + * @dataProvider getLocalesWithoutScript + */ + public function testItDoesNotReturnsTheScript(Locale $locale): void + { + static::assertNull($locale->getScript()); + } + + /** + * @return Generator + */ + public function getLocalesWithRegion(): Generator + { + foreach (Locale::cases() as $locale) { + if ($locale->hasRegion()) { + yield $locale->value => [$locale]; + } + } + } + + /** + * @dataProvider getLocalesWithRegion + */ + public function testItReturnsTheRegion(Locale $locale): void + { + static::assertNotEmpty($locale->getRegion()); + static::assertNotEmpty($locale->getDisplayRegion()); + } + + /** + * @return Generator + */ + public function getLocalesWithoutRegion(): Generator + { + foreach (Locale::cases() as $locale) { + if (!$locale->hasRegion()) { + yield $locale->value => [$locale]; + } + } + } + /** + * @dataProvider getLocalesWithoutRegion + */ + public function testItDoesNotReturnsTheRegion(Locale $locale): void + { + static::assertNull($locale->getRegion()); + static::assertNull($locale->getDisplayRegion()); + } +}