-
-
Save jeckel/8a540640fffaef1e57827e85b02d3922 to your computer and use it in GitHub Desktop.
Locale Value Object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace ValueObject; | |
use ResourceBundle; | |
use Stringable; | |
final readonly class Locale implements Stringable | |
{ | |
private function __construct(public string $locale) {} | |
public static function from(string $locale): self | |
{ | |
static $locales = null; | |
static $instances = []; | |
if ($locales === null) { | |
$locales = ResourceBundle::getLocales(''); | |
} | |
$parts = \Locale::parseLocale($locale); | |
if (! isset($parts['language'], $parts['region'])) { | |
throw new InvalidArgumentException("Invalid locale $locale provided"); | |
} | |
$normalizedLocale = $parts['language'] . '_' . strtoupper($parts['region']); | |
if (!in_array($normalizedLocale, $locales, true)) { | |
throw new InvalidArgumentException("Invalid locale $locale provided"); | |
} | |
if (! isset($instances[$normalizedLocale])) { | |
$instances[$normalizedLocale] = new self($normalizedLocale); | |
} | |
return $instances[$normalizedLocale]; | |
} | |
public function __toString(): string | |
{ | |
return $this->locale; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Test\ValueObject; | |
use ValueObject\InvalidArgumentException; | |
use ValueObject\Locale; | |
use PHPUnit\Framework\Attributes\TestDox; | |
use PHPUnit\Framework\Attributes\TestWith; | |
use PHPUnit\Framework\TestCase; | |
class LocaleTest extends TestCase | |
{ | |
#[TestWith(['fr_FR', 'fr_FR'])] | |
#[TestWith(['fr_CA', 'fr_CA'])] | |
#[TestWith(['en_US', 'en_US'])] | |
#[TestWith(['en_GB', 'en_GB'])] | |
#[TestWith(['de-DE', 'de_DE'])] | |
#[TestWith(['de-CH', 'de_CH'])] | |
#[TestWith(['fr_CA.ISO-8895-1@euro', 'fr_CA'])] | |
#[TestWith(['fr-CA-u-ca-gregorian-nu-arab', 'fr_CA'])] | |
#[TestDox('Create locale $localeToTest with should return Locale instance with $expected value')] | |
public function testValidLocaleShouldReturnLocaleInstance(string $localeToTest, string $expected): void | |
{ | |
$locale = Locale::from($localeToTest); | |
self::assertSame($expected, $locale->locale); | |
} | |
#[TestWith(['fr_DE'])] | |
#[TestWith(['en_UK'])] | |
#[TestWith(['foobar'])] | |
#[TestDox('Create locale $localeToTest with should fail')] | |
public function testWithInvalidLocaleShouldFail(string $localeToTest): void | |
{ | |
$this->expectException(InvalidArgumentException::class); | |
Locale::from($localeToTest); | |
} | |
public function testInstantiateTwiceSameLocaleReturnsSameInstance(): void | |
{ | |
self::assertSame( | |
Locale::from('fr_CA'), | |
Locale::from('fr-CA-u-ca-gregorian-nu-arab') | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment