Created
November 9, 2021 17:31
-
-
Save mathroc/e64c831d8bc0101be9388f4140d2d5f6 to your computer and use it in GitHub Desktop.
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 | |
// Translator | |
interface Translator | |
{ | |
/** | |
* @param array<mixed> $context | |
*/ | |
public function translate(string $message, array $context = [], ?LocalesPreferences $localesPreferences = null): string; | |
} | |
interface LocalesPreferences | |
{ | |
/** | |
* @param array<Locale> $availableLocales | |
*/ | |
public function bestLocale(array $availableLocales): ?Locale; | |
} | |
// Translation catalog | |
interface LocalizableMessage | |
{ | |
public function localize(LocalesPreferences $localesPreferences): ?LocalizedMessage; | |
} | |
interface LocalizedMessage | |
{ | |
/** | |
* @param array<mixed> $context | |
*/ | |
public function render(array $context): string; | |
} | |
interface TranslationCatalog | |
{ | |
public function fetch(string $message): ?LocalizableMessage; | |
} | |
// exemple | |
class MyTranslator implements Translator | |
{ | |
/** | |
* @param callable(string $message): LocalizedMessage | |
*/ | |
public function __construct( | |
private TranslationCatalog $catalog, | |
private Closure $fallback, | |
private LocalesPreferences $defaultLocalesPreferences | |
) {} | |
/** | |
* @param array<mixed> $context | |
*/ | |
public function translate(string $message, array $context = [], ?LocalesPreferences $localesPreferences = null): string | |
{ | |
$localizableMessage = $this->catalog->fetch($message); | |
$localizedMessage = $localizableMessage?->localize($localesPreferences ?? $this->defaultLocalesPreferences) | |
?: ($this->fallback)($message); | |
return $localizedMessage->render($context); | |
} | |
} | |
class MyLocalesPreferences implements LocalesPreferences | |
{ | |
/** | |
* @param array<Locale> $availableLocales | |
*/ | |
public function bestLocale(array $availableLocales): ?Locale | |
{ | |
return $availableLocales[array_rand($availableLocales, 1)] ?? null; | |
} | |
} | |
class MyLocalizableMessage implements LocalizableMessage | |
{ | |
/** @var array<Locales> */ | |
private array $locales = []; | |
/** SplObjectStorage<Locale,string> */ | |
private SplObjectStorage $messages; | |
/** | |
* @param array<array{locale:Locale,message:string}> | |
*/ | |
public function __construct(array $messages) { | |
$this->messages = new SplObjectStorage(); | |
foreach ($messages as ["locale" => $locale, "message" => $message]) { | |
$this->locales[] = $locale; | |
$this->messages->attach($locale, $message); | |
} | |
} | |
public function localize(LocalesPreferences $localesPreferences): ?LocalizedMessage { | |
return $this->messages[$localesPreferences->bestLocale($this->locales)] ?? null; | |
} | |
} | |
class MySprintfLocalizedMessage implements LocalizedMessage | |
{ | |
public function __construct(private string $localizedContent) {} | |
/** | |
* @param array<mixed> $context | |
*/ | |
public function render(array $context): string { | |
return sprintf($this->localizedContent, ...$context); | |
} | |
} | |
class MyTranslationCatalog implements TranslationCatalog | |
{ | |
/** | |
* @param array<string,LocalizableMessage> $messages | |
*/ | |
public function __construct(private array $messages) {} | |
public function fetch(string $message): ?LocalizableMessage { | |
return $this->messages[$message] ?? null; | |
} | |
} | |
$catalog = new MyTranslationCatalog([ | |
"Hello World!" => new MyLocalizableMessage([[ | |
"locale" => new Locale("fr"), | |
"message" => new MySprintfLocalizedMessage("Bonjour, monde !"), | |
]]), | |
"Hello %s!" => new MyLocalizableMessage([[ | |
"locale" => new Locale("fr"), | |
"message" => new MySprintfLocalizedMessage("Bonjour, %s !"), | |
]]), | |
]); | |
global $translator; | |
$translator = new MyTranslator( | |
$catalog, | |
static fn (string $message) => new MySprintfLocalizedMessage($message), | |
new MyLocalesPreferences(), | |
); | |
/** | |
* @param array<mixed> $context | |
*/ | |
function __(string $key, array $context = []): string | |
{ | |
global $translator; | |
return $translator->translate($key, $context); | |
} | |
echo __("Hello %s!", ["John"]), PHP_EOL; | |
echo __("Good bye %s!", ["John"]), PHP_EOL; | |
// output: | |
// Bonjour, John ! | |
// Good bye John! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment