Skip to content

Instantly share code, notes, and snippets.

@jeckel
Forked from heiglandreas/index.php
Last active October 29, 2023 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeckel/8a540640fffaef1e57827e85b02d3922 to your computer and use it in GitHub Desktop.
Save jeckel/8a540640fffaef1e57827e85b02d3922 to your computer and use it in GitHub Desktop.
Locale Value Object
<?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;
}
}
<?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