Skip to content

Commit

Permalink
feat(locale): add Locale::default() function to retrieve default lo…
Browse files Browse the repository at this point in the history
…cale (#447)

Signed-off-by: azjezz <azjezz@protonmail.com>
  • Loading branch information
azjezz committed Mar 24, 2024
1 parent 5f0aeac commit 69728d2
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/component/locale.md
Expand Up @@ -12,6 +12,6 @@

#### `Enums`

- [Locale](./../../src/Psl/Locale/Locale.php#L12)
- [Locale](./../../src/Psl/Locale/Locale.php#L13)


46 changes: 46 additions & 0 deletions src/Psl/Locale/Locale.php
Expand Up @@ -5,6 +5,7 @@
namespace Psl\Locale;

use Locale as NativeLocale;
use Psl\Str;

/**
* Represents a locale identifier.
Expand Down Expand Up @@ -686,8 +687,11 @@ enum Locale: string
case AlbanianNorthMacedonia = "sq_MK";
case AlbanianKosovo = "sq_XK";
case Serbian = "sr";
case SerbianSerbia = "sr_RS";
case SerbianCyrillic = "sr_Cyrl";
case SerbianCyrillicSerbia = "sr_Cyrl_RS";
case SerbianLatin = "sr_Latn";
case SerbianLatinSerbia = "sr_Latn_RS";
case Sundanese = "su";
case SundaneseLatin = "su_Latn";
case Swedish = "sv";
Expand Down Expand Up @@ -791,6 +795,48 @@ enum Locale: string
case Zulu = "zu";
case ZuluSouthAfrica = "zu_ZA";

/**
* Retrieves the system's default locale from the PHP environment settings.
*
* This method returns the locale configured via `intl.default_locale`. Should the PHP environment lack a specific
* locale configuration or if the configured locale is unsupported, it defaults to `self::English` representing
* the English language.
*
* The choice of English as the fallback is motivated by its global comprehension, role as a base language in
* technology and international communication, predominance in technical documentation and support resources,
* and its historical precedence in the tech industry. These factors ensure the fallback locale is both broadly
* accessible and consistent with international standards.
*
* @return self The default locale as an enum instance, sourced from PHP settings or `self::English` as the fallback.
*
* @see https://www.php.net/manual/en/locale.getdefault.php
*/
public static function default(): self
{
$full_locale = NativeLocale::getDefault();
if (!$full_locale) {
// Fallback to English if no locale is set or supported.
return self::English;
}

$language = NativeLocale::getPrimaryLanguage($full_locale);
$script = NativeLocale::getScript($full_locale);
$region = NativeLocale::getRegion($full_locale);

$locale = Str\lowercase($language);
if ($script) {
$locale .= '_' . Str\capitalize($script);
}

if ($region) {
$locale .= '_' . Str\uppercase($region);
}

// Attempt to match the system-configured locale with a supported enum instance,
// defaulting to English if a precise match is unavailable.
return self::tryFrom($locale) ?? self::tryFrom($language) ?? self::English;
}

/**
* Get a human-readable name for the locale, suitable for display.
*
Expand Down
118 changes: 118 additions & 0 deletions tests/unit/Locale/LocaleTest.php
Expand Up @@ -9,8 +9,125 @@
use Psl\Locale\Locale;
use Psl\Str;

use function locale_get_default;
use function locale_set_default;

final class LocaleTest extends TestCase
{
private ?string $defaultLocale = null;
protected function setUp(): void
{
$this->defaultLocale = locale_get_default();
}

protected function tearDown(): void
{
if (null !== $this->defaultLocale) {
locale_set_default($this->defaultLocale);
}
}

public function testDefault(): void
{
foreach (Locale::cases() as $locale) {
locale_set_default($locale->value);

static::assertSame($locale, Locale::default());
}
}

public function testDefaultIgnoresCharset(): void
{
locale_set_default('sr_RS.UTF-8');
static::assertSame(Locale::SerbianSerbia, Locale::default());

locale_set_default('sr_Cyrl.UTF-8');
static::assertSame(Locale::SerbianCyrillic, Locale::default());
locale_set_default('sr_Cyrl_RS.UTF-8');
static::assertSame(Locale::SerbianCyrillicSerbia, Locale::default());

locale_set_default('sr_Latn.UTF-8');
static::assertSame(Locale::SerbianLatin, Locale::default());
locale_set_default('sr_Latn_RS.UTF-8');
static::assertSame(Locale::SerbianLatinSerbia, Locale::default());
}

public function testDefaultIgnoresVariant(): void
{
locale_set_default('sr_RS@ekavsk');
static::assertSame(Locale::SerbianSerbia, Locale::default());

locale_set_default('sr_Cyrl@ekavsk');
static::assertSame(Locale::SerbianCyrillic, Locale::default());
locale_set_default('sr_Cyrl_RS@ekavsk');
static::assertSame(Locale::SerbianCyrillicSerbia, Locale::default());

locale_set_default('sr_Latn@ekavsk');
static::assertSame(Locale::SerbianLatin, Locale::default());
locale_set_default('sr_Latn_RS@ekavsk');
static::assertSame(Locale::SerbianLatinSerbia, Locale::default());
}

public function testDefaultIgnoresExtension(): void
{
locale_set_default('sr_RS-u-currency-EUR');
static::assertSame(Locale::SerbianSerbia, Locale::default());

locale_set_default('sr_Cyrl-u-currency-EUR');
static::assertSame(Locale::SerbianCyrillic, Locale::default());
locale_set_default('sr_Cyrl_RS-u-currency-EUR');
static::assertSame(Locale::SerbianCyrillicSerbia, Locale::default());

locale_set_default('sr_Latn-u-currency-EUR');
static::assertSame(Locale::SerbianLatin, Locale::default());
locale_set_default('sr_Latn_RS-u-currency-EUR');
static::assertSame(Locale::SerbianLatinSerbia, Locale::default());
}

public function testDefaultIgnoresCasing(): void
{
locale_set_default('ar_TN');
static::assertSame(Locale::ArabicTunisia, Locale::default());

locale_set_default('AR_TN');
static::assertSame(Locale::ArabicTunisia, Locale::default());

locale_set_default('AR_tn');
static::assertSame(Locale::ArabicTunisia, Locale::default());

locale_set_default('aR_Tn');
static::assertSame(Locale::ArabicTunisia, Locale::default());

locale_set_default('Ar_tN');
static::assertSame(Locale::ArabicTunisia, Locale::default());

locale_set_default('Ar_TN');
static::assertSame(Locale::ArabicTunisia, Locale::default());

locale_set_default('aR_TN');
static::assertSame(Locale::ArabicTunisia, Locale::default());

locale_set_default('AR_Tn');
static::assertSame(Locale::ArabicTunisia, Locale::default());

locale_set_default('AR_tN');
static::assertSame(Locale::ArabicTunisia, Locale::default());
}

public function testFallbackToJustLanguage(): void
{
locale_set_default('zh_CN');

static::assertSame(Locale::Chinese, Locale::default());
}

public function testDefaultFallbacksToEnglish(): void
{
locale_set_default('xx_XX');

static::assertSame(Locale::English, Locale::default());
}

/**
* @return Generator<string, array{Locale}, void, null>
*/
Expand Down Expand Up @@ -119,6 +236,7 @@ public function getLocalesWithoutRegion(): Generator
}
}
}

/**
* @dataProvider getLocalesWithoutRegion
*/
Expand Down

0 comments on commit 69728d2

Please sign in to comment.