Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"phpunit/phpunit": "^9.3",
"vimeo/psalm": "4.0.1",
"laravel/pint": "1.2.*",
"phpstan/phpstan": "1.9.x-dev"
"phpstan/phpstan": "1.*"
},
"scripts": {
"lint": "./vendor/bin/pint --test",
Expand Down
51 changes: 41 additions & 10 deletions src/Locale/Locale.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ class Locale
*/
public $default;

/**
* Fallback locale. Used when specific or default locale is missing translation.
* Should always be set to locale that includes all translations.
*
* @var string|null
*/
public $fallback = null;

/**
* Set New Locale from an array
*
Expand All @@ -44,7 +52,7 @@ public static function setLanguageFromArray(string $name, array $translations):
*/
public static function setLanguageFromJSON(string $name, string $path): void
{
if (! file_exists($path)) {
if (! file_exists($path) && self::$exceptions) {
throw new Exception('Translation file not found.');
}

Expand All @@ -55,13 +63,31 @@ public static function setLanguageFromJSON(string $name, string $path): void

public function __construct(string $default)
{
if (! \array_key_exists($default, self::$language)) {
if (! \array_key_exists($default, self::$language) && self::$exceptions) {
throw new Exception('Locale not found');
}

$this->default = $default;
}

/**
* Change fallback Locale
*
* @param $name
*
* @throws Exception
*/
public function setFallback(string $name): self
{
if (! \array_key_exists($name, self::$language) && self::$exceptions) {
throw new Exception('Locale not found');
}

$this->fallback = $name;

return $this;
}

/**
* Change Default Locale
*
Expand All @@ -71,7 +97,7 @@ public function __construct(string $default)
*/
public function setDefault(string $name): self
{
if (! \array_key_exists($name, self::$language)) {
if (! \array_key_exists($name, self::$language) && self::$exceptions) {
throw new Exception('Locale not found');
}

Expand All @@ -91,17 +117,22 @@ public function setDefault(string $name): self
*/
public function getText(string $key, array $placeholders = [])
{
$default = '{{'.$key.'}}';
$defaultExists = \array_key_exists($key, self::$language[$this->default]);
$fallbackExists = \array_key_exists($key, self::$language[$this->fallback ?? ''] ?? []);

if (! \array_key_exists($key, self::$language[$this->default])) {
if (self::$exceptions) {
throw new Exception('Key named "'.$key.'" not found');
}
$translation = '{{'.$key.'}}';

return $default;
if ($fallbackExists) {
$translation = self::$language[$this->fallback ?? ''][$key];
}

$translation = self::$language[$this->default][$key];
if ($defaultExists) {
$translation = self::$language[$this->default][$key];
}

if (! $defaultExists && ! $fallbackExists && self::$exceptions) {
throw new Exception('Key named "'.$key.'" not found');
}

foreach ($placeholders as $placeholderKey => $placeholderValue) {
$translation = str_replace('{{'.$placeholderKey.'}}', (string) $placeholderValue, $translation);
Expand Down
23 changes: 23 additions & 0 deletions tests/Locale/LocaleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,27 @@ public function testTexts(): void

$this->fail('No exception was thrown');
}

public function testFallback(): void
{
$locale = new Locale('he-IL');

$this->assertEquals('שלום', $locale->getText('hello'));
$this->assertEquals('{{world}}', $locale->getText('world'));
$this->assertEquals('{{missing}}', $locale->getText('missing'));

$locale->setFallback('en-US');

$this->assertEquals('שלום', $locale->getText('hello'));
$this->assertEquals('World', $locale->getText('world'));
$this->assertEquals('{{missing}}', $locale->getText('missing'));

Locale::$exceptions = true;
try {
$locale->getText('missing');
$this->fail('Failed to throw exception when translation is missing');
} catch (Exception $e) {
$this->assertInstanceOf(Exception::class, $e);
}
}
}