PDF rausgenommen
This commit is contained in:
@ -0,0 +1,233 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class CreatePull extends TranslationBase
|
||||
{
|
||||
const GIT_BASE_BRANCH = '3.x-dev';
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:createpull')
|
||||
->setDescription('Updates translation files')
|
||||
->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'Transifex username')
|
||||
->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Transifex password')
|
||||
->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'Transifex project slug')
|
||||
->addOption('plugin', 'P', InputOption::VALUE_OPTIONAL, 'optional name of plugin to update translations for');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$changes = shell_exec('git status --porcelain -uno');
|
||||
|
||||
if (!empty($changes)) {
|
||||
|
||||
$output->writeln("You have uncommited changes. Creating pull request is only available with a clean working directory");
|
||||
return;
|
||||
}
|
||||
|
||||
$unpushedCommits = shell_exec('git log origin/' . self::GIT_BASE_BRANCH . '..HEAD');
|
||||
|
||||
if (!empty($unpushedCommits)) {
|
||||
|
||||
$output->writeln("You have unpushed commits. Creating pull request is only available with a clean working directory");
|
||||
return;
|
||||
}
|
||||
|
||||
chdir(PIWIK_DOCUMENT_ROOT);
|
||||
|
||||
shell_exec('
|
||||
git checkout -f ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
|
||||
git pull > /dev/null 2>&1
|
||||
git submodule init > /dev/null 2>&1
|
||||
git submodule update > /dev/null 2>&1
|
||||
');
|
||||
|
||||
$plugin = $input->getOption('plugin');
|
||||
if (!empty($plugin)) {
|
||||
|
||||
chdir(PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR.'plugins'.DIRECTORY_SEPARATOR.$plugin);
|
||||
shell_exec('
|
||||
git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
|
||||
git pull > /dev/null 2>&1
|
||||
');
|
||||
}
|
||||
|
||||
// check if branch exists localy and track it if not
|
||||
$branch = shell_exec('git branch | grep translationupdates');
|
||||
|
||||
if (empty($branch)) {
|
||||
|
||||
shell_exec('git checkout -b translationupdates origin/translationupdates');
|
||||
}
|
||||
|
||||
// switch to branch and update it to latest $GIT_BASE_BRANCH
|
||||
shell_exec('
|
||||
git checkout -f translationupdates > /dev/null 2>&1
|
||||
git reset --hard origin/' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
|
||||
git push origin translationupdates > /dev/null 2>&1
|
||||
');
|
||||
|
||||
// update translation files
|
||||
$command = $this->getApplication()->find('translations:update');
|
||||
$arguments = array(
|
||||
'command' => 'translations:update',
|
||||
'--username' => $input->getOption('username'),
|
||||
'--password' => $input->getOption('password'),
|
||||
'--slug' => $input->getOption('slug'),
|
||||
'--plugin' => $plugin
|
||||
);
|
||||
$inputObject = new ArrayInput($arguments);
|
||||
$inputObject->setInteractive($input->isInteractive());
|
||||
$command->run($inputObject, $output);
|
||||
|
||||
shell_exec('git add lang/. > /dev/null 2>&1');
|
||||
|
||||
if (empty($plugin)) {
|
||||
foreach (Update::getPluginsInCore() as $pluginName) {
|
||||
shell_exec(sprintf('git add plugins/%s/lang/. > /dev/null 2>&1', $pluginName));
|
||||
}
|
||||
}
|
||||
|
||||
$changes = shell_exec('git status --porcelain -uno');
|
||||
|
||||
if (empty($changes)) {
|
||||
|
||||
$output->writeln("Nothing changed. Everything is already up to date.");
|
||||
shell_exec('git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1');
|
||||
return;
|
||||
}
|
||||
|
||||
API::unsetInstance(); // reset languagemanager api (to force refresh of data)
|
||||
|
||||
$stats = shell_exec('git diff --numstat HEAD');
|
||||
|
||||
preg_match_all('/([0-9]+)\t([0-9]+)\t[a-zA-Z\/]*lang\/([a-z]{2,3}(?:-[a-z]{2,3})?)\.json/', $stats, $lineChanges);
|
||||
|
||||
$addedLinesSum = 0;
|
||||
if (!empty($lineChanges[1])) {
|
||||
$addedLinesSum = array_sum($lineChanges[1]);
|
||||
}
|
||||
|
||||
$linesSumByLang = array();
|
||||
$lineChangesCount = count($lineChanges[0]);
|
||||
for ($i = 0; $i < $lineChangesCount; $i++) {
|
||||
@$linesSumByLang[$lineChanges[3][$i]] += $lineChanges[1][$i];
|
||||
}
|
||||
|
||||
preg_match_all('/M [a-zA-Z\/]*lang\/([a-z]{2,3}(?:-[a-z]{2,3})?)\.json/', $changes, $modifiedFiles);
|
||||
preg_match_all('/A [a-zA-Z\/]*lang\/([a-z]{2,3}(?:-[a-z]{2,3})?)\.json/', $changes, $addedFiles);
|
||||
|
||||
$messages = array();
|
||||
|
||||
$languageCodesTouched = array();
|
||||
if (!empty($addedFiles[1])) {
|
||||
foreach ($addedFiles[1] as $addedFile) {
|
||||
$languageInfo = $this->getLanguageInfoByIsoCode($addedFile);
|
||||
$messages[$addedFile] = sprintf('- Added %s (%s changes / %s translated)\n', $languageInfo['english_name'], $linesSumByLang[$addedFile], $languageInfo['percentage_complete']);
|
||||
}
|
||||
$languageCodesTouched = array_merge($languageCodesTouched, $addedFiles[1]);
|
||||
}
|
||||
|
||||
if (!empty($modifiedFiles[1])) {
|
||||
foreach ($modifiedFiles[1] as $modifiedFile) {
|
||||
if ($linesSumByLang[$modifiedFile]) {
|
||||
$languageInfo = $this->getLanguageInfoByIsoCode($modifiedFile);
|
||||
$messages[$modifiedFile] = sprintf(
|
||||
'- Updated %s (%s changes / %s translated)\n',
|
||||
$languageInfo['english_name'],
|
||||
$linesSumByLang[$modifiedFile],
|
||||
$languageInfo['percentage_complete']
|
||||
);
|
||||
$languageCodesTouched[] = $modifiedFile;
|
||||
}
|
||||
}
|
||||
$languageCodesTouched = array_unique($languageCodesTouched);
|
||||
}
|
||||
|
||||
$message = implode('', $messages);
|
||||
|
||||
$message .= '\n\nHelp us translate Matomo in your language!\nSignup at https://www.transifex.com/matomo/matomo/\nIf you have any questions, get in touch with us at translations@matomo.org';
|
||||
|
||||
$languageCodesTouched = array_unique($languageCodesTouched, SORT_REGULAR);
|
||||
|
||||
$title = sprintf(
|
||||
'Updated %s strings in %u languages (%s)',
|
||||
$addedLinesSum,
|
||||
count($languageCodesTouched),
|
||||
implode(', ', $languageCodesTouched)
|
||||
);
|
||||
|
||||
shell_exec('git commit -m "language update ${pluginName}"');
|
||||
shell_exec('git push');
|
||||
shell_exec('git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1');
|
||||
|
||||
$this->createPullRequest($output, $title, $message);
|
||||
}
|
||||
|
||||
private function getLanguageInfoByIsoCode($isoCode)
|
||||
{
|
||||
$languages = API::getInstance()->getAvailableLanguagesInfo();
|
||||
foreach ($languages as $languageInfo) {
|
||||
if ($languageInfo['code'] == $isoCode) {
|
||||
return $languageInfo;
|
||||
}
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
private function createPullRequest(OutputInterface $output, $title, $message)
|
||||
{
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
|
||||
while (true) {
|
||||
|
||||
$username = $dialog->ask($output, 'Please provide your GitHub username (to create a pull request using GitHub API): ');
|
||||
|
||||
$returnCode = shell_exec('curl \
|
||||
-X POST \
|
||||
-k \
|
||||
--silent \
|
||||
--write-out %{http_code} \
|
||||
--stderr /dev/null \
|
||||
-o /dev/null \
|
||||
-u '.$username.' \
|
||||
--data "{\"title\":\"[automatic translation update] '.$title.'\",\"body\":\"'.$message.'\",\"head\":\"translationupdates\",\"base\":\"' . self::GIT_BASE_BRANCH . '\"}" \
|
||||
-H "Accept: application/json" \
|
||||
https://api.github.com/repos/matomo-org/matomo/pulls');
|
||||
|
||||
switch ($returnCode) {
|
||||
case 401:
|
||||
$output->writeln("Pull request failed. Bad credentials... Please try again");
|
||||
continue 2;
|
||||
|
||||
case 422:
|
||||
$output->writeln("Pull request failed. Unprocessable Entity. Maybe a pull request was already created before.");
|
||||
return;
|
||||
|
||||
case 201:
|
||||
case 200:
|
||||
$output->writeln("Pull request successfully created.");
|
||||
return;
|
||||
|
||||
default:
|
||||
$output->writeln("Pull request failed... Please try again");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Container\StaticContainer;
|
||||
use Piwik\Exception\AuthenticationFailedException;
|
||||
use Piwik\Plugins\LanguagesManager\API as LanguagesManagerApi;
|
||||
use Piwik\Translation\Transifex\API;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class FetchTranslations extends TranslationBase
|
||||
{
|
||||
const DOWNLOAD_PATH = '/transifex';
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$path = StaticContainer::get('path.tmp') . self::DOWNLOAD_PATH;
|
||||
|
||||
$this->setName('translations:fetch')
|
||||
->setDescription('Fetches translations files from Transifex to ' . $path)
|
||||
->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'Transifex username')
|
||||
->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Transifex password')
|
||||
->addOption('lastupdate', 'l', InputOption::VALUE_OPTIONAL, 'Last time update ran', time()-30*24*3600)
|
||||
->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'project slug on transifex', 'matomo')
|
||||
->addOption('plugin', 'r', InputOption::VALUE_OPTIONAL, 'Plugin to update');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->setDecorated(true);
|
||||
|
||||
$username = $input->getOption('username');
|
||||
$password = $input->getOption('password');
|
||||
$plugin = $input->getOption('plugin');
|
||||
$lastUpdate = $input->getOption('lastupdate');
|
||||
$slug = $input->getOption('slug');
|
||||
|
||||
$resource = 'matomo-'. ($plugin ? 'plugin-'.strtolower($plugin) : 'base');
|
||||
|
||||
$transifexApi = new API($username, $password, $slug);
|
||||
|
||||
// remove all existing translation files in download path
|
||||
$files = glob($this->getDownloadPath() . DIRECTORY_SEPARATOR . '*.json');
|
||||
array_map('unlink', $files);
|
||||
|
||||
if (!$transifexApi->resourceExists($resource)) {
|
||||
$output->writeln("Skipping resource $resource as it doesn't exist on Transifex");
|
||||
return;
|
||||
}
|
||||
|
||||
$output->writeln("Fetching translations from Transifex for resource $resource");
|
||||
|
||||
$availableLanguages = LanguagesManagerApi::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageCodes = array();
|
||||
foreach ($availableLanguages as $languageInfo) {
|
||||
$languageCodes[] = $languageInfo['code'];
|
||||
}
|
||||
|
||||
$languageCodes = array_filter($languageCodes, function($code) {
|
||||
return !in_array($code, array('en', 'dev'));
|
||||
});
|
||||
|
||||
try {
|
||||
$languages = $transifexApi->getAvailableLanguageCodes();
|
||||
|
||||
if (!empty($plugin)) {
|
||||
$languages = array_filter($languages, function ($language) {
|
||||
return LanguagesManagerApi::getInstance()->isLanguageAvailable(str_replace('_', '-', strtolower($language)));
|
||||
});
|
||||
}
|
||||
} catch (AuthenticationFailedException $e) {
|
||||
$languages = $languageCodes;
|
||||
}
|
||||
|
||||
/** @var ProgressBar $progress */
|
||||
$progress = new ProgressBar($output, count($languages));
|
||||
|
||||
$progress->start();
|
||||
|
||||
$statistics = $transifexApi->getStatistics($resource);
|
||||
|
||||
foreach ($languages as $language) {
|
||||
try {
|
||||
// if we have modification date given from statistics api compare it with given last update time to ignore not update resources
|
||||
if (LanguagesManagerApi::getInstance()->isLanguageAvailable(str_replace('_', '-', strtolower($language))) && isset($statistics->$language)) {
|
||||
$lastupdated = strtotime($statistics->$language->last_update);
|
||||
if ($lastUpdate > $lastupdated) {
|
||||
$progress->advance();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$translations = $transifexApi->getTranslations($resource, $language, true);
|
||||
file_put_contents($this->getDownloadPath() . DIRECTORY_SEPARATOR . str_replace('_', '-', strtolower($language)) . '.json', $translations);
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln("Error fetching language file $language: " . $e->getMessage());
|
||||
}
|
||||
$progress->advance();
|
||||
}
|
||||
|
||||
$progress->finish();
|
||||
$output->writeln('');
|
||||
}
|
||||
|
||||
public static function getDownloadPath()
|
||||
{
|
||||
$path = StaticContainer::get('path.tmp') . self::DOWNLOAD_PATH;
|
||||
|
||||
if (!is_dir($path)) {
|
||||
mkdir($path);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class LanguageCodes extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:languagecodes')
|
||||
->setDescription('Shows available language codes');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageCodes = array();
|
||||
foreach ($languages as $languageInfo) {
|
||||
$languageCodes[] = $languageInfo['code'];
|
||||
}
|
||||
|
||||
sort($languageCodes);
|
||||
|
||||
$output->writeln("Currently available languages:");
|
||||
$output->writeln(implode("\n", $languageCodes));
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class LanguageNames extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:languagenames')
|
||||
->setDescription('Shows available language names');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageNames = array();
|
||||
foreach ($languages as $languageInfo) {
|
||||
$languageNames[] = $languageInfo['english_name'];
|
||||
}
|
||||
|
||||
sort($languageNames);
|
||||
|
||||
$output->writeln("Currently available languages:");
|
||||
$output->writeln(implode("\n", $languageNames));
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugin\Manager;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class PluginsWithTranslations extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:plugins')
|
||||
->setDescription('Shows all plugins that have own translation files');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->writeln("Following plugins contain their own translation files:");
|
||||
|
||||
$pluginFiles = array();
|
||||
foreach (Manager::getPluginsDirectories() as $pluginsDir) {
|
||||
$pluginFiles = array_merge($pluginsDir, glob(sprintf('%s*/lang/en.json', $pluginsDir)));
|
||||
}
|
||||
$pluginFiles = array_map(function($elem){
|
||||
$replace = Manager::getPluginsDirectories();
|
||||
$replace[] = '/lang/en.json';
|
||||
return str_replace($replace, '', $elem);
|
||||
}, $pluginFiles);
|
||||
|
||||
$output->writeln(join("\n", $pluginFiles));
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\ByBaseTranslations;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\ByParameterCount;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\EmptyTranslations;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\EncodedEntities;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\UnnecassaryWhitespaces;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Validate\CoreTranslations;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Validate\NoScripts;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Writer;
|
||||
use Symfony\Component\Console\Helper\DialogHelper;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class SetTranslations extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:set')
|
||||
->setDescription('Sets new translations for a given language')
|
||||
->addOption('code', 'c', InputOption::VALUE_REQUIRED, 'code of the language to set translations for')
|
||||
->addOption('file', 'f', InputOption::VALUE_REQUIRED, 'json file to load new translations from')
|
||||
->addOption('plugin', 'pl', InputOption::VALUE_OPTIONAL, 'optional name of plugin to set translations for');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
/** @var DialogHelper $dialog */
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
|
||||
$languageCode = $input->getOption('code');
|
||||
$filename = $input->getOption('file');
|
||||
|
||||
$languageCodes = (new API())->getAvailableLanguages();
|
||||
|
||||
if (empty($languageCode) || !in_array($languageCode, $languageCodes)) {
|
||||
$languageCode = $dialog->askAndValidate($output, 'Please provide a valid language code: ', function ($code) use ($languageCodes) {
|
||||
if (!in_array($code, array_values($languageCodes))) {
|
||||
throw new \InvalidArgumentException(sprintf('Language code "%s" is invalid.', $code));
|
||||
}
|
||||
|
||||
return $code;
|
||||
});
|
||||
}
|
||||
|
||||
if (empty($filename) || !file_exists($filename)) {
|
||||
$filename = $dialog->askAndValidate($output, 'Please provide a file to load translations from: ', function ($file) {
|
||||
if (!file_exists($file)) {
|
||||
throw new \InvalidArgumentException(sprintf('File "%s" does not exist.', $file));
|
||||
}
|
||||
|
||||
return $file;
|
||||
});
|
||||
}
|
||||
|
||||
$output->writeln("Starting to import data from '$filename' to language '$languageCode'");
|
||||
|
||||
$plugin = $input->getOption('plugin');
|
||||
$translationWriter = new Writer($languageCode, $plugin);
|
||||
|
||||
$baseTranslations = $translationWriter->getTranslations("en");
|
||||
|
||||
$translationWriter->addValidator(new NoScripts());
|
||||
if (empty($plugin)) {
|
||||
$translationWriter->addValidator(new CoreTranslations($baseTranslations));
|
||||
}
|
||||
|
||||
$translationWriter->addFilter(new ByBaseTranslations($baseTranslations));
|
||||
$translationWriter->addFilter(new EmptyTranslations());
|
||||
$translationWriter->addFilter(new ByParameterCount($baseTranslations));
|
||||
$translationWriter->addFilter(new UnnecassaryWhitespaces($baseTranslations));
|
||||
$translationWriter->addFilter(new EncodedEntities($baseTranslations));
|
||||
|
||||
$translationData = file_get_contents($filename);
|
||||
$translations = json_decode($translationData, true);
|
||||
|
||||
$translationWriter->setTranslations($translations);
|
||||
|
||||
if (!$translationWriter->isValid()) {
|
||||
$output->writeln("Failed setting translations:" . $translationWriter->getValidationMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$translationWriter->hasTranslations()) {
|
||||
$output->writeln("No translations available");
|
||||
return;
|
||||
}
|
||||
|
||||
$translationWriter->save();
|
||||
|
||||
$output->writeln("Finished.");
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Development;
|
||||
use Piwik\Plugin\ConsoleCommand;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
abstract class TranslationBase extends ConsoleCommand
|
||||
{
|
||||
public function isEnabled()
|
||||
{
|
||||
return Development::isEnabled();
|
||||
}
|
||||
}
|
255
msd2/tracking/piwik/plugins/LanguagesManager/Commands/Update.php
Normal file
255
msd2/tracking/piwik/plugins/LanguagesManager/Commands/Update.php
Normal file
@ -0,0 +1,255 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Cache;
|
||||
use Piwik\Plugin\Manager;
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Helper\DialogHelper;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\NullOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
|
||||
/**
|
||||
*/
|
||||
class Update extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:update')
|
||||
->setDescription('Updates translation files')
|
||||
->addOption('force', 'f', InputOption::VALUE_NONE, 'Force update of all language files')
|
||||
->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'Transifex username')
|
||||
->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Transifex password')
|
||||
->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'Transifex project slug')
|
||||
->addOption('all', 'a', InputOption::VALUE_NONE, 'Force to update all plugins (even non core). Can not be used with plugin option')
|
||||
->addOption('plugin', 'P', InputOption::VALUE_OPTIONAL, 'optional name of plugin to update translations for');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->setDecorated(true);
|
||||
|
||||
$start = microtime(true);
|
||||
|
||||
/** @var DialogHelper $dialog */
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
|
||||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageCodes = array();
|
||||
foreach ($languages as $languageInfo) {
|
||||
$languageCodes[] = $languageInfo['code'];
|
||||
}
|
||||
|
||||
$plugin = $input->getOption('plugin');
|
||||
$forceAllPlugins = $input->getOption('all');
|
||||
|
||||
if (!$input->isInteractive()) {
|
||||
$output->writeln("(!) Non interactive mode: New languages will be skipped");
|
||||
}
|
||||
|
||||
$pluginList = array($plugin);
|
||||
if (empty($plugin)) {
|
||||
$pluginList = $forceAllPlugins ? self::getAllPlugins() : self::getPluginsInCore();
|
||||
array_unshift($pluginList, '');
|
||||
} else {
|
||||
$input->setOption('force', true); // force plugin only updates
|
||||
}
|
||||
|
||||
foreach ($pluginList as $plugin) {
|
||||
|
||||
$output->writeln("");
|
||||
|
||||
// fetch base or specific plugin
|
||||
$this->fetchTranslations($input, $output, $plugin);
|
||||
|
||||
$files = _glob(FetchTranslations::getDownloadPath() . DIRECTORY_SEPARATOR . '*.json');
|
||||
|
||||
if (count($files) == 0) {
|
||||
$output->writeln("No translation updates available! Skipped.");
|
||||
continue;
|
||||
}
|
||||
|
||||
$output->writeln("Starting to import new language files");
|
||||
|
||||
/** @var ProgressBar $progress */
|
||||
$progress = new ProgressBar($output, count($files));
|
||||
|
||||
$progress->start();
|
||||
|
||||
foreach ($files as $filename) {
|
||||
|
||||
$progress->advance();
|
||||
|
||||
$code = basename($filename, '.json');
|
||||
|
||||
if (!in_array($code, $languageCodes)) {
|
||||
|
||||
if (!empty($plugin)) {
|
||||
continue; # never create a new language for plugin only
|
||||
}
|
||||
|
||||
$createNewFile = false;
|
||||
if ($input->isInteractive()) {
|
||||
$createNewFile = $dialog->askConfirmation($output, "\nLanguage $code does not exist. Should it be added? ", false);
|
||||
}
|
||||
|
||||
if (!$createNewFile) {
|
||||
continue; # do not create a new file for the language
|
||||
}
|
||||
|
||||
@touch(PIWIK_DOCUMENT_ROOT . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR . $code . '.json');
|
||||
API::unsetAllInstances(); // unset language manager instance, so valid names are refetched
|
||||
|
||||
$command = $this->getApplication()->find('translations:generate-intl-data');
|
||||
$arguments = array(
|
||||
'command' => 'translations:generate-intl-data',
|
||||
'--language' => $code,
|
||||
);
|
||||
$inputObject = new ArrayInput($arguments);
|
||||
$inputObject->setInteractive($input->isInteractive());
|
||||
$command->run($inputObject, $output->isVeryVerbose() ? $output : new NullOutput());
|
||||
|
||||
API::unsetAllInstances(); // unset language manager instance, so valid names are refetched
|
||||
Cache::flushAll();
|
||||
|
||||
$languageCodes[] = $code;
|
||||
}
|
||||
|
||||
$command = $this->getApplication()->find('translations:set');
|
||||
$arguments = array(
|
||||
'command' => 'translations:set',
|
||||
'--code' => $code,
|
||||
'--file' => $filename,
|
||||
'--plugin' => $plugin
|
||||
);
|
||||
$inputObject = new ArrayInput($arguments);
|
||||
$inputObject->setInteractive($input->isInteractive());
|
||||
$command->run($inputObject, $output->isVeryVerbose() ? $output : new NullOutput());
|
||||
}
|
||||
|
||||
$progress->finish();
|
||||
$output->writeln('');
|
||||
}
|
||||
|
||||
$output->writeln("Finished in " . round(microtime(true)-$start, 3) . "s");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all plugins having their own translations that are bundled in core
|
||||
* @return array
|
||||
*/
|
||||
public static function getAllPlugins()
|
||||
{
|
||||
static $pluginsWithTranslations;
|
||||
|
||||
if (!empty($pluginsWithTranslations)) {
|
||||
return $pluginsWithTranslations;
|
||||
}
|
||||
|
||||
$pluginsWithTranslations = array();
|
||||
foreach (Manager::getPluginsDirectories() as $pluginsDir) {
|
||||
$pluginsWithTranslations = array_merge($pluginsWithTranslations, glob(sprintf('%s*/lang/en.json', $pluginsDir)));
|
||||
}
|
||||
$pluginsWithTranslations = array_map(function ($elem) {
|
||||
$replace = Manager::getPluginsDirectories();
|
||||
$replace[] = '/lang/en.json';
|
||||
return str_replace($replace, '', $elem);
|
||||
}, $pluginsWithTranslations);
|
||||
|
||||
return $pluginsWithTranslations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all plugins having their own translations that are bundled in core
|
||||
* @return array
|
||||
*/
|
||||
public static function getPluginsInCore()
|
||||
{
|
||||
static $pluginsInCore;
|
||||
|
||||
if (!empty($pluginsInCore)) {
|
||||
return $pluginsInCore;
|
||||
}
|
||||
|
||||
$submodules = shell_exec('git submodule status');
|
||||
preg_match_all('/plugins\/([a-zA-z]+) /', $submodules, $matches);
|
||||
$submodulePlugins = $matches[1];
|
||||
|
||||
// ignore complete new plugins as well
|
||||
$changes = shell_exec('git status');
|
||||
preg_match_all('/plugins\/([a-zA-z]+)\/\n/', $changes, $matches);
|
||||
$newPlugins = $matches[1];
|
||||
|
||||
$pluginsNotInCore = array_merge($submodulePlugins, $newPlugins);
|
||||
$pluginsWithTranslations = array();
|
||||
foreach (Manager::getPluginsDirectories() as $pluginsDir) {
|
||||
$pluginsWithTranslations = array_merge($pluginsWithTranslations, glob(sprintf('%s*/lang/en.json', $pluginsDir)));
|
||||
}
|
||||
$pluginsWithTranslations = array_map(function ($elem) {
|
||||
$replace = Manager::getPluginsDirectories();
|
||||
$replace[] = '/lang/en.json';
|
||||
return str_replace($replace, '', $elem);
|
||||
}, $pluginsWithTranslations);
|
||||
|
||||
$pluginsInCore = array_diff($pluginsWithTranslations, $pluginsNotInCore);
|
||||
|
||||
return $pluginsInCore;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @param string $plugin
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function fetchTranslations(InputInterface $input, OutputInterface $output, $plugin)
|
||||
{
|
||||
|
||||
$command = $this->getApplication()->find('translations:fetch');
|
||||
$arguments = array(
|
||||
'command' => 'translations:fetch',
|
||||
'--username' => $input->getOption('username'),
|
||||
'--password' => $input->getOption('password'),
|
||||
'--slug' => $input->getOption('slug'),
|
||||
'--plugin' => $plugin
|
||||
);
|
||||
|
||||
if ($input->getOption('force')) {
|
||||
$arguments['--lastupdate'] = 1;
|
||||
} else {
|
||||
$lastModDate = strtotime('2015-01-04 00:00:00'); // date of initial transifex setup
|
||||
try {
|
||||
// try to find the language file (of given plugin) with the newest modification date in git log
|
||||
$path = ($plugin ? 'plugins/' . $plugin . '/' : '') . 'lang';
|
||||
$files = explode("\n", trim(shell_exec('git ls-tree -r --name-only HEAD ' . $path)));
|
||||
|
||||
foreach ($files as $file) {
|
||||
$fileModDate = shell_exec('git log -1 --format="%at" -- ' . $file);
|
||||
if (basename($file) != 'en.json' && $fileModDate > $lastModDate) {
|
||||
$lastModDate = $fileModDate;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
if ($lastModDate != 0) {
|
||||
$arguments['--lastupdate'] = $lastModDate;
|
||||
}
|
||||
}
|
||||
$inputObject = new ArrayInput($arguments);
|
||||
$inputObject->setInteractive($input->isInteractive());
|
||||
$command->run($inputObject, $output);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user