Skip to content

Instantly share code, notes, and snippets.

@imbrish
Created September 29, 2016 11:48
Show Gist options
  • Save imbrish/204e3b85cadfd8d6db0369d6469eb814 to your computer and use it in GitHub Desktop.
Save imbrish/204e3b85cadfd8d6db0369d6469eb814 to your computer and use it in GitHub Desktop.
Laravel artisan command for syncing all translation files for given languages.
<?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