2019-12-21 18:51:56 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Tell;
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
class I18n implements MissingKeyInterface
|
2019-12-21 18:51:56 +00:00
|
|
|
{
|
|
|
|
const DELIMITER = '.';
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected string $locale = "en_US";
|
2019-12-21 18:51:56 +00:00
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected string $language = "";
|
2019-12-21 18:51:56 +00:00
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected array $data = [];
|
2019-12-21 18:51:56 +00:00
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected array $fileStack = [];
|
2019-12-21 18:51:56 +00:00
|
|
|
|
|
|
|
protected string $currentLanguage = "";
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected Reader\ReaderInterface $dataReader;
|
2019-12-21 18:51:56 +00:00
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected ? Reader\ReaderInterface $cacheReader = null;
|
2019-12-21 18:51:56 +00:00
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected ? MissingKeyInterface $missingKey = null;
|
|
|
|
|
|
|
|
public function __construct(
|
|
|
|
Reader\ReaderInterface $dataReader,
|
|
|
|
? Reader\ReaderInterface $cacheReader = null,
|
|
|
|
? MissingKeyInterface $missingKey = null
|
|
|
|
)
|
|
|
|
{
|
|
|
|
$this->dataReader = $dataReader;
|
|
|
|
$this->cacheReader = $cacheReader;
|
|
|
|
$this->missingKey = $missingKey;
|
2019-12-21 18:51:56 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
public function initialize(bool $useCache) : bool
|
|
|
|
{
|
|
|
|
$loaded = $useCache && $this->fromReader($this->cacheReader) ?: $this->fromReader($this->dataReader);
|
|
|
|
|
|
|
|
if ( ! $useCache ) {
|
|
|
|
$this->cacheReader->save($this->locale, $this->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $loaded;
|
2019-12-21 18:51:56 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
public function fromKey(string $key, array $variables) : ?string
|
|
|
|
{
|
|
|
|
if ( null === ( $string = $this->get($key) ) ) {
|
|
|
|
$string = $this->missingKey ? $this->missingKey->get($key) : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_array($string)) {
|
|
|
|
$string = json_encode($string);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $string && $variables ? $this->placeVariables($string, $variables) : $string;
|
2019-12-21 18:51:56 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
public function get(string $key)
|
|
|
|
{
|
|
|
|
# Testing full locale key first
|
|
|
|
if ( null === ( $string = Iterate::arrayGet($this->data, "{$this->locale}.$key", static::DELIMITER)) ) {
|
|
|
|
# Fallback on language only
|
|
|
|
$string = Iterate::arrayGet($this->data, "{$this->language}.$key", static::DELIMITER);
|
2019-12-21 18:51:56 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
return $string;
|
2019-12-21 18:51:56 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
public function set(string $key, $value)
|
|
|
|
{
|
2019-12-21 18:51:56 +00:00
|
|
|
$cache = explode(static::DELIMITER, $key);
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
while ( ! empty($cache) ) {
|
2019-12-21 18:51:56 +00:00
|
|
|
$imp = implode(static::DELIMITER, $cache);
|
|
|
|
array_pop($cache);
|
|
|
|
unset( $this->cache[$imp] );
|
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
$this->cache[$key] = $value;
|
2019-12-21 18:51:56 +00:00
|
|
|
|
|
|
|
return Iterate::arraySet($this->data, $key, $value, static::DELIMITER);
|
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
public function locale(?string $set = null)
|
|
|
|
{
|
|
|
|
$locale = $set === null ? ( $this->locale ?? null ) : $this->locale = strtolower(explode(".", $this->locale)[0]);
|
|
|
|
|
|
|
|
if ( $set !== null ) {
|
|
|
|
$this->language = explode('_', $locale)[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $locale;
|
2019-12-21 18:51:56 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected function mergeData($data) : void
|
|
|
|
{
|
|
|
|
$this->data = array_replace_recursive($this->data, Iterate::splitKeys($data));
|
|
|
|
}
|
2019-12-21 18:51:56 +00:00
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected function fromReader(Reader\ReaderInterface $reader) : bool
|
|
|
|
{
|
|
|
|
foreach($reader->pathList as $path) {
|
2019-12-21 18:51:56 +00:00
|
|
|
foreach(Iterate::files($path) as $item) {
|
2020-05-10 02:55:07 +00:00
|
|
|
if ( $reader->accept($item->getExtension() )) {
|
|
|
|
if ( null !== ( $data = $reader->load( $item ) )) {
|
|
|
|
|
|
|
|
if ( $reader->filenameAsKey ) {
|
|
|
|
# Adding folder to full key
|
|
|
|
$filekey = ltrim(substr($item->getPathname(), strlen($path)), DIRECTORY_SEPARATOR);
|
|
|
|
|
|
|
|
# Removing extension
|
|
|
|
$filekey = substr($filekey, 0, strrpos($filekey, '.'));
|
|
|
|
|
|
|
|
# Replacing directory separator with dots
|
|
|
|
$filekey = str_replace(DIRECTORY_SEPARATOR, '.', $filekey);
|
|
|
|
|
|
|
|
$this->mergeData([ '{' . $filekey . '}' => $data ]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$this->mergeData($data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-21 18:51:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
return false;
|
2019-12-21 18:51:56 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 02:55:07 +00:00
|
|
|
protected function placeVariables(string $string, array $parameters) {
|
|
|
|
if ( preg_match_all('~{$(.*?)}~si', $string, $matches, PREG_SET_ORDER) ) {
|
|
|
|
$search = [];
|
|
|
|
|
|
|
|
foreach($matches as $item) {
|
|
|
|
$search[ $item[0] ] = Iterate::arrayGet($parameters, $item[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return str_replace(array_keys($search), array_values($search), $string);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $string;
|
2019-12-21 18:51:56 +00:00
|
|
|
}
|
|
|
|
}
|