- First commit, some small work porting an old lib I had done into this first draft

This commit is contained in:
Dave M. 2019-12-21 13:51:56 -05:00
commit a58efcdef4
4 changed files with 288 additions and 0 deletions

18
composer.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "mcnd/tell",
"description": "JSON-based i18n library.",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Dave Mc Nicoll",
"email": "mcndave@gmail.com"
}
],
"require": {},
"autoload": {
"psr-4": {
"Tell\\": "src/"
}
}
}

106
src/I18n.php Normal file
View File

@ -0,0 +1,106 @@
<?php
namespace Tell;
class I18n
{
const DELIMITER = '.';
protected bool $updatedData = false;
protected array $data = [];
protected array $cache = [];
protected array $engine = [];
protected string $currentLanguage = "";
protected array $fileStack = [];
protected function __construct(bool $enableCache = false) {
# $this->persistent = new Persistent(static::class);
if ( $enableCache ) {
# $data = $this->persistent->load();
# $this->data = $data['data'];
# $this->fileStack = $data['fileStack'];
}
}
public function __destruct() {
# $this->update_data() && $this->persistent->save([
# 'fileStack' => $this->fileStack,
# 'data' => $this->data
# ]);
}
public function updateData() {
return $this->updatedData;
}
public static function get(?string $key = null) {
if ( $key === null ) {
return $this->data;
}
return isset( $this->cache[$key] ) ? $this->cache[$key] : $this->cache[$key] = Iterate::arrayGet($this->data, ( $this->currentLanguage ? $this->currentLanguage."." : "").$key, static::DELIMITER);
}
public static function set(string $key, $value) {
$cache = explode(static::DELIMITER, $key);
while ( !empty($cache) ) {
$imp = implode(static::DELIMITER, $cache);
array_pop($cache);
unset( $this->cache[$imp] );
}
$this->cache[$key] = $value ;
return Iterate::arraySet($this->data, $key, $value, static::DELIMITER);
}
public function addEngine($engine) {
$this->engine[] = $engine;
}
public function load(string $path, bool $filenameAsKey = false) {
if ( !in_array($path, $this->fileStack) ) {
$this->updatedData = true;
$this->fileStack[] = $path;
foreach(Iterate::files($path) as $item) {
foreach($this->engine as $engine) {
if ( $engine->accept($item )) {
if ( $array = $engine->translate( $item ) ){
if ($filenameAsKey ) {
$base = basename($item);
$key = substr($base,0, strrpos($base, "."));
$keysplit = explode(".", $key);
$key = array_pop($keysplit);
$this->mergeData([ $keysplit ? "{".implode(".", array_merge([ $key ], $keysplit))."}" : $key => $array ]);
}
else {
$this->mergeData($array);
}
}
continue 2;
}
}
}
}
}
public static function currentLanguage($set = null) {
return $set === null ? $this->currentLanguage : $this->currentLanguage = $set;
}
protected function mergeData($data) {
$this->data = array_replace_recursive($this->data, Iterate::splitKeys($data));
}
}

117
src/Iterate.php Normal file
View File

@ -0,0 +1,117 @@
<?php
namespace Tell;
use RecursiveDirectoryIterator,
RecursiveIteratorIterator,
RecursiveRegexIterator,
RegexIterator;
class Iterate
{
/**
* Set value to array with a given path using recursion
* @param array $array - array to set passed by reference !
* @param string $path - path like 'person.name.first'
* @param string $value - value to set
*/
public static function arraySet(array &$array, string $path, string $value = '', string $delimiter = '.') {
$pathArr = explode($delimiter, $path);
// Go to next node
if ( isset($pathArr[1])) {
static::arraySet($array[ array_shift($pathArr) ], implode($delimiter, $pathArr), $value);
}
// We are at the end of the path, set value
else {
$array[ $pathArr[0] ] = $value;
}
}
public static function arrayGet(array $array, string $path, string $delimiter = '.') {
$pathArr = explode($delimiter, $path);
if (isset($array[$pathArr[0]])) {
if ( isset($pathArr[1]) ) {
return static::arrayGet($array[array_shift($pathArr)], implode($delimiter, $pathArr));
}
else {
return $array[$pathArr[0]];
}
}
else {
return null;
}
}
public static function splitKeys(array &$array, string $delimiter = ".", string $enclosed = '{}') {
if ( is_array($array) ) {
$swap = [];
foreach($array as $key => &$value) {
$process = strstr($key, $delimiter);
if ( $enclosed ) {
if ( ( strlen($key) - 2 ) !== strlen( $tkey = trim($key, $enclosed) ) ) {
$process = false;
}
else {
$oldKey = $key;
$key = $tkey;
}
}
if ( $process ) {
$tmp = [];
$keylist = explode($delimiter, $key);
$finalKey = array_shift($keylist);
# Arrayobj::iterate_set($keylist, $tmp, $value);
static::arraySet($tmp, $key, $value);
$swap[$finalKey] = static::splitKeys($tmp, $delimiter);
unset($array[isset($oldKey) ? $oldKey : $key]);
}
else if ( is_array($value) ) {
$value = static::splitKeys($value, $delimiter);
}
}
foreach($swap as $key => $item) {
if ( $enclosed ) {
if ( ( strlen($key) - 2 ) === ( $tkey = trim($key, $enclosed)) ) {
$key = $tkey;
}
}
$array[$key] = $item;
}
}
return $array;
}
public static function files(string $path, string $fileExtension = "") {
$retval = [];
if ( \file_exists($path) ) {
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD);
if ($fileExtension) {
$iterator = new RegexIterator($iterator, '/^.+\.'.$fileExtension.'$/i', RecursiveRegexIterator::GET_MATCH);
}
foreach ($iterator as $file) {
if ($fileExtension) {
$retval[] = $file[0];
}
else {
if ( $file->isFile() || $file->isDir() ) {
$retval[] = $file->getRealPath();
}
}
}
}
return $retval;
}
}

47
src/TellTrait.php Normal file
View File

@ -0,0 +1,47 @@
<?php
namespace Tell;
trait TellTrait {
public function lang(...$args)
{
static $vars_pattern = null;
$vars_pattern || ( $vars_pattern = $this->config('Eckinox.language.vars.pattern') );
switch ( count($args) ) {
case 1:
return ( $value = Language::get( $args[0] ) ) !== null ? $value : ( Eckinox::debug() ? "'{$args[0]}'" : "" );
case 0:
return Language::instance();
case 2:
if ( empty($args[1]) ) {
return $this->lang($args[0]);
}
/* Handling arrays with keys */
if ( Arrayobj::array_is_associative($args[1]) ) {
$content = $this->lang($args[0]);
if ( preg_match_all("~\\{\\$(.*?)\\}~si", $this->lang($args[0]), $matches, PREG_SET_ORDER) ) {
$search = [];
foreach($matches as $item) {
$search[ $item[0] ] = $a = iterate::array_get($args[1], $item[1]);
}
$content = str_replace(array_keys($search), array_values($search), $content);
}
return $content;
}
default:
/* Handling arrays with indexes */
return call_user_func_array('sprintf', array_merge([ $this->lang( array_shift($args) ) ], $args));
}
}
}