Created
September 29, 2016 11:48
-
-
Save imbrish/204e3b85cadfd8d6db0369d6469eb814 to your computer and use it in GitHub Desktop.
Laravel artisan command for syncing all translation files for given languages.
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 | |
namespace App\Console\Commands; | |
use Illuminate\Console\Command; | |
class LocalizationSync extends Command | |
{ | |
/** | |
* The name and signature of the console command. | |
* | |
* @var string | |
*/ | |
protected $signature = 'localization:sync {base : Base language} {target : Target language}'; | |
/** | |
* The console command description. | |
* | |
* @var string | |
*/ | |
protected $description = 'Synchronize all lang files in target language with base language'; | |
/** | |
* Create a new command instance. | |
* | |
* @return void | |
*/ | |
public function __construct() | |
{ | |
parent::__construct(); | |
} | |
/** | |
* Execute the console command. | |
* | |
* @return mixed | |
*/ | |
public function handle() | |
{ | |
$base_lang = $this->argument('base'); | |
$target_lang = $this->argument('target'); | |
$lang_dir = base_path() . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'lang'; | |
$base_dir = $lang_dir . DIRECTORY_SEPARATOR . $base_lang; | |
$target_dir = $lang_dir . DIRECTORY_SEPARATOR . $target_lang; | |
foreach (scandir($base_dir) as $name) { | |
if ($name == '.' || $name == '..' || preg_match('#\.[0-9]{8}_[0-9]{6}\.php$#', $name)) { | |
continue; | |
} | |
$base_path = $base_dir . DIRECTORY_SEPARATOR . $name; | |
$target_path = $target_dir . DIRECTORY_SEPARATOR . $name; | |
if (file_exists($target_path)) { | |
$target = file_get_contents($target_path); | |
$lemmas = $this->parse($target); | |
if ($lemmas === false) { | |
$this->error("Parsing failed while reading '$target_lang/$name'"); | |
continue; | |
} | |
} | |
else { | |
$target = false; | |
$lemmas = []; | |
} | |
$base = file_get_contents($base_path); | |
$result = $this->parse($base, $lemmas); | |
if ($result === false) { | |
$this->error("Parsing failed while syncing '$base_lang/$name'"); | |
continue; | |
} | |
if ($target === false || $target != $result) { | |
file_put_contents($target_path, $result); | |
$this->info("File '$target_lang/$name' synchronized"); | |
} | |
else { | |
$this->line("File '$target_lang/$name' already in sync"); | |
} | |
} | |
return 0; | |
} | |
/** | |
* If lemmas are given substitute them in the content | |
* Otherwise extract lemmas from content | |
* | |
* @param string $content | |
* @param false|array $lemmas | |
* @return string | |
*/ | |
public function parse($content, $lemmas = false) | |
{ | |
$result = $lemmas === false ? [] : ''; | |
$tree = [null]; | |
$expects_key = false; | |
while (strlen($content) > 0) { | |
// whitespace, multiline comment, single line comment, initial return statement, final semicolon, array pair separator, array item separator, php opening tag, php closing tag | |
if (preg_match('#^\s+#', $content, $match) | |
|| preg_match('#^/\*.*?\*/#s', $content, $match) | |
|| preg_match('#^//.*?(?:\r\n?|\n)#', $content, $match) | |
|| preg_match('#^return#', $content, $match) | |
|| preg_match('#^;#', $content, $match) | |
|| preg_match('#^=>#', $content, $match) | |
|| preg_match('#^,#', $content, $match) | |
|| preg_match('#^<\?php#', $content, $match) | |
|| preg_match('#^\?>#', $content, $match) | |
) { | |
$segment = $match[0]; | |
} | |
// array opening | |
else if (preg_match('#^\[#', $content, $match)) { | |
if ($expects_key) { | |
return false; | |
} | |
$segment = $match[0]; | |
$expects_key = true; | |
} | |
// array closing | |
else if (preg_match('#^\]#', $content, $match)) { | |
// there are no more open array, including top level | |
if (count($tree) < 1) { | |
return false; | |
} | |
$segment = $match[0]; | |
array_pop($tree); | |
} | |
// single or double quoted string | |
else if (preg_match('#^(")((?:[^"\\\\]|\\\\.)*)"#', $content, $match) | |
|| preg_match("#^(')((?:[^'\\\\]|\\\\.)*)'#", $content, $match) | |
) { | |
if ($expects_key) { | |
$segment = $match[0]; | |
// add key to tree structure | |
$tree[] = $match[2]; | |
$expects_key = false; | |
} | |
else { | |
// there is no key to assign the value to | |
if (count($tree) < 2) { | |
return false; | |
} | |
$key = implode('.', $tree); | |
// add value to results array | |
if ($lemmas === false) { | |
$result[$key] = $match[2]; | |
} | |
// replace value with matching, non-empty lemma | |
else if (array_key_exists($key, $lemmas) && strlen($lemmas[$key]) > 0) { | |
$segment = $match[1] . $lemmas[$key] . $match[1]; | |
} | |
// mark value as not specified | |
else { | |
$segment = $match[1] . '@todo: ' . $key . $match[1]; | |
} | |
array_pop($tree); | |
$expects_key = true; | |
} | |
} | |
// non recognized - something gone wrong | |
else { | |
return false; | |
} | |
$content = substr($content, strlen($match[0])); | |
if ($lemmas !== false) { | |
$result .= $segment; | |
} | |
} | |
return $result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment