Created
October 29, 2019 22:46
-
-
Save aiphee/b48790c6a07686a4c37aacf3754af78e to your computer and use it in GitHub Desktop.
Lokalise.com for CakePhp 3.6 using official API
This file contains 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\Shell; | |
use Cake\Console\Shell; | |
use Cake\Core\App; | |
use Cake\Core\Configure; | |
use Cake\Network\Http\Client; | |
use Cake\Utility\Hash; | |
use ZipArchive; | |
class LokaliseShell extends Shell { | |
/** | |
* {@inheritDocs} | |
* | |
*/ | |
public function getOptionParser() | |
{ | |
return parent::getOptionParser() | |
->addSubCommand('push', [ | |
'help' => 'Pushes the translation template files (.pot) to lokalise and merges with existing translations upstream', | |
'parser' => [ | |
'options' => [ | |
'locales' => [ | |
'short' => 'l', | |
'help' => 'A comma separated list of all the locales that should be updated with the template files' | |
], | |
'cleanup' => [ | |
'help' => 'Remove old keys - compare src/Locale from server fst', | |
'boolean' => true, | |
'default' => false | |
], | |
'replace' => [ | |
'help' => 'Replace translations from code to lokalise, backup fst', | |
'boolean' => true, | |
'default' => false | |
], | |
'tags' => [ | |
'help' => 'A comma separated list of words that should be used as tags for the uploaded files' | |
], | |
'hidden' => [ | |
'help' => 'Add this flag if you wish to make the new translation strings hidden in the interface', | |
'boolean' => true, | |
'default' => false | |
] | |
] | |
] | |
]) | |
->addSubcommand('pull', [ | |
'help' => 'Dowloads all translation strings from lokalise and place them in the right folders for Cake to pick up', | |
'parser' => [ | |
'options' => [ | |
'locales' => [ | |
'short' => 'l', | |
'help' => 'A comma separated list of all the locales that should be downloaded. By default all locales are downloaded' | |
], | |
] | |
] | |
]); | |
} | |
/** | |
* Downloads all translations and upakcs them into the Locale folder | |
* | |
* @return mixed | |
*/ | |
public function pull() | |
{ | |
$project = Configure::read('Lokalise.project'); | |
$token = Configure::read('Lokalise.api_key'); | |
$client = new \Lokalise\LokaliseApiClient($token); | |
$locales = array_filter(array_map('trim', explode(',', Hash::get($this->params, 'locales', '')))); | |
$response = $client->files->download($project, [ | |
'format' => 'po', | |
'filter_langs' => $locales, | |
'original_filenames' => true, | |
'export_sort' => 'first_added' | |
]); | |
$this->processFile($response->body['bundle_url']); | |
$this->out('<success>Replaced translation files. You can now commit the changes</success>'); | |
} | |
/** | |
* Download file by link provided by API response | |
* | |
* @param string $path Path to zip file | |
* @return mixed | |
*/ | |
protected function processFile($path) | |
{ | |
$this->verbose("Starting download of <info>$path</info>"); | |
$date = gmdate('Y-m-d.H.i.s'); | |
$destination = sys_get_temp_dir() . DS; | |
$filename = $destination . "translations_$date.zip"; | |
$client = new Client(); | |
$response = $client->get($path); | |
if ($response->getStatusCode() !== 200) { | |
return $this->abort('Could not download translations file'); | |
} | |
file_put_contents($filename, $response->body()); | |
$this->out('<success>Successfully downloaded bundle file</success>'); | |
$zip = new ZipArchive; | |
$zip->open($filename); | |
for ($i = 0; $i < $zip->numFiles; $i++) { | |
$stat = $zip->statIndex($i); | |
if (preg_match('/\.pot$/', $stat['name'])) { | |
$zip->renameIndex($i, preg_replace('/\.pot$/', '.po', $stat['name'])); | |
} | |
} | |
$zip->close(); | |
$zip->open($filename); | |
$zip->extractTo(App::path('Locale')[0]); | |
$this->verbose('Successfully extracted bundle file'); | |
unlink($filename); | |
$this->verbose('Deleted bundle file'); | |
} | |
/** | |
* Pushs all pot files to lokalise | |
* | |
* @return void | |
*/ | |
public function push() | |
{ | |
$paths = App::path('Locale'); | |
$project = Configure::read('Lokalise.project'); | |
$token = Configure::read('Lokalise.api_key'); | |
$client = new \Lokalise\LokaliseApiClient($token); | |
$locales = array_filter(array_map('trim', explode(',', Hash::get($this->params, 'locales', '')))); | |
$tags = array_filter(array_map('trim', explode(',', Hash::get($this->params, 'tags', '')))); | |
if (empty($locales)) { | |
$locales = [Configure::read('App.defaultLocale')]; | |
} | |
$progress = $this->helper('Progress'); | |
$this->clear(); | |
$this->out('Starting the file upload'); | |
if ($this->params['cleanup']) { | |
$this->verbose('Deleting old'); | |
} | |
if ($this->params['replace']) { | |
$this->verbose('Replacing changed from old'); | |
} | |
collection($paths) | |
->map(function ($path) { | |
return glob($path . '*.pot'); | |
}) | |
->unfold() | |
->unfold(function ($file) use ($locales) { | |
foreach ($locales as $l) { | |
yield $file => $l; | |
} | |
}) | |
->through(function ($all) use ($progress) { | |
$total = iterator_count($all); | |
$progress->init(['total' => $total]); | |
return $all; | |
}) | |
->each(function ($locale, $file) use ($client, $project, $token, $tags, $progress) { | |
// We need to observe the API throttling from lokalise | |
sleep(5); | |
$this->verbose(sprintf('Uploading file <info>%s</info> for locale <info>%s</info>', $file, $locale)); | |
// It is easier for all if tje files terminate with .po | |
$dest = str_replace('.pot', '.po', sys_get_temp_dir() . DS . basename($file)); | |
file_put_contents($dest, file_get_contents($file)); | |
$body = [ | |
'data' => base64_encode(file_get_contents($dest)), | |
'filename' => str_replace('.pot', '.po', basename($file)), | |
'lang_iso' => $locale, | |
'replace_modified' => true, | |
'distinguish_by_file' => true, | |
'hidden' => (int) $this->params['hidden'], | |
'tags' => $tags | |
]; | |
if ($this->params['cleanup']) { | |
$body['cleanup_mode'] = true; | |
} | |
if ($this->params['replace']) { | |
$body['replace_modified'] = true; | |
} | |
$response = $client->files->upload($project, $body); | |
$progress->increment(1); | |
$progress->draw(); | |
}); | |
$this->clear(); | |
$this->nl(2); | |
$this->out('<success>All Done.</success>'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment