164 lines
4.3 KiB
PHP
164 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace CrocWork\Zappy\I18n;
|
|
|
|
/**
|
|
* Translator class
|
|
*
|
|
* The Translator class provides an implementation for setting the application's
|
|
* locale and providing translations for use in the application ui. This implementation
|
|
* uses a regular expression to check if entered locales conform to a standardized format.
|
|
*/
|
|
class Translator
|
|
{
|
|
/**
|
|
* Regular expression used to check the form of locale strings.
|
|
*/
|
|
private const LOCALE_REGEX = '/^[A-Za-z]{2,3}([_-][A-Za-z]{4})?([_-][A-Za-z]{2})?$/';
|
|
|
|
/**
|
|
* The default application locale.
|
|
* @var string
|
|
*/
|
|
private string $fallbackLocale;
|
|
|
|
/**
|
|
* The currently active locale.
|
|
* @var string
|
|
*/
|
|
private string $locale;
|
|
|
|
/**
|
|
* The path where translation files are stored.
|
|
* @var string
|
|
*/
|
|
private string $translationsPath;
|
|
|
|
/**
|
|
* The currently loaded translations.
|
|
* @var array
|
|
*/
|
|
private array $translations;
|
|
|
|
/**
|
|
* Initialize a Translator instance.
|
|
*
|
|
* To initialize a Translator, it must know where translation files are to be found and what
|
|
* locale to set by default on initialization. These values are checked for correctness, upon
|
|
* failure an exception will be thrown.
|
|
*
|
|
* @param string $fallbackLocale
|
|
* @param string $translationsPath
|
|
*/
|
|
public function __construct(string $fallbackLocale, string $translationsPath)
|
|
{
|
|
$this->fallbackLocale = $fallbackLocale;
|
|
$this->locale = $this->fallbackLocale;
|
|
$this->translationsPath = $translationsPath;
|
|
|
|
if(!file_exists($translationsPath) || !is_dir($translationsPath)) {
|
|
throw new \RuntimeException("Could not initialize translator: invalid translations path.");
|
|
}
|
|
}
|
|
|
|
public function provides(): string
|
|
{
|
|
return 'translator';
|
|
}
|
|
|
|
/**
|
|
* Get the default locale string.
|
|
* @return string
|
|
*/
|
|
public function getFallbackLocale(): string
|
|
{
|
|
return $this->fallbackLocale;
|
|
}
|
|
|
|
/**
|
|
* Get the current locale string.
|
|
* @return string
|
|
*/
|
|
public function getLocale(): string
|
|
{
|
|
return $this->locale;
|
|
}
|
|
|
|
/**
|
|
* Set the current locale string. If the form is invalid, an exception will be thrown.
|
|
* @param string $locale
|
|
* @return $this
|
|
*/
|
|
public function setLocale(string $locale): static
|
|
{
|
|
if(!static::checkLocale($locale)) {
|
|
throw new \RuntimeException("Could not set locale: invalid locale format.");
|
|
}
|
|
|
|
$this->locale = $locale;
|
|
$this->loadTranslations();
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get a translation from the translation array.
|
|
* @param string $key
|
|
* @param $default
|
|
* @return mixed|null|string
|
|
*/
|
|
public function getTranslation(string $key, $default = null)
|
|
{
|
|
if(empty($this->translations)) {
|
|
return $default;
|
|
}
|
|
|
|
$keys = explode ('.', $key);
|
|
|
|
$value = $this->translations;
|
|
foreach($keys as $index) {
|
|
if(!key_exists($index, $value)) return $default;
|
|
$value = $value[$index];
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Check if a locale string has the correct format.
|
|
* @param string $locale
|
|
* @return bool
|
|
*/
|
|
public static function checkLocale(string $locale): bool
|
|
{
|
|
return (!empty($locale) && preg_match_all(static::LOCALE_REGEX, $locale));
|
|
}
|
|
|
|
/**
|
|
* Load translations for the currently selected locale.
|
|
* @return void
|
|
*/
|
|
private function loadTranslations(): void
|
|
{
|
|
$dir = $this->translationsPath;
|
|
$locale = $this->locale;
|
|
$localeDir = $dir . DIRECTORY_SEPARATOR . $locale;
|
|
|
|
if(!file_exists($localeDir)) {
|
|
//TODO: is the error really needed?
|
|
throw new \RuntimeException("Unable to load translations; translation directory not found.");
|
|
}
|
|
|
|
$files = glob($localeDir . DIRECTORY_SEPARATOR . '*.php');
|
|
if($files === false || empty($files)) {
|
|
return;
|
|
}
|
|
|
|
$this->translations = [];
|
|
foreach($files as $file) {
|
|
$translations = require $file;
|
|
$key = basename($file, '.php');
|
|
$this->translations[$key] = $translations;
|
|
}
|
|
}
|
|
|
|
} |