update Piwik to version 2.16 (fixes #91)
This commit is contained in:
parent
296343bf3b
commit
d885a4baa9
5833 changed files with 418860 additions and 226988 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -9,16 +9,19 @@
|
|||
*/
|
||||
namespace Piwik\Plugins\LanguagesManager;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Db;
|
||||
use Piwik\Development;
|
||||
use Piwik\Filesystem;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Cache as PiwikCache;
|
||||
use Piwik\Plugin\Manager as PluginManager;
|
||||
use Piwik\Translation\Loader\DevelopmentLoader;
|
||||
|
||||
/**
|
||||
* The LanguagesManager API lets you access existing Piwik translations, and change Users languages preferences.
|
||||
*
|
||||
* "getTranslationsForLanguage" will return all translation strings for a given language,
|
||||
* so you can leverage Piwik translations in your application (and automatically benefit from the <a href='http://piwik.org/translations/' target='_blank'>40+ translations</a>!).
|
||||
* so you can leverage Piwik translations in your application (and automatically benefit from the <a href='http://piwik.org/translations/' rel='noreferrer' target='_blank'>40+ translations</a>!).
|
||||
* This is mostly useful to developers who integrate Piwik API results in their own application.
|
||||
*
|
||||
* You can also request the default language to load for a user via "getLanguageForUser",
|
||||
|
|
@ -47,7 +50,7 @@ class API extends \Piwik\Plugin\API
|
|||
/**
|
||||
* Return array of available languages
|
||||
*
|
||||
* @return array Arry of strings, each containing its ISO language code
|
||||
* @return array Array of strings, each containing its ISO language code
|
||||
*/
|
||||
public function getAvailableLanguages()
|
||||
{
|
||||
|
|
@ -65,6 +68,8 @@ class API extends \Piwik\Plugin\API
|
|||
}
|
||||
}
|
||||
|
||||
$this->enableDevelopmentLanguageInDevEnvironment($languages);
|
||||
|
||||
/**
|
||||
* Hook called after loading available language files.
|
||||
*
|
||||
|
|
@ -90,7 +95,7 @@ class API extends \Piwik\Plugin\API
|
|||
|
||||
// merge with plugin translations if any
|
||||
$pluginFiles = glob(sprintf('%s/plugins/*/lang/en.json', PIWIK_INCLUDE_PATH));
|
||||
foreach ($pluginFiles AS $file) {
|
||||
foreach ($pluginFiles as $file) {
|
||||
|
||||
$data = file_get_contents($file);
|
||||
$pluginTranslations = json_decode($data, true);
|
||||
|
|
@ -105,7 +110,7 @@ class API extends \Piwik\Plugin\API
|
|||
|
||||
// merge with plugin translations if any
|
||||
$pluginFiles = glob(sprintf('%s/plugins/*/lang/%s.json', PIWIK_INCLUDE_PATH, $filename));
|
||||
foreach ($pluginFiles AS $file) {
|
||||
foreach ($pluginFiles as $file) {
|
||||
|
||||
$data = file_get_contents($file);
|
||||
$pluginTranslations = json_decode($data, true);
|
||||
|
|
@ -123,14 +128,19 @@ class API extends \Piwik\Plugin\API
|
|||
}
|
||||
return $res;
|
||||
};
|
||||
|
||||
// Skip languages not having Intl translations
|
||||
if (empty($translations['Intl'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$translationStringsDone = $intersect($englishTranslation, $translations);
|
||||
$percentageComplete = count($translationStringsDone, COUNT_RECURSIVE) / count($englishTranslation, COUNT_RECURSIVE);
|
||||
$percentageComplete = round(100 * $percentageComplete, 0);
|
||||
$languageInfo = array('code' => $filename,
|
||||
'name' => $translations['General']['OriginalLanguageName'],
|
||||
'english_name' => $translations['General']['EnglishLanguageName'],
|
||||
'name' => $translations['Intl']['OriginalLanguageName'],
|
||||
'english_name' => $translations['Intl']['EnglishLanguageName'],
|
||||
'translators' => $translations['General']['TranslatorName'],
|
||||
'translators_email' => $translations['General']['TranslatorEmail'],
|
||||
'percentage_complete' => $percentageComplete . '%',
|
||||
);
|
||||
$languagesInfo[] = $languageInfo;
|
||||
|
|
@ -171,6 +181,17 @@ class API extends \Piwik\Plugin\API
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (PluginManager::getInstance()->getLoadedPluginsName() as $pluginName) {
|
||||
$translations = $this->getPluginTranslationsForLanguage($pluginName, $languageCode);
|
||||
|
||||
if (!empty($translations)) {
|
||||
foreach ($translations as $keys) {
|
||||
$languageInfo[] = $keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $languageInfo;
|
||||
}
|
||||
|
||||
|
|
@ -217,12 +238,20 @@ class API extends \Piwik\Plugin\API
|
|||
*/
|
||||
public function getLanguageForUser($login)
|
||||
{
|
||||
if($login == 'anonymous') {
|
||||
if ($login == 'anonymous') {
|
||||
return false;
|
||||
}
|
||||
|
||||
Piwik::checkUserHasSuperUserAccessOrIsTheUser($login);
|
||||
return Db::fetchOne('SELECT language FROM ' . Common::prefixTable('user_language') .
|
||||
' WHERE login = ? ', array($login));
|
||||
|
||||
$lang = $this->getModel()->getLanguageForUser($login);
|
||||
|
||||
return $lang;
|
||||
}
|
||||
|
||||
private function getModel()
|
||||
{
|
||||
return new Model();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -236,35 +265,98 @@ class API extends \Piwik\Plugin\API
|
|||
{
|
||||
Piwik::checkUserHasSuperUserAccessOrIsTheUser($login);
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
if (!$this->isLanguageAvailable($languageCode)) {
|
||||
return false;
|
||||
}
|
||||
$paramsBind = array($login, $languageCode, $languageCode);
|
||||
Db::query('INSERT INTO ' . Common::prefixTable('user_language') .
|
||||
' (login, language)
|
||||
VALUES (?,?)
|
||||
ON DUPLICATE KEY UPDATE language=?',
|
||||
$paramsBind);
|
||||
|
||||
$this->getModel()->setLanguageForUser($login, $languageCode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user uses 12 hour clock
|
||||
*
|
||||
* @param string $login
|
||||
* @return string
|
||||
*/
|
||||
public function uses12HourClockForUser($login)
|
||||
{
|
||||
if ($login == 'anonymous') {
|
||||
return false;
|
||||
}
|
||||
|
||||
Piwik::checkUserHasSuperUserAccessOrIsTheUser($login);
|
||||
|
||||
$lang = $this->getModel()->uses12HourClock($login);
|
||||
|
||||
return $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user uses 12 hour clock
|
||||
*
|
||||
* @param string $login
|
||||
* @param bool $use12HourClock
|
||||
* @return string
|
||||
*/
|
||||
public function set12HourClockForUser($login, $use12HourClock)
|
||||
{
|
||||
if ($login == 'anonymous') {
|
||||
return false;
|
||||
}
|
||||
|
||||
Piwik::checkUserHasSuperUserAccessOrIsTheUser($login);
|
||||
|
||||
$lang = $this->getModel()->set12HourClock($login, $use12HourClock);
|
||||
|
||||
return $lang;
|
||||
}
|
||||
|
||||
private function loadAvailableLanguages()
|
||||
{
|
||||
if (!is_null($this->availableLanguageNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$filenames = $this->getAvailableLanguages();
|
||||
$languagesInfo = array();
|
||||
foreach ($filenames as $filename) {
|
||||
$data = file_get_contents(PIWIK_INCLUDE_PATH . "/lang/$filename.json");
|
||||
$translations = json_decode($data, true);
|
||||
$languagesInfo[] = array(
|
||||
'code' => $filename,
|
||||
'name' => $translations['General']['OriginalLanguageName'],
|
||||
'english_name' => $translations['General']['EnglishLanguageName']
|
||||
);
|
||||
$cacheId = 'availableLanguages';
|
||||
$cache = PiwikCache::getEagerCache();
|
||||
|
||||
if ($cache->contains($cacheId)) {
|
||||
$languagesInfo = $cache->fetch($cacheId);
|
||||
} else {
|
||||
$languages = $this->getAvailableLanguages();
|
||||
$languagesInfo = array();
|
||||
foreach ($languages as $languageCode) {
|
||||
$data = @file_get_contents(PIWIK_INCLUDE_PATH . "/plugins/Intl/lang/$languageCode.json");
|
||||
|
||||
// Skip languages not having Intl translations
|
||||
if (empty($data)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$translations = json_decode($data, true);
|
||||
$languagesInfo[] = array(
|
||||
'code' => $languageCode,
|
||||
'name' => $translations['Intl']['OriginalLanguageName'],
|
||||
'english_name' => $translations['Intl']['EnglishLanguageName']
|
||||
);
|
||||
}
|
||||
|
||||
$cache->save($cacheId, $languagesInfo);
|
||||
}
|
||||
|
||||
$this->availableLanguageNames = $languagesInfo;
|
||||
}
|
||||
|
||||
private function enableDevelopmentLanguageInDevEnvironment(&$languages)
|
||||
{
|
||||
if (!Development::isEnabled()) {
|
||||
$key = array_search(DevelopmentLoader::LANGUAGE_ID, $languages);
|
||||
if ($key) {
|
||||
unset($languages[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -9,9 +9,7 @@
|
|||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugin\ConsoleCommand;
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Piwik\Plugins\LanguagesManager\Commands\Update;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
|
@ -19,14 +17,14 @@ use Symfony\Component\Console\Output\OutputInterface;
|
|||
|
||||
/**
|
||||
*/
|
||||
class CreatePull extends ConsoleCommand
|
||||
class CreatePull extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:createpull')
|
||||
->setDescription('Updates translation files')
|
||||
->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'oTrance username')
|
||||
->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'oTrance password')
|
||||
->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'Transifex username')
|
||||
->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Transifex password')
|
||||
->addOption('plugin', 'P', InputOption::VALUE_OPTIONAL, 'optional name of plugin to update translations for');
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +49,7 @@ class CreatePull extends ConsoleCommand
|
|||
chdir(PIWIK_DOCUMENT_ROOT);
|
||||
|
||||
shell_exec('
|
||||
git checkout master > /dev/null 2>&1
|
||||
git checkout -f master > /dev/null 2>&1
|
||||
git pull > /dev/null 2>&1
|
||||
git submodule init > /dev/null 2>&1
|
||||
git submodule update > /dev/null 2>&1
|
||||
|
|
@ -77,7 +75,7 @@ class CreatePull extends ConsoleCommand
|
|||
|
||||
// switch to branch and update it to latest master
|
||||
shell_exec('
|
||||
git checkout translationupdates > /dev/null 2>&1
|
||||
git checkout -f translationupdates > /dev/null 2>&1
|
||||
git merge master > /dev/null 2>&1
|
||||
git push origin translationupdates > /dev/null 2>&1
|
||||
');
|
||||
|
|
@ -97,7 +95,7 @@ class CreatePull extends ConsoleCommand
|
|||
shell_exec('git add lang/. > /dev/null 2>&1');
|
||||
|
||||
if (empty($plugin)) {
|
||||
foreach (Update::getPluginsInCore() AS $pluginName) {
|
||||
foreach (Update::getPluginsInCore() as $pluginName) {
|
||||
shell_exec(sprintf('git add plugins/%s/lang/. > /dev/null 2>&1', $pluginName));
|
||||
}
|
||||
}
|
||||
|
|
@ -115,7 +113,7 @@ class CreatePull extends ConsoleCommand
|
|||
|
||||
$stats = shell_exec('git diff --numstat HEAD');
|
||||
|
||||
preg_match_all('/([0-9]+)\t([0-9]+)\t[a-zA-Z\/]*lang\/([a-z]{2,3})\.json/', $stats, $lineChanges);
|
||||
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])) {
|
||||
|
|
@ -123,18 +121,19 @@ class CreatePull extends ConsoleCommand
|
|||
}
|
||||
|
||||
$linesSumByLang = array();
|
||||
for($i=0; $i<count($lineChanges[0]); $i++) {
|
||||
$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})\.json/', $changes, $modifiedFiles);
|
||||
preg_match_all('/A [a-zA-Z\/]*lang\/([a-z]{2,3})\.json/', $changes, $addedFiles);
|
||||
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) {
|
||||
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']);
|
||||
}
|
||||
|
|
@ -142,11 +141,11 @@ class CreatePull extends ConsoleCommand
|
|||
}
|
||||
|
||||
if (!empty($modifiedFiles[1])) {
|
||||
foreach ($modifiedFiles[1] AS $modifiedFile) {
|
||||
foreach ($modifiedFiles[1] as $modifiedFile) {
|
||||
$languageInfo = $this->getLanguageInfoByIsoCode($modifiedFile);
|
||||
$messages[$modifiedFile] = sprintf('- Updated %s (%s changes / %s translated)\n', $languageInfo['english_name'], $linesSumByLang[$modifiedFile], $languageInfo['percentage_complete']);
|
||||
}
|
||||
$languageCodesTouched = $modifiedFiles[1];
|
||||
$languageCodesTouched = array_merge($languageCodesTouched, $modifiedFiles[1]);
|
||||
}
|
||||
|
||||
$message = implode('', $messages);
|
||||
|
|
@ -160,7 +159,7 @@ class CreatePull extends ConsoleCommand
|
|||
implode(', ', $languageCodesTouched)
|
||||
);
|
||||
|
||||
shell_exec('git commit -m "language update ${pluginName} refs #3430"');
|
||||
shell_exec('git commit -m "language update ${pluginName}"');
|
||||
shell_exec('git push');
|
||||
shell_exec('git checkout master > /dev/null 2>&1');
|
||||
|
||||
|
|
@ -170,7 +169,7 @@ class CreatePull extends ConsoleCommand
|
|||
private function getLanguageInfoByIsoCode($isoCode)
|
||||
{
|
||||
$languages = API::getInstance()->getAvailableLanguagesInfo();
|
||||
foreach ($languages AS $languageInfo) {
|
||||
foreach ($languages as $languageInfo) {
|
||||
if ($languageInfo['code'] == $isoCode) {
|
||||
return $languageInfo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,172 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @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\ConsoleCommand;
|
||||
use Piwik\Unzip;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class FetchFromOTrance extends ConsoleCommand
|
||||
{
|
||||
const DOWNLOADPATH = 'tmp/oTrance';
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:fetch')
|
||||
->setDescription('Fetches translations files from oTrance to '.self::DOWNLOADPATH)
|
||||
->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'oTrance username')
|
||||
->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'oTrance password');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->writeln("Starting to fetch latest language pack");
|
||||
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
|
||||
$cookieFile = self::getDownloadPath() . DIRECTORY_SEPARATOR . 'cookie.txt';
|
||||
@unlink($cookieFile);
|
||||
|
||||
$username = $input->getOption('username');
|
||||
$password = $input->getOption('password');
|
||||
|
||||
while (!file_exists($cookieFile)) {
|
||||
if (empty($username)) {
|
||||
$username = $dialog->ask($output, 'What is your oTrance username? ');
|
||||
}
|
||||
|
||||
if (empty($password)) {
|
||||
$password = $dialog->askHiddenResponse($output, 'What is your oTrance password? ');
|
||||
}
|
||||
|
||||
// send login request to oTrance and save the login cookie
|
||||
$curl = curl_init('http://translations.piwik.org/public/index/login');
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, sprintf("user=%s&pass=%s&autologin=1", $username, $password));
|
||||
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookieFile);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_exec($curl);
|
||||
curl_close($curl);
|
||||
|
||||
if (strpos(file_get_contents($cookieFile), 'oTranCe_autologin') !== false) {
|
||||
break;
|
||||
}
|
||||
|
||||
$username = null;
|
||||
$password = null;
|
||||
@unlink($cookieFile);
|
||||
$output->writeln("Invalid oTrance credentials. Please try again...");
|
||||
}
|
||||
|
||||
// send request to create a new download package using the cookie file
|
||||
$createNewPackage = true;
|
||||
if ($input->isInteractive()) {
|
||||
$createNewPackage = $dialog->askConfirmation($output, 'Shall we create a new language pack? ');
|
||||
}
|
||||
|
||||
if ($createNewPackage) {
|
||||
|
||||
$curl = curl_init('http://translations.piwik.org/public/export/update.all');
|
||||
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookieFile);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_exec($curl);
|
||||
curl_close($curl);
|
||||
}
|
||||
|
||||
// request download page to search for available packages
|
||||
$curl = curl_init('http://translations.piwik.org/public/downloads/');
|
||||
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookieFile);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
|
||||
preg_match_all('/language\_pack\-[0-9]{8}\-[0-9]{6}\.tar\.gz/i', $response, $matches);
|
||||
|
||||
if (empty($matches[0])) {
|
||||
|
||||
$output->writeln("No packages found for download. Please try again.");
|
||||
return;
|
||||
}
|
||||
|
||||
$downloadPackage = array_shift($matches[0]);
|
||||
|
||||
$continueWithPackage = true;
|
||||
if ($input->isInteractive()) {
|
||||
$continueWithPackage = $dialog->askConfirmation($output, "Found language pack $downloadPackage. Proceed? ");
|
||||
}
|
||||
|
||||
if (!$continueWithPackage) {
|
||||
|
||||
$output->writeln('Aborted.');
|
||||
return;
|
||||
}
|
||||
|
||||
// download language pack
|
||||
$packageHandle = fopen(self::getDownloadPath() . DIRECTORY_SEPARATOR . 'language_pack.tar.gz', 'w');
|
||||
$curl = curl_init('http://translations.piwik.org/public/downloads/download/file/'.$downloadPackage);
|
||||
curl_setopt($curl, CURLOPT_COOKIEFILE, self::getDownloadPath() . DIRECTORY_SEPARATOR . 'cookie.txt');
|
||||
curl_setopt($curl, CURLOPT_FILE, $packageHandle);
|
||||
curl_exec($curl);
|
||||
curl_close($curl);
|
||||
|
||||
@unlink($cookieFile);
|
||||
|
||||
$output->writeln("Extracting package...");
|
||||
|
||||
$unzipper = Unzip::factory('tar.gz', self::getDownloadPath() . DIRECTORY_SEPARATOR . 'language_pack.tar.gz');
|
||||
$unzipper->extract(self::getDownloadPath());
|
||||
|
||||
@unlink(self::getDownloadPath() . DIRECTORY_SEPARATOR . 'en.php');
|
||||
@unlink(self::getDownloadPath() . DIRECTORY_SEPARATOR . 'language_pack.tar.gz');
|
||||
|
||||
$filesToConvert = _glob(self::getDownloadPath() . DIRECTORY_SEPARATOR . '*.php');
|
||||
|
||||
$output->writeln("Converting downloaded php files to json");
|
||||
|
||||
$progress = $this->getHelperSet()->get('progress');
|
||||
|
||||
$progress->start($output, count($filesToConvert));
|
||||
foreach ($filesToConvert AS $filename) {
|
||||
|
||||
require_once $filename;
|
||||
$basename = explode(".", basename($filename));
|
||||
$nested = array();
|
||||
foreach ($translations as $key => $value) {
|
||||
list($plugin, $nkey) = explode("_", $key, 2);
|
||||
$nested[$plugin][$nkey] = $value;
|
||||
}
|
||||
$translations = $nested;
|
||||
$data = json_encode($translations, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
$newFile = sprintf("%s/%s.json", self::getDownloadPath(), $basename[0]);
|
||||
file_put_contents($newFile, $data);
|
||||
@unlink($filename);
|
||||
|
||||
$progress->advance();
|
||||
}
|
||||
|
||||
$progress->finish();
|
||||
|
||||
$output->writeln("Finished fetching new language files from oTrance");
|
||||
}
|
||||
|
||||
public static function getDownloadPath() {
|
||||
|
||||
$path = PIWIK_DOCUMENT_ROOT . DIRECTORY_SEPARATOR . self::DOWNLOADPATH;
|
||||
|
||||
if (!is_dir($path)) {
|
||||
mkdir($path);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?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\ProgressHelper;
|
||||
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('plugin', 'r', InputOption::VALUE_OPTIONAL, 'Plugin to update');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$username = $input->getOption('username');
|
||||
$password = $input->getOption('password');
|
||||
$plugin = $input->getOption('plugin');
|
||||
$lastUpdate = $input->getOption('lastupdate');
|
||||
|
||||
$resource = 'piwik-'. ($plugin ? 'plugin-'.strtolower($plugin) : 'base');
|
||||
|
||||
$transifexApi = new API($username, $password);
|
||||
|
||||
// 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 ProgressHelper $progress */
|
||||
$progress = $this->getHelperSet()->get('progress');
|
||||
|
||||
$progress->start($output, count($languages));
|
||||
|
||||
$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();
|
||||
}
|
||||
|
||||
public static function getDownloadPath()
|
||||
{
|
||||
$path = StaticContainer::get('path.tmp') . self::DOWNLOAD_PATH;
|
||||
|
||||
if (!is_dir($path)) {
|
||||
mkdir($path);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -9,14 +9,13 @@
|
|||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugin\ConsoleCommand;
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class LanguageCodes extends ConsoleCommand
|
||||
class LanguageCodes extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
|
|
@ -29,7 +28,7 @@ class LanguageCodes extends ConsoleCommand
|
|||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageCodes = array();
|
||||
foreach ($languages AS $languageInfo) {
|
||||
foreach ($languages as $languageInfo) {
|
||||
$languageCodes[] = $languageInfo['code'];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -9,14 +9,13 @@
|
|||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugin\ConsoleCommand;
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class LanguageNames extends ConsoleCommand
|
||||
class LanguageNames extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
|
|
@ -29,7 +28,7 @@ class LanguageNames extends ConsoleCommand
|
|||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageNames = array();
|
||||
foreach ($languages AS $languageInfo) {
|
||||
foreach ($languages as $languageInfo) {
|
||||
$languageNames[] = $languageInfo['english_name'];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -9,15 +9,12 @@
|
|||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugin\ConsoleCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class PluginsWithTranslations extends ConsoleCommand
|
||||
class PluginsWithTranslations extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -9,23 +9,21 @@
|
|||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugin\ConsoleCommand;
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Piwik\Translate\Filter\ByBaseTranslations;
|
||||
use Piwik\Translate\Filter\ByParameterCount;
|
||||
use Piwik\Translate\Filter\EmptyTranslations;
|
||||
use Piwik\Translate\Filter\EncodedEntities;
|
||||
use Piwik\Translate\Filter\UnnecassaryWhitespaces;
|
||||
use Piwik\Translate\Validate\CoreTranslations;
|
||||
use Piwik\Translate\Validate\NoScripts;
|
||||
use Piwik\Translate\Writer;
|
||||
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 ConsoleCommand
|
||||
class SetTranslations extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
|
|
@ -38,6 +36,7 @@ class SetTranslations extends ConsoleCommand
|
|||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
/** @var DialogHelper $dialog */
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
|
||||
$languageCode = $input->getOption('code');
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -9,8 +9,9 @@
|
|||
|
||||
namespace Piwik\Plugins\LanguagesManager\Commands;
|
||||
|
||||
use Piwik\Plugin\ConsoleCommand;
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Helper\DialogHelper;
|
||||
use Symfony\Component\Console\Helper\ProgressHelper;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
|
@ -19,112 +20,108 @@ use Symfony\Component\Console\Output\OutputInterface;
|
|||
|
||||
/**
|
||||
*/
|
||||
class Update extends ConsoleCommand
|
||||
class Update extends TranslationBase
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:update')
|
||||
->setDescription('Updates translation files')
|
||||
->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'oTrance username')
|
||||
->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'oTrance password')
|
||||
->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('plugin', 'P', InputOption::VALUE_OPTIONAL, 'optional name of plugin to update translations for');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
$start = microtime(true);
|
||||
|
||||
$command = $this->getApplication()->find('translations:fetch');
|
||||
$arguments = array(
|
||||
'command' => 'translations:fetch',
|
||||
'--username' => $input->getOption('username'),
|
||||
'--password' => $input->getOption('password')
|
||||
);
|
||||
$inputObject = new ArrayInput($arguments);
|
||||
$inputObject->setInteractive($input->isInteractive());
|
||||
$command->run($inputObject, $output);
|
||||
/** @var DialogHelper $dialog */
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
|
||||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageCodes = array();
|
||||
foreach ($languages AS $languageInfo) {
|
||||
foreach ($languages as $languageInfo) {
|
||||
$languageCodes[] = $languageInfo['code'];
|
||||
}
|
||||
|
||||
$plugin = $input->getOption('plugin');
|
||||
|
||||
$files = _glob(FetchFromOTrance::getDownloadPath() . DIRECTORY_SEPARATOR . '*.json');
|
||||
|
||||
$output->writeln("Starting to import new language files");
|
||||
|
||||
if (!$input->isInteractive()) {
|
||||
$output->writeln("(!) Non interactive mode: New languages will be skipped");
|
||||
}
|
||||
|
||||
$progress = $this->getHelperSet()->get('progress');
|
||||
|
||||
$progress->start($output, count($files));
|
||||
|
||||
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::unsetInstance(); // unset language manager instance, so valid names are refetched
|
||||
}
|
||||
|
||||
$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, new NullOutput());
|
||||
|
||||
// update core modules that aren't in their own repo
|
||||
if (empty($plugin)) {
|
||||
|
||||
foreach (self::getPluginsInCore() AS $pluginName) {
|
||||
|
||||
// update translation files
|
||||
$command = $this->getApplication()->find('translations:set');
|
||||
$arguments = array(
|
||||
'command' => 'translations:set',
|
||||
'--code' => $code,
|
||||
'--file' => $filename,
|
||||
'--plugin' => $pluginName
|
||||
);
|
||||
$inputObject = new ArrayInput($arguments);
|
||||
$inputObject->setInteractive($input->isInteractive());
|
||||
$command->run($inputObject, new NullOutput());
|
||||
}
|
||||
}
|
||||
$pluginList = array($plugin);
|
||||
if (empty($plugin)) {
|
||||
$pluginList = self::getPluginsInCore();
|
||||
array_unshift($pluginList, '');
|
||||
} else {
|
||||
$input->setOption('force', true); // force plugin only updates
|
||||
}
|
||||
|
||||
$progress->finish();
|
||||
$output->writeln("Finished.");
|
||||
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 ProgressHelper $progress */
|
||||
$progress = $this->getHelperSet()->get('progress');
|
||||
|
||||
$progress->start($output, count($files));
|
||||
|
||||
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::unsetInstance(); // unset language manager instance, so valid names are refetched
|
||||
}
|
||||
|
||||
$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, new NullOutput());
|
||||
}
|
||||
|
||||
$progress->finish();
|
||||
}
|
||||
|
||||
$output->writeln("Finished in " . round(microtime(true)-$start, 3) . "s");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -151,7 +148,7 @@ class Update extends ConsoleCommand
|
|||
$pluginsNotInCore = array_merge($submodulePlugins, $newPlugins);
|
||||
|
||||
$pluginsWithTranslations = glob(sprintf('%s/plugins/*/lang/en.json', PIWIK_INCLUDE_PATH));
|
||||
$pluginsWithTranslations = array_map(function($elem){
|
||||
$pluginsWithTranslations = array_map(function ($elem) {
|
||||
return str_replace(array(sprintf('%s/plugins/', PIWIK_INCLUDE_PATH), '/lang/en.json'), '', $elem);
|
||||
}, $pluginsWithTranslations);
|
||||
|
||||
|
|
@ -159,4 +156,48 @@ class Update extends ConsoleCommand
|
|||
|
||||
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'),
|
||||
'--plugin' => $plugin
|
||||
);
|
||||
|
||||
if ($input->getOption('force')) {
|
||||
$arguments['--lastupdate'] = 1;
|
||||
} else {
|
||||
$lastModDate = strtotime('2015-01-04 00:00:00'); // date of inital 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -13,10 +13,11 @@ use Piwik\Common;
|
|||
use Piwik\DbHelper;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Url;
|
||||
use Piwik\View;
|
||||
|
||||
/**
|
||||
*/
|
||||
class Controller extends \Piwik\Plugin\Controller
|
||||
class Controller extends \Piwik\Plugin\ControllerAdmin
|
||||
{
|
||||
/**
|
||||
* anonymous = in the session
|
||||
|
|
@ -34,4 +35,11 @@ class Controller extends \Piwik\Plugin\Controller
|
|||
LanguagesManager::setLanguageForSession($language);
|
||||
Url::redirectToReferrer();
|
||||
}
|
||||
|
||||
public function searchTranslation()
|
||||
{
|
||||
Piwik::checkUserHasSomeAdminAccess();
|
||||
|
||||
return $this->renderTemplate('searchTranslation');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -10,15 +10,16 @@
|
|||
namespace Piwik\Plugins\LanguagesManager;
|
||||
|
||||
use Exception;
|
||||
use Piwik\API\Request;
|
||||
use Piwik\Common;
|
||||
use Piwik\Config;
|
||||
|
||||
use Piwik\Container\StaticContainer;
|
||||
use Piwik\Cookie;
|
||||
use Piwik\Db;
|
||||
use Piwik\DbHelper;
|
||||
use Piwik\Menu\MenuTop;
|
||||
use Piwik\Intl\Locale;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Translate;
|
||||
use Piwik\Translation\Translator;
|
||||
use Piwik\View;
|
||||
|
||||
/**
|
||||
|
|
@ -27,36 +28,33 @@ use Piwik\View;
|
|||
class LanguagesManager extends \Piwik\Plugin
|
||||
{
|
||||
/**
|
||||
* @see Piwik\Plugin::getListHooksRegistered
|
||||
* @see Piwik\Plugin::registerEvents
|
||||
*/
|
||||
public function getListHooksRegistered()
|
||||
public function registerEvents()
|
||||
{
|
||||
return array(
|
||||
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
|
||||
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
|
||||
'Menu.Top.addItems' => 'showLanguagesSelector',
|
||||
'User.getLanguage' => 'getLanguageToLoad',
|
||||
'UsersManager.deleteUser' => 'deleteUserLanguage',
|
||||
'Template.topBar' => 'addLanguagesManagerToOtherTopBar',
|
||||
'Template.jsGlobalVariables' => 'jsGlobalVariables'
|
||||
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
|
||||
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
|
||||
'Config.NoConfigurationFile' => 'initLanguage',
|
||||
'Request.dispatchCoreAndPluginUpdatesScreen' => 'initLanguage',
|
||||
'Request.dispatch' => 'initLanguage',
|
||||
'Platform.initialized' => 'initLanguage',
|
||||
'UsersManager.deleteUser' => 'deleteUserLanguage',
|
||||
'Template.topBar' => 'addLanguagesManagerToOtherTopBar',
|
||||
'Template.jsGlobalVariables' => 'jsGlobalVariables'
|
||||
);
|
||||
}
|
||||
|
||||
public function getStylesheetFiles(&$stylesheets)
|
||||
{
|
||||
$stylesheets[] = "plugins/Zeitgeist/stylesheets/base.less";
|
||||
$stylesheets[] = "plugins/Morpheus/stylesheets/base.less";
|
||||
}
|
||||
|
||||
public function getJsFiles(&$jsFiles)
|
||||
{
|
||||
$jsFiles[] = "plugins/LanguagesManager/javascripts/languageSelector.js";
|
||||
}
|
||||
|
||||
public function showLanguagesSelector()
|
||||
{
|
||||
if (Piwik::isUserIsAnonymous() || !DbHelper::isInstalled()) {
|
||||
MenuTop::addEntry('LanguageSelector', $this->getLanguagesSelector(), true, $order = 30, true);
|
||||
}
|
||||
$jsFiles[] = "plugins/LanguagesManager/angularjs/languageselector/languageselector.directive.js";
|
||||
$jsFiles[] = "plugins/LanguagesManager/angularjs/translationsearch/translationsearch.controller.js";
|
||||
$jsFiles[] = "plugins/LanguagesManager/angularjs/translationsearch/translationsearch.directive.js";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -68,7 +66,8 @@ class LanguagesManager extends \Piwik\Plugin
|
|||
{
|
||||
// piwik object & scripts aren't loaded in 'other' topbars
|
||||
$str .= "<script type='text/javascript'>if (!window.piwik) window.piwik={};</script>";
|
||||
$str .= "<script type='text/javascript' src='plugins/LanguagesManager/javascripts/languageSelector.js'></script>";
|
||||
$str .= "<script type='text/javascript' src='plugins/CoreHome/angularjs/menudropdown/menudropdown.directive.js'></script>";
|
||||
$str .= "<script type='text/javascript' src='plugins/LanguagesManager/angularjs/languageselector/languageselector.directive.js'></script>";
|
||||
$str .= $this->getLanguagesSelector();
|
||||
}
|
||||
|
||||
|
|
@ -88,27 +87,39 @@ class LanguagesManager extends \Piwik\Plugin
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getLanguagesSelector()
|
||||
public function getLanguagesSelector()
|
||||
{
|
||||
$view = new View("@LanguagesManager/getLanguagesSelector");
|
||||
$view->languages = API::getInstance()->getAvailableLanguageNames();
|
||||
$view->currentLanguageCode = self::getLanguageCodeForCurrentUser();
|
||||
$view->currentLanguageName = self::getLanguageNameForCurrentUser();
|
||||
return $view->render();
|
||||
}
|
||||
|
||||
function getLanguageToLoad(&$language)
|
||||
public function initLanguage()
|
||||
{
|
||||
/** @var Translator $translator */
|
||||
$translator = StaticContainer::get('Piwik\Translation\Translator');
|
||||
|
||||
$language = Common::getRequestVar('language', '', 'string');
|
||||
if (empty($language)) {
|
||||
$language = self::getLanguageCodeForCurrentUser();
|
||||
$userLanguage = self::getLanguageCodeForCurrentUser();
|
||||
if (API::getInstance()->isLanguageAvailable($userLanguage)) {
|
||||
$language = $userLanguage;
|
||||
}
|
||||
}
|
||||
if (!API::getInstance()->isLanguageAvailable($language)) {
|
||||
$language = Translate::getLanguageDefault();
|
||||
if (!empty($language) && API::getInstance()->isLanguageAvailable($language)) {
|
||||
$translator->setCurrentLanguage($language);
|
||||
}
|
||||
|
||||
$locale = $translator->translate('General_Locale');
|
||||
Locale::setLocale($locale);
|
||||
}
|
||||
|
||||
public function deleteUserLanguage($userLogin)
|
||||
{
|
||||
Db::query('DELETE FROM ' . Common::prefixTable('user_language') . ' WHERE login = ?', $userLogin);
|
||||
$model = new Model();
|
||||
$model->deleteUserLanguage($userLogin);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -116,10 +127,7 @@ class LanguagesManager extends \Piwik\Plugin
|
|||
*/
|
||||
public function install()
|
||||
{
|
||||
$userLanguage = "login VARCHAR( 100 ) NOT NULL ,
|
||||
language VARCHAR( 10 ) NOT NULL ,
|
||||
PRIMARY KEY ( login )";
|
||||
DbHelper::createTable('user_language', $userLanguage);
|
||||
Model::install();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -127,13 +135,26 @@ class LanguagesManager extends \Piwik\Plugin
|
|||
*/
|
||||
public function uninstall()
|
||||
{
|
||||
Db::dropTables(Common::prefixTable('user_language'));
|
||||
Model::uninstall();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public static function uses12HourClockForCurrentUser()
|
||||
{
|
||||
try {
|
||||
$currentUser = Piwik::getCurrentUserLogin();
|
||||
return Request::processRequest('LanguagesManager.uses12HourClockForUser', array('login' => $currentUser));
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Two letters language code, eg. "fr"
|
||||
*/
|
||||
static public function getLanguageCodeForCurrentUser()
|
||||
public static function getLanguageCodeForCurrentUser()
|
||||
{
|
||||
$languageCode = self::getLanguageFromPreferences();
|
||||
if (!API::getInstance()->isLanguageAvailable($languageCode)) {
|
||||
|
|
@ -148,7 +169,7 @@ class LanguagesManager extends \Piwik\Plugin
|
|||
/**
|
||||
* @return string Full english language string, eg. "French"
|
||||
*/
|
||||
static public function getLanguageNameForCurrentUser()
|
||||
public static function getLanguageNameForCurrentUser()
|
||||
{
|
||||
$languageCode = self::getLanguageCodeForCurrentUser();
|
||||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
|
@ -163,7 +184,7 @@ class LanguagesManager extends \Piwik\Plugin
|
|||
/**
|
||||
* @return string|false if language preference could not be loaded
|
||||
*/
|
||||
static protected function getLanguageFromPreferences()
|
||||
protected static function getLanguageFromPreferences()
|
||||
{
|
||||
if (($language = self::getLanguageForSession()) != null) {
|
||||
return $language;
|
||||
|
|
@ -182,7 +203,7 @@ class LanguagesManager extends \Piwik\Plugin
|
|||
*
|
||||
* @return string|null
|
||||
*/
|
||||
static public function getLanguageForSession()
|
||||
public static function getLanguageForSession()
|
||||
{
|
||||
$cookieName = Config::getInstance()->General['language_cookie_name'];
|
||||
$cookie = new Cookie($cookieName);
|
||||
|
|
@ -198,7 +219,7 @@ class LanguagesManager extends \Piwik\Plugin
|
|||
* @param string $languageCode ISO language code
|
||||
* @return bool
|
||||
*/
|
||||
static public function setLanguageForSession($languageCode)
|
||||
public static function setLanguageForSession($languageCode)
|
||||
{
|
||||
if (!API::getInstance()->isLanguageAvailable($languageCode)) {
|
||||
return false;
|
||||
|
|
|
|||
34
www/analytics/plugins/LanguagesManager/Menu.php
Normal file
34
www/analytics/plugins/LanguagesManager/Menu.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?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;
|
||||
|
||||
use Piwik\Development;
|
||||
use Piwik\Menu\MenuAdmin;
|
||||
use Piwik\Menu\MenuTop;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\SettingsPiwik;
|
||||
|
||||
class Menu extends \Piwik\Plugin\Menu
|
||||
{
|
||||
public function configureTopMenu(MenuTop $menu)
|
||||
{
|
||||
if (Piwik::isUserIsAnonymous() || !SettingsPiwik::isPiwikInstalled()) {
|
||||
$langManager = new LanguagesManager();
|
||||
$menu->addHtml('LanguageSelector', $langManager->getLanguagesSelector(), true, $order = 30, false);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureAdminMenu(MenuAdmin $menu)
|
||||
{
|
||||
if (Development::isEnabled() && Piwik::isUserHasSomeAdminAccess()) {
|
||||
$menu->addDevelopmentItem('LanguagesManager_TranslationSearch',
|
||||
$this->urlForAction('searchTranslation'));
|
||||
}
|
||||
}
|
||||
}
|
||||
103
www/analytics/plugins/LanguagesManager/Model.php
Normal file
103
www/analytics/plugins/LanguagesManager/Model.php
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<?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;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Db;
|
||||
use Piwik\DbHelper;
|
||||
|
||||
class Model
|
||||
{
|
||||
private static $rawPrefix = 'user_language';
|
||||
private $table;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->table = Common::prefixTable(self::$rawPrefix);
|
||||
}
|
||||
|
||||
public function deleteUserLanguage($userLogin)
|
||||
{
|
||||
Db::query('DELETE FROM ' . $this->table . ' WHERE login = ?', $userLogin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the language for the user
|
||||
*
|
||||
* @param string $userLogin
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguageForUser($userLogin)
|
||||
{
|
||||
return Db::fetchOne('SELECT language FROM ' . $this->table .
|
||||
' WHERE login = ? ', array($userLogin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the language for the user
|
||||
*
|
||||
* @param string $login
|
||||
* @param string $languageCode
|
||||
* @return bool
|
||||
*/
|
||||
public function setLanguageForUser($login, $languageCode)
|
||||
{
|
||||
$query = 'INSERT INTO ' . $this->table .
|
||||
' (login, language) VALUES (?,?) ON DUPLICATE KEY UPDATE language=?';
|
||||
$bind = array($login, $languageCode, $languageCode);
|
||||
Db::query($query, $bind);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given user has choosen to use 12 hour clock
|
||||
*
|
||||
* @param $userLogin
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function uses12HourClock($userLogin)
|
||||
{
|
||||
return (bool) Db::fetchOne('SELECT use_12_hour_clock FROM ' . $this->table .
|
||||
' WHERE login = ? ', array($userLogin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the given user wants to use 12 hout clock
|
||||
*
|
||||
* @param string $login
|
||||
* @param string $use12HourClock
|
||||
* @return bool
|
||||
*/
|
||||
public function set12HourClock($login, $use12HourClock)
|
||||
{
|
||||
$query = 'INSERT INTO ' . $this->table .
|
||||
' (login, use_12_hour_clock) VALUES (?,?) ON DUPLICATE KEY UPDATE use_12_hour_clock=?';
|
||||
$bind = array($login, $use12HourClock, $use12HourClock);
|
||||
Db::query($query, $bind);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function install()
|
||||
{
|
||||
$userLanguage = "login VARCHAR( 100 ) NOT NULL ,
|
||||
language VARCHAR( 10 ) NOT NULL ,
|
||||
use_12_hour_clock TINYINT(1) NOT NULL DEFAULT 0 ,
|
||||
PRIMARY KEY ( login )";
|
||||
DbHelper::createTable(self::$rawPrefix, $userLanguage);
|
||||
}
|
||||
|
||||
public static function uninstall()
|
||||
{
|
||||
Db::dropTables(Common::prefixTable(self::$rawPrefix));
|
||||
}
|
||||
}
|
||||
187
www/analytics/plugins/LanguagesManager/Test/Integration/LanguagesManagerTest.php
Executable file
187
www/analytics/plugins/LanguagesManager/Test/Integration/LanguagesManagerTest.php
Executable file
|
|
@ -0,0 +1,187 @@
|
|||
<?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\Test\Integration;
|
||||
|
||||
use Piwik\Container\StaticContainer;
|
||||
use Piwik\Intl\Data\Provider\LanguageDataProvider;
|
||||
use Piwik\Plugins\LanguagesManager\API;
|
||||
use \Exception;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
*/
|
||||
class LanguagesManagerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
function getTestDataForLanguageFiles()
|
||||
{
|
||||
// we also test that none of the language php files outputs any character on the screen (eg. space before the <?php)
|
||||
$languages = API::getInstance()->getAvailableLanguages();
|
||||
|
||||
$plugins = \Piwik\Plugin\Manager::getInstance()->readPluginsDirectory();
|
||||
|
||||
$pluginsWithTranslation = array();
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
|
||||
if (API::getInstance()->getPluginTranslationsForLanguage($plugin, 'en')) {
|
||||
|
||||
$pluginsWithTranslation[] = $plugin;
|
||||
}
|
||||
}
|
||||
|
||||
$return = array();
|
||||
foreach ($languages as $language) {
|
||||
if ($language != 'en') {
|
||||
$return[] = array($language, null);
|
||||
|
||||
foreach ($pluginsWithTranslation as $plugin) {
|
||||
|
||||
$return[] = array($language, $plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* test all languages
|
||||
*
|
||||
* @group Plugins
|
||||
*
|
||||
* @dataProvider getTestDataForLanguageFiles
|
||||
*/
|
||||
function testGetTranslationsForLanguages($language, $plugin)
|
||||
{
|
||||
$translationWriter = new Writer($language, $plugin);
|
||||
|
||||
$baseTranslations = $translationWriter->getTranslations('en');
|
||||
|
||||
$translationWriter->addValidator(new NoScripts());
|
||||
if (empty($plugin)) {
|
||||
$translationWriter->addValidator(new CoreTranslations($baseTranslations));
|
||||
}
|
||||
|
||||
// prevent build from failing when translations string have been deleted
|
||||
// $translationWriter->addFilter(new ByBaseTranslations($baseTranslations));
|
||||
$translationWriter->addFilter(new EmptyTranslations());
|
||||
$translationWriter->addFilter(new ByParameterCount($baseTranslations));
|
||||
$translationWriter->addFilter(new UnnecassaryWhitespaces($baseTranslations));
|
||||
$translationWriter->addFilter(new EncodedEntities());
|
||||
|
||||
$translations = $translationWriter->getTranslations($language);
|
||||
|
||||
if (empty($translations)) {
|
||||
return; // skip language / plugin combinations that aren't present
|
||||
}
|
||||
|
||||
$translationWriter->setTranslations($translations);
|
||||
|
||||
$this->assertTrue($translationWriter->isValid(), $translationWriter->getValidationMessage());
|
||||
|
||||
if ($translationWriter->wasFiltered()) {
|
||||
|
||||
$translationWriter->saveTemporary();
|
||||
$this->markTestSkipped(implode("\n", $translationWriter->getFilterMessages()) . "\n"
|
||||
. 'Translation file errors detected in ' . $language . "...\n"
|
||||
. "To synchronise the language files with the english strings, you can manually edit the language files or run the following command may work if you have access to Transifex: \n"
|
||||
. "$ ./console translations:update [--plugin=XYZ] \n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* test language when it's not defined
|
||||
*
|
||||
* @group Plugins
|
||||
*
|
||||
* @expectedException Exception
|
||||
*/
|
||||
function testWriterInvalidPlugin()
|
||||
{
|
||||
new Writer('de', 'iNvaLiDPluGin'); // invalid plugin throws exception
|
||||
}
|
||||
|
||||
/**
|
||||
* test language when it's not defined
|
||||
*
|
||||
* @group Plugins
|
||||
*/
|
||||
function testGetTranslationsForLanguagesNot()
|
||||
{
|
||||
$this->assertFalse(API::getInstance()->getTranslationsForLanguage("../no-language"));
|
||||
}
|
||||
|
||||
/**
|
||||
* test English short name for language
|
||||
*
|
||||
* @group Plugins
|
||||
*/
|
||||
function testGetLanguageNamesInEnglish()
|
||||
{
|
||||
$languages = API::getInstance()->getAvailableLanguages();
|
||||
|
||||
/** @var LanguageDataProvider $dataProvider */
|
||||
$dataProvider = StaticContainer::get('Piwik\Intl\Data\Provider\LanguageDataProvider');
|
||||
$languagesReference = $dataProvider->getLanguageList();
|
||||
|
||||
foreach ($languages as $language) {
|
||||
$data = file_get_contents(PIWIK_INCLUDE_PATH . "/plugins/Intl/lang/$language.json");
|
||||
$translations = json_decode($data, true);
|
||||
$name = $translations['Intl']['EnglishLanguageName'];
|
||||
|
||||
if ($language != 'en') {
|
||||
$this->assertFalse($name == 'English', "for $language");
|
||||
}
|
||||
|
||||
$languageCode = substr($language, 0, 2);
|
||||
$this->assertTrue(isset($languagesReference[$languageCode]));
|
||||
$names = $languagesReference[$languageCode];
|
||||
|
||||
if (isset($languagesReference[$language])) {
|
||||
if (is_array($names)) {
|
||||
$this->assertTrue(in_array($name, $names), "$language: failed because $name not a known language name");
|
||||
} else {
|
||||
$this->assertTrue($name == $names, "$language: failed because $name == $names");
|
||||
}
|
||||
} else {
|
||||
if (is_array($names)) {
|
||||
$this->assertTrue(strpos($name, $names[0]) !== false);
|
||||
} else {
|
||||
$this->fail("$language: expected an array of language names");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* test format of DataFile/Languages.php
|
||||
*
|
||||
* @group Plugins
|
||||
*/
|
||||
public function testGetLanguagesList()
|
||||
{
|
||||
/** @var LanguageDataProvider $languageDataProvider */
|
||||
$languageDataProvider = StaticContainer::get('Piwik\Intl\Data\Provider\LanguageDataProvider');
|
||||
|
||||
$languages = $languageDataProvider->getLanguageList();
|
||||
$this->assertTrue(count($languages) > 0);
|
||||
foreach ($languages as $langCode => $langs) {
|
||||
$this->assertTrue(strlen($langCode) == 2, "$langCode length = 2");
|
||||
$this->assertTrue(is_array($langs) && count($langs) >= 1, "$langCode array(names) >= 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
<?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\tests\Integration;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Db;
|
||||
use Piwik\Plugins\LanguagesManager\Model;
|
||||
use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
* @group ModelTest
|
||||
* @group Plugins
|
||||
*/
|
||||
class ModelTest extends IntegrationTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Model
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->model = new Model();
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function test_install_ShouldNotFailAndActuallyCreateTheDatabases()
|
||||
{
|
||||
$this->assertContainTables(array('user_language'));
|
||||
|
||||
$columns = Db::fetchAll('show columns from ' . Common::prefixTable('user_language'));
|
||||
$this->assertCount(3, $columns);
|
||||
}
|
||||
|
||||
public function test_uninstall_ShouldNotFailAndRemovesAllAlertTables()
|
||||
{
|
||||
Model::uninstall();
|
||||
|
||||
$this->assertNotContainTables(array('user_language'));
|
||||
|
||||
Model::install();
|
||||
}
|
||||
|
||||
public function test_handlesUserLanguageEntriesCorrectly()
|
||||
{
|
||||
$this->model->setLanguageForUser('admin', 'de');
|
||||
|
||||
$this->assertTableEntryCount(1);
|
||||
|
||||
$this->assertEquals('de', $this->model->getLanguageForUser('admin'));
|
||||
|
||||
$this->model->deleteUserLanguage('admin');
|
||||
|
||||
$this->assertTableEntryCount(0);
|
||||
}
|
||||
|
||||
public function test_handlesUserTimeFormatEntriesCorrectly()
|
||||
{
|
||||
$this->model->set12HourClock('admin', false);
|
||||
|
||||
$this->assertTableEntryCount(1);
|
||||
|
||||
$this->assertEquals(false, $this->model->uses12HourClock('admin'));
|
||||
|
||||
$this->model->deleteUserLanguage('admin');
|
||||
|
||||
$this->assertTableEntryCount(0);
|
||||
}
|
||||
|
||||
public function test_handlesUserLanguageAndTimeFormatEntriesCorrectly()
|
||||
{
|
||||
$this->model->setLanguageForUser('admin', 'de');
|
||||
|
||||
$this->assertTableEntryCount(1);
|
||||
|
||||
$this->model->set12HourClock('admin', false);
|
||||
$this->model->set12HourClock('user', true);
|
||||
|
||||
$this->assertTableEntryCount(2);
|
||||
|
||||
$this->assertEquals('de', $this->model->getLanguageForUser('admin'));
|
||||
$this->assertEquals('', $this->model->getLanguageForUser('user'));
|
||||
$this->assertEquals(false, $this->model->uses12HourClock('admin'));
|
||||
$this->assertEquals(true, $this->model->uses12HourClock('user'));
|
||||
|
||||
$this->model->deleteUserLanguage('admin');
|
||||
|
||||
$this->assertTableEntryCount(1);
|
||||
}
|
||||
|
||||
private function assertTableEntryCount($count)
|
||||
{
|
||||
$entryCount = Db::fetchOne('SELECT COUNT(*) FROM ' . Common::prefixTable('user_language'));
|
||||
|
||||
$this->assertEquals($count, $entryCount);
|
||||
|
||||
}
|
||||
|
||||
private function assertContainTables($expectedTables)
|
||||
{
|
||||
$tableNames = $this->getCurrentAvailableTableNames();
|
||||
|
||||
foreach ($expectedTables as $expectedTable) {
|
||||
$this->assertContains(Common::prefixTable($expectedTable), $tableNames);
|
||||
}
|
||||
}
|
||||
|
||||
private function assertNotContainTables($expectedTables)
|
||||
{
|
||||
$tableNames = $this->getCurrentAvailableTableNames();
|
||||
|
||||
foreach ($expectedTables as $expectedTable) {
|
||||
$this->assertNotContains(Common::prefixTable($expectedTable), $tableNames);
|
||||
}
|
||||
}
|
||||
|
||||
private function getCurrentAvailableTableNames()
|
||||
{
|
||||
$tables = Db::fetchAll('show tables');
|
||||
|
||||
$tableNames = array();
|
||||
foreach ($tables as $table) {
|
||||
$tableNames[] = array_shift($table);
|
||||
}
|
||||
|
||||
return $tableNames;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
<?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\Test\Unit\TranslationWriter\Filter;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\ByBaseTranslations;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
*/
|
||||
class ByBaseTranslationsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getFilterTestData()
|
||||
{
|
||||
return array(
|
||||
// empty stays empty
|
||||
array(
|
||||
array(),
|
||||
array(),
|
||||
array(),
|
||||
array()
|
||||
),
|
||||
// empty plugin is removed
|
||||
array(
|
||||
array(
|
||||
'test' => array()
|
||||
),
|
||||
array(),
|
||||
array(),
|
||||
array(
|
||||
'test' => array()
|
||||
),
|
||||
),
|
||||
// not existing values/plugins are removed
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => 'value',
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => 'value',
|
||||
'x' => 'y'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => 'value',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test',
|
||||
)
|
||||
),
|
||||
),
|
||||
// no change if all exist
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array()
|
||||
),
|
||||
// unavailable removed, others stay
|
||||
array(
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'test'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => 'test',
|
||||
'empty' => ' ',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'test'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => 'test',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'test'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'empty' => ' ',
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'test'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => 'test',
|
||||
'empty' => ' ',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'bla' => 'test'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => 'test',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'test'
|
||||
),
|
||||
'test' => array(
|
||||
'empty' => ' ',
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilterTestData
|
||||
* @group Core
|
||||
*/
|
||||
public function testFilter($translations, $baseTranslations, $expected, $filteredData)
|
||||
{
|
||||
$filter = new ByBaseTranslations($baseTranslations);
|
||||
$result = $filter->filter($translations);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals($filteredData, $filter->getFilteredData());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
<?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\Test\Unit\TranslationWriter\Filter;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\ByParameterCount;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
*/
|
||||
class ByParameterCountTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getFilterTestData()
|
||||
{
|
||||
return array(
|
||||
// empty stays empty - nothing to filter
|
||||
array(
|
||||
array(),
|
||||
array(),
|
||||
array(),
|
||||
array()
|
||||
),
|
||||
// empty plugin is removed
|
||||
array(
|
||||
array(
|
||||
'test' => array()
|
||||
),
|
||||
array(),
|
||||
array(),
|
||||
array(),
|
||||
),
|
||||
// value with %s will be removed, as it isn't there in base
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => 'val%sue',
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => 'value',
|
||||
)
|
||||
),
|
||||
array(),
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => 'val%sue',
|
||||
)
|
||||
),
|
||||
),
|
||||
// no change if placeholder count is the same
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'te%sst'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test%s'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'te%sst'
|
||||
)
|
||||
),
|
||||
array()
|
||||
),
|
||||
// missing placeholder will be removed
|
||||
array(
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 't%1$sest'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => '%1$stest',
|
||||
'empty' => ' ',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'test%1$s'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => '%1$stest%2$s',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 't%1$sest'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => '%1$stest',
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilterTestData
|
||||
* @group Core
|
||||
*/
|
||||
public function testFilter($translations, $baseTranslations, $expected, $filteredData)
|
||||
{
|
||||
$filter = new ByParameterCount($baseTranslations);
|
||||
$result = $filter->filter($translations);
|
||||
$message = sprintf("got %s but expected %s", var_export($result, true), var_export($expected, true));
|
||||
$this->assertEquals($expected, $result, $message);
|
||||
$this->assertEquals($filteredData, $filter->getFilteredData());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?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\Test\Unit\TranslationWriter\Filter;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\EmptyTranslations;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
*/
|
||||
class EmptyTranslationsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getFilterTestData()
|
||||
{
|
||||
return array(
|
||||
// empty stays empty
|
||||
array(
|
||||
array(),
|
||||
array(),
|
||||
array()
|
||||
),
|
||||
// empty plugin is removed
|
||||
array(
|
||||
array(
|
||||
'test' => array()
|
||||
),
|
||||
array(),
|
||||
array(),
|
||||
),
|
||||
// empty values/plugins are removed
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'empty' => '',
|
||||
'whitespace' => ' '
|
||||
)
|
||||
),
|
||||
array(),
|
||||
array(
|
||||
'test' => array(
|
||||
'empty' => '',
|
||||
'whitespace' => ' '
|
||||
)
|
||||
),
|
||||
),
|
||||
// no change if no empty value
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array()
|
||||
),
|
||||
// empty values are removed, others stay
|
||||
array(
|
||||
array(
|
||||
'empty' => array(),
|
||||
'test' => array(
|
||||
'test' => 'test',
|
||||
'empty' => ' ',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'empty' => ' ',
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilterTestData
|
||||
* @group Core
|
||||
*/
|
||||
public function testFilter($translations, $expected, $filteredData)
|
||||
{
|
||||
$filter = new EmptyTranslations();
|
||||
$result = $filter->filter($translations);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals($filteredData, $filter->getFilteredData());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
<?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\Test\Unit\TranslationWriter\Filter;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\EncodedEntities;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
*/
|
||||
class EncodedEntitiesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getFilterTestData()
|
||||
{
|
||||
return array(
|
||||
// empty stays empty - nothing to filter
|
||||
array(
|
||||
array(),
|
||||
array(),
|
||||
array()
|
||||
),
|
||||
// empty plugin is removed
|
||||
array(
|
||||
array(
|
||||
'test' => array()
|
||||
),
|
||||
array(
|
||||
'test' => array()
|
||||
),
|
||||
array(),
|
||||
),
|
||||
// no entites - nothing to filter
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => 'val%sue',
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => 'val%sue',
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(),
|
||||
),
|
||||
// entities needs to be decodded
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'te&st'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'te&st'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'te&st'
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'tüsest'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => '%1$stest',
|
||||
'empty' => '˜',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'tüsest'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => '%1$stest',
|
||||
'empty' => '˜',
|
||||
)
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'tüsest'
|
||||
),
|
||||
'test' => array(
|
||||
'empty' => '˜',
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilterTestData
|
||||
* @group Core
|
||||
*/
|
||||
public function testFilter($translations, $expected, $filteredData)
|
||||
{
|
||||
$filter = new EncodedEntities();
|
||||
$result = $filter->filter($translations);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals($filteredData, $filter->getFilteredData());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
<?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\Test\Unit\TranslationWriter\Filter;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\UnnecassaryWhitespaces;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
*/
|
||||
class UnnecassaryWhitepsacesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getFilterTestData()
|
||||
{
|
||||
return array(
|
||||
// empty stays empty - nothing to filter
|
||||
array(
|
||||
array(),
|
||||
array(),
|
||||
array(),
|
||||
array()
|
||||
),
|
||||
// no entites - nothing to filter
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => "val\n\n\r\n\nue",
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => "base val\n\nue",
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => "val\n\nue",
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => "val\n\n\r\n\nue",
|
||||
)
|
||||
|
||||
),
|
||||
),
|
||||
// entities needs to be decodded
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test palim'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'no line breaks'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test palim'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test palim'
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => "test\n\n\ntest"
|
||||
),
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'no line break'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'test test'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => "test\n\n\ntest"
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => "test\n \n\n test"
|
||||
),
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'no line break'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'test test'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => "test\n \n\n test"
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => "test\n \n\n test"
|
||||
),
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => "line\n break"
|
||||
),
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => "test\n\ntest"
|
||||
),
|
||||
),
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => "test\n \n\n test"
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilterTestData
|
||||
* @group Core
|
||||
*/
|
||||
public function testFilter($translations, $baseTranslations, $expected, $filteredData)
|
||||
{
|
||||
$filter = new UnnecassaryWhitespaces($baseTranslations);
|
||||
$result = $filter->filter($translations);
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertEquals($filteredData, $filter->getFilteredData());
|
||||
}
|
||||
}
|
||||
|
|
@ -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\Test\Unit\TranslationWriter\Validate;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Validate\CoreTranslations;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
*/
|
||||
class CoreTranslationsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getFilterTestDataValid()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'General' => array_merge(array_fill(0, 251, 'test'), array(
|
||||
'Locale' => 'de_DE.UTF-8',
|
||||
'TranslatorName' => 'name'
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilterTestDataValid
|
||||
* @group Core
|
||||
*/
|
||||
public function testFilterValid($translations)
|
||||
{
|
||||
$filter = new CoreTranslations();
|
||||
$result = $filter->isValid($translations);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function getFilterTestDataInvalid()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'General' => array(
|
||||
'bla' => 'test text'
|
||||
)
|
||||
),
|
||||
CoreTranslations::ERRORSTATE_LOCALEREQUIRED
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'General' => array(
|
||||
'Locale' => 'de_DE.UTF-8'
|
||||
)
|
||||
),
|
||||
CoreTranslations::ERRORSTATE_TRANSLATORINFOREQUIRED
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'General' => array(
|
||||
'Locale' => 'invalid',
|
||||
'TranslatorName' => 'name'
|
||||
)
|
||||
),
|
||||
CoreTranslations::ERRORSTATE_LOCALEINVALID
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'General' => array(
|
||||
'Locale' => 'xx_DE.UTF-8',
|
||||
'TranslatorName' => 'name'
|
||||
)
|
||||
),
|
||||
CoreTranslations::ERRORSTATE_LOCALEINVALIDLANGUAGE
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'General' => array(
|
||||
'Locale' => 'de_XX.UTF-8',
|
||||
'TranslatorName' => 'name'
|
||||
)
|
||||
),
|
||||
CoreTranslations::ERRORSTATE_LOCALEINVALIDCOUNTRY
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilterTestDataInvalid
|
||||
* @group Core
|
||||
*/
|
||||
public function testFilterInvalid($translations, $msg)
|
||||
{
|
||||
$filter = new CoreTranslations();
|
||||
$result = $filter->isValid($translations);
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals($msg, $filter->getMessage());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
<?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\Test\Unit\TranslationWriter\Validate;
|
||||
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Validate\NoScripts;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
*/
|
||||
class NoScriptsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getFilterTestDataValid()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'test' => array()
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'key' => 'val%sue',
|
||||
'test' => 'test'
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilterTestDataValid
|
||||
* @group Core
|
||||
*/
|
||||
public function testFilterValid($translations)
|
||||
{
|
||||
$filter = new NoScripts();
|
||||
$result = $filter->isValid($translations);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function getFilterTestDataInvalid()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'test text <script'
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'empty' => array(
|
||||
'test' => 'tüsest'
|
||||
),
|
||||
'test' => array(
|
||||
'test' => 'bla <a href="javascript:alert();"> link </a>',
|
||||
'empty' => '˜',
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'bla <a onload="alert(\'test\');">link</a>'
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'no <img src="test" />'
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'that will fail on document. or not?'
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'test' => array(
|
||||
'test' => 'bla <a background="yellow">link</a>'
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFilterTestDataInvalid
|
||||
* @group Core
|
||||
*/
|
||||
public function testFilterInvalid($translations)
|
||||
{
|
||||
$filter = new NoScripts();
|
||||
$result = $filter->isValid($translations);
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
<?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\Test\Unit\TranslationWriter;
|
||||
|
||||
use Piwik\Container\StaticContainer;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\ByBaseTranslations;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\ByParameterCount;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @group LanguagesManager
|
||||
*/
|
||||
class WriterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @group Core
|
||||
*
|
||||
* @dataProvider getValidConstructorData
|
||||
*/
|
||||
public function testConstructorValid($language, $plugin)
|
||||
{
|
||||
$translationWriter = new Writer($language, $plugin);
|
||||
$this->assertEquals($language, $translationWriter->getLanguage());
|
||||
$this->assertFalse($translationWriter->hasTranslations());
|
||||
}
|
||||
|
||||
public function getValidConstructorData()
|
||||
{
|
||||
return array(
|
||||
array('en', ''),
|
||||
array('de', ''),
|
||||
array('en', 'ExamplePlugin'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*
|
||||
* @expectedException \Exception
|
||||
*/
|
||||
public function testConstructorInvalid()
|
||||
{
|
||||
new Writer('en', 'InValIdPlUGin');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*/
|
||||
public function testHasTranslations()
|
||||
{
|
||||
$writer = new Writer('de');
|
||||
$writer->setTranslations(array('General' => array('test' => 'test')));
|
||||
$this->assertTrue($writer->hasTranslations());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*/
|
||||
public function testHasNoTranslations()
|
||||
{
|
||||
$writer = new Writer('de');
|
||||
$this->assertFalse($writer->hasTranslations());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*/
|
||||
public function testSetTranslationsEmpty()
|
||||
{
|
||||
$writer = new Writer('de');
|
||||
$writer->setTranslations(array());
|
||||
$this->assertTrue($writer->isValid());
|
||||
$this->assertFalse($writer->hasTranslations());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*
|
||||
* @dataProvider getInvalidTranslations
|
||||
*/
|
||||
public function testSetTranslationsInvalid($translations, $error)
|
||||
{
|
||||
$writer = new Writer('de');
|
||||
$writer->setTranslations($translations);
|
||||
$writer->addValidator(new NoScripts());
|
||||
$writer->addValidator(new CoreTranslations());
|
||||
$this->assertFalse($writer->isValid());
|
||||
$this->assertEquals($error, $writer->getValidationMessage());
|
||||
}
|
||||
|
||||
public function getInvalidTranslations()
|
||||
{
|
||||
$translations = json_decode(file_get_contents(PIWIK_INCLUDE_PATH.'/lang/de.json'), true);
|
||||
return array(
|
||||
array(array('General' => array('Locale' => '')) + $translations, CoreTranslations::ERRORSTATE_LOCALEREQUIRED),
|
||||
array(array('General' => array('Locale' => 'de_DE.UTF-8')) + $translations, CoreTranslations::ERRORSTATE_TRANSLATORINFOREQUIRED),
|
||||
array(array('General' => array('Locale' => 'invalid',
|
||||
'TranslatorName' => 'name')) + $translations, CoreTranslations::ERRORSTATE_LOCALEINVALID),
|
||||
array(array('General' => array('Locale' => 'xx_DE.UTF-8',
|
||||
'TranslatorName' => 'name')) + $translations, CoreTranslations::ERRORSTATE_LOCALEINVALIDLANGUAGE),
|
||||
array(array('General' => array('Locale' => 'de_XX.UTF-8',
|
||||
'TranslatorName' => 'name')) + $translations, CoreTranslations::ERRORSTATE_LOCALEINVALIDCOUNTRY),
|
||||
array(array('General' => array('Locale' => '<script>')) + $translations, 'script tags restricted for language files'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*
|
||||
* @expectedException \Exception
|
||||
*/
|
||||
public function testSaveException()
|
||||
{
|
||||
$writer = new Writer('it');
|
||||
$writer->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*
|
||||
* @expectedException \Exception
|
||||
*/
|
||||
public function testSaveTemporaryException()
|
||||
{
|
||||
$writer = new Writer('it');
|
||||
$writer->saveTemporary();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*/
|
||||
public function testSaveTranslation()
|
||||
{
|
||||
$translations = json_decode(file_get_contents(PIWIK_INCLUDE_PATH.'/lang/en.json'), true);
|
||||
|
||||
$translationsToWrite = array();
|
||||
$translationsToWrite['General'] = $translations['General'];
|
||||
$translationsToWrite['Mobile'] = $translations['Mobile'];
|
||||
|
||||
$translationsToWrite['General']['Yes'] = 'string with %1$s';
|
||||
$translationsToWrite['Plugin'] = array(
|
||||
'Body' => "Message\nBody"
|
||||
);
|
||||
|
||||
$translationWriter = new Writer('fr');
|
||||
|
||||
$translationWriter->addFilter(new UnnecassaryWhitespaces($translations));
|
||||
$translationWriter->addFilter(new ByBaseTranslations($translations));
|
||||
$translationWriter->addFilter(new ByParameterCount($translations));
|
||||
|
||||
$translationWriter->setTranslations($translationsToWrite);
|
||||
|
||||
$rc = $translationWriter->saveTemporary();
|
||||
|
||||
@unlink(PIWIK_INCLUDE_PATH.'/tmp/fr.json');
|
||||
|
||||
$this->assertGreaterThan(25000, $rc);
|
||||
|
||||
$this->assertCount(4, $translationWriter->getFilterMessages());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*
|
||||
* @dataProvider getTranslationPathTestData
|
||||
*/
|
||||
public function testGetTranslationsPath($language, $plugin, $path)
|
||||
{
|
||||
$writer = new Writer($language, $plugin);
|
||||
$this->assertEquals($path, $writer->getTranslationPath());
|
||||
}
|
||||
|
||||
public function getTranslationPathTestData()
|
||||
{
|
||||
return array(
|
||||
array('de', null, PIWIK_INCLUDE_PATH . '/lang/de.json'),
|
||||
array('te', null, PIWIK_INCLUDE_PATH . '/lang/te.json'),
|
||||
array('de', 'CoreHome', PIWIK_INCLUDE_PATH . '/plugins/CoreHome/lang/de.json'),
|
||||
array('pt-br', 'Actions', PIWIK_INCLUDE_PATH . '/plugins/Actions/lang/pt-br.json'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*
|
||||
* @dataProvider getTranslationPathTemporaryTestData
|
||||
*/
|
||||
public function testGetTemporaryTranslationPath($language, $plugin, $path)
|
||||
{
|
||||
$writer = new Writer($language, $plugin);
|
||||
$this->assertEquals($path, $writer->getTemporaryTranslationPath());
|
||||
}
|
||||
|
||||
public function getTranslationPathTemporaryTestData()
|
||||
{
|
||||
$tmpPath = StaticContainer::get('path.tmp');
|
||||
|
||||
return array(
|
||||
array('de', null, $tmpPath . '/de.json'),
|
||||
array('te', null, $tmpPath . '/te.json'),
|
||||
array('de', 'CoreHome', $tmpPath . '/plugins/CoreHome/lang/de.json'),
|
||||
array('pt-br', 'Actions', $tmpPath . '/plugins/Actions/lang/pt-br.json'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Core
|
||||
*
|
||||
* @dataProvider getValidLanguages
|
||||
*/
|
||||
public function testSetLanguageValid($language)
|
||||
{
|
||||
$writer = new Writer('en', null);
|
||||
$writer->setLanguage($language);
|
||||
$this->assertEquals(strtolower($language), $writer->getLanguage());
|
||||
}
|
||||
|
||||
public function getValidLanguages()
|
||||
{
|
||||
return array(
|
||||
array('de'),
|
||||
array('te'),
|
||||
array('pt-br'),
|
||||
array('tzm'),
|
||||
array('abc'),
|
||||
array('de-de'),
|
||||
array('DE'),
|
||||
array('DE-DE'),
|
||||
array('DE-de'),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @group Core
|
||||
*
|
||||
* @expectedException \Exception
|
||||
* @dataProvider getInvalidLanguages
|
||||
*/
|
||||
public function testSetLanguageInvalid($language)
|
||||
{
|
||||
$writer = new Writer('en', null);
|
||||
$writer->setLanguage($language);
|
||||
}
|
||||
|
||||
public function getInvalidLanguages()
|
||||
{
|
||||
return array(
|
||||
array(''),
|
||||
array('abcd'),
|
||||
array('pt-brfr'),
|
||||
array('00'),
|
||||
array('a-b'),
|
||||
array('x3'),
|
||||
array('X4-fd'),
|
||||
array('12-34'),
|
||||
array('$§'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?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\TranslationWriter\Filter;
|
||||
|
||||
class ByBaseTranslations extends FilterAbstract
|
||||
{
|
||||
protected $baseTranslations = array();
|
||||
|
||||
/**
|
||||
* Sets base translations
|
||||
*
|
||||
* @param array $baseTranslations
|
||||
*/
|
||||
public function __construct($baseTranslations = array())
|
||||
{
|
||||
$this->baseTranslations = $baseTranslations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all translations that aren't present in the base translations set in constructor
|
||||
*
|
||||
* @param array $translations
|
||||
*
|
||||
* @return array filtered translations
|
||||
*/
|
||||
public function filter($translations)
|
||||
{
|
||||
$cleanedTranslations = array();
|
||||
|
||||
foreach ($translations as $pluginName => $pluginTranslations) {
|
||||
|
||||
if (empty($this->baseTranslations[$pluginName])) {
|
||||
$this->filteredData[$pluginName] = $pluginTranslations;
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($pluginTranslations as $key => $translation) {
|
||||
if (isset($this->baseTranslations[$pluginName][$key])) {
|
||||
$cleanedTranslations[$pluginName][$key] = $translation;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($cleanedTranslations[$pluginName])) {
|
||||
$diff = array_diff($translations[$pluginName], $cleanedTranslations[$pluginName]);
|
||||
} else {
|
||||
$diff = $translations[$pluginName];
|
||||
}
|
||||
if (!empty($diff)) {
|
||||
$this->filteredData[$pluginName] = $diff;
|
||||
}
|
||||
}
|
||||
|
||||
return $cleanedTranslations;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
<?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\TranslationWriter\Filter;
|
||||
|
||||
class ByParameterCount extends FilterAbstract
|
||||
{
|
||||
protected $baseTranslations = array();
|
||||
|
||||
/**
|
||||
* Sets base translations
|
||||
*
|
||||
* @param array $baseTranslations
|
||||
*/
|
||||
public function __construct($baseTranslations = array())
|
||||
{
|
||||
$this->baseTranslations = $baseTranslations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all translations where the placeholder parameter count differs to base translation
|
||||
*
|
||||
* @param array $translations
|
||||
*
|
||||
* @return array filtered translations
|
||||
*/
|
||||
public function filter($translations)
|
||||
{
|
||||
$cleanedTranslations = array();
|
||||
|
||||
foreach ($translations as $pluginName => $pluginTranslations) {
|
||||
|
||||
foreach ($pluginTranslations as $key => $translation) {
|
||||
|
||||
if (isset($this->baseTranslations[$pluginName][$key])) {
|
||||
$baseTranslation = $this->baseTranslations[$pluginName][$key];
|
||||
} else {
|
||||
// english string was deleted, do not error
|
||||
continue;
|
||||
}
|
||||
|
||||
// ensure that translated strings have the same number of %s as the english source strings
|
||||
$baseCount = $this->_getParametersCountToReplace($baseTranslation);
|
||||
$translationCount = $this->_getParametersCountToReplace($translation);
|
||||
|
||||
if ($baseCount != $translationCount) {
|
||||
|
||||
$this->filteredData[$pluginName][$key] = $translation;
|
||||
continue;
|
||||
}
|
||||
|
||||
$cleanedTranslations[$pluginName][$key] = $translation;
|
||||
}
|
||||
}
|
||||
|
||||
return $cleanedTranslations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the placeholder parameters n given string
|
||||
*
|
||||
* @param string $string
|
||||
* @return array
|
||||
*/
|
||||
protected function _getParametersCountToReplace($string)
|
||||
{
|
||||
$sprintfParameters = array('%s', '%1$s', '%2$s', '%3$s', '%4$s', '%5$s', '%6$s', '%7$s', '%8$s', '%9$s');
|
||||
$count = array();
|
||||
foreach ($sprintfParameters as $parameter) {
|
||||
|
||||
$placeholderCount = substr_count($string, $parameter);
|
||||
if ($placeholderCount > 0) {
|
||||
|
||||
$count[$parameter] = $placeholderCount;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?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\TranslationWriter\Filter;
|
||||
|
||||
class EmptyTranslations extends FilterAbstract
|
||||
{
|
||||
/**
|
||||
* Removes all empty translations
|
||||
*
|
||||
* @param array $translations
|
||||
*
|
||||
* @return array filtered translations
|
||||
*/
|
||||
public function filter($translations)
|
||||
{
|
||||
$translationsBefore = $translations;
|
||||
|
||||
foreach ($translations as $plugin => &$pluginTranslations) {
|
||||
|
||||
$pluginTranslations = array_filter($pluginTranslations, function ($value) {
|
||||
return !empty($value) && '' != trim($value);
|
||||
});
|
||||
|
||||
$diff = array_diff($translationsBefore[$plugin], $pluginTranslations);
|
||||
if (!empty($diff)) {
|
||||
$this->filteredData[$plugin] = $diff;
|
||||
}
|
||||
}
|
||||
|
||||
// remove plugins without translations
|
||||
$translations = array_filter($translations, function ($value) {
|
||||
return !empty($value) && count($value);
|
||||
});
|
||||
|
||||
return $translations;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?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\TranslationWriter\Filter;
|
||||
|
||||
use Piwik\Translate;
|
||||
|
||||
class EncodedEntities extends FilterAbstract
|
||||
{
|
||||
/**
|
||||
* Decodes all encoded entities in the given translations
|
||||
*
|
||||
* @param array $translations
|
||||
*
|
||||
* @return array filtered translations
|
||||
*/
|
||||
public function filter($translations)
|
||||
{
|
||||
foreach ($translations as $pluginName => $pluginTranslations) {
|
||||
foreach ($pluginTranslations as $key => $translation) {
|
||||
|
||||
// remove encoded entities
|
||||
$decoded = Translate::clean($translation);
|
||||
if ($translation != $decoded) {
|
||||
$this->filteredData[$pluginName][$key] = $translation;
|
||||
$translations[$pluginName][$key] = $decoded;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $translations;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?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\TranslationWriter\Filter;
|
||||
|
||||
abstract class FilterAbstract
|
||||
{
|
||||
protected $filteredData = array();
|
||||
|
||||
/**
|
||||
* Filter the given translations
|
||||
*
|
||||
* @param array $translations
|
||||
*
|
||||
* @return array filtered translations
|
||||
*/
|
||||
abstract public function filter($translations);
|
||||
|
||||
/**
|
||||
* Returnes the data filtered out by the filter
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFilteredData()
|
||||
{
|
||||
return $this->filteredData;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?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\TranslationWriter\Filter;
|
||||
|
||||
class UnnecassaryWhitespaces extends FilterAbstract
|
||||
{
|
||||
protected $baseTranslations = array();
|
||||
|
||||
/**
|
||||
* Sets base translations
|
||||
*
|
||||
* @param array $baseTranslations
|
||||
*/
|
||||
public function __construct($baseTranslations = array())
|
||||
{
|
||||
$this->baseTranslations = $baseTranslations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all unnecassary whitespaces and newlines from the given translations
|
||||
*
|
||||
* @param array $translations
|
||||
*
|
||||
* @return array filtered translations
|
||||
*/
|
||||
public function filter($translations)
|
||||
{
|
||||
foreach ($translations as $pluginName => $pluginTranslations) {
|
||||
foreach ($pluginTranslations as $key => $translation) {
|
||||
|
||||
$baseTranslation = '';
|
||||
if (isset($this->baseTranslations[$pluginName][$key])) {
|
||||
$baseTranslation = $this->baseTranslations[$pluginName][$key];
|
||||
}
|
||||
|
||||
// remove excessive line breaks (and leading/trailing whitespace) from translations
|
||||
$stringNoLineBreak = trim($translation);
|
||||
$stringNoLineBreak = str_replace("\r", "", $stringNoLineBreak); # remove useless carrige renturns
|
||||
$stringNoLineBreak = preg_replace('/(\n[ ]+)/', "\n", $stringNoLineBreak); # remove useless white spaces after line breaks
|
||||
$stringNoLineBreak = preg_replace('/([\n]{2,})/', "\n\n", $stringNoLineBreak); # remove excessive line breaks
|
||||
if (empty($baseTranslation) || !substr_count($baseTranslation, "\n")) {
|
||||
$stringNoLineBreak = preg_replace("/[\n]+/", " ", $stringNoLineBreak); # remove all line breaks if english string doesn't contain any
|
||||
}
|
||||
$stringNoLineBreak = preg_replace('/([ ]{2,})/', " ", $stringNoLineBreak); # remove excessive white spaces again as there might be any now, after removing line breaks
|
||||
if ($translation !== $stringNoLineBreak) {
|
||||
$this->filteredData[$pluginName][$key] = $translation;
|
||||
$translations[$pluginName][$key] = $stringNoLineBreak;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $translations;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
<?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\TranslationWriter\Validate;
|
||||
|
||||
use Piwik\Container\StaticContainer;
|
||||
use Piwik\Intl\Data\Provider\LanguageDataProvider;
|
||||
use Piwik\Intl\Data\Provider\RegionDataProvider;
|
||||
|
||||
class CoreTranslations extends ValidateAbstract
|
||||
{
|
||||
/**
|
||||
* Error States
|
||||
*/
|
||||
const ERRORSTATE_LOCALEREQUIRED = 'Locale required';
|
||||
const ERRORSTATE_TRANSLATORINFOREQUIRED = 'Translator info required';
|
||||
const ERRORSTATE_LOCALEINVALID = 'Locale is invalid';
|
||||
const ERRORSTATE_LOCALEINVALIDLANGUAGE = 'Locale is invalid - invalid language code';
|
||||
const ERRORSTATE_LOCALEINVALIDCOUNTRY = 'Locale is invalid - invalid country code';
|
||||
|
||||
protected $baseTranslations = array();
|
||||
|
||||
/**
|
||||
* Sets base translations
|
||||
*
|
||||
* @param array $baseTranslations
|
||||
*/
|
||||
public function __construct($baseTranslations = array())
|
||||
{
|
||||
$this->baseTranslations = $baseTranslations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given translations
|
||||
* * There need to be more than 250 translations present
|
||||
* * Locale and TranslatorName needs to be set in plugin General
|
||||
* * Locale must be valid (format, language & country)
|
||||
*
|
||||
* @param array $translations
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isValid($translations)
|
||||
{
|
||||
$this->message = null;
|
||||
|
||||
if (empty($translations['General']['Locale'])) {
|
||||
$this->message = self::ERRORSTATE_LOCALEREQUIRED;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($translations['General']['TranslatorName'])) {
|
||||
$this->message = self::ERRORSTATE_TRANSLATORINFOREQUIRED;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var LanguageDataProvider $languageDataProvider */
|
||||
$languageDataProvider = StaticContainer::get('Piwik\Intl\Data\Provider\LanguageDataProvider');
|
||||
/** @var RegionDataProvider $regionDataProvider */
|
||||
$regionDataProvider = StaticContainer::get('Piwik\Intl\Data\Provider\RegionDataProvider');
|
||||
|
||||
$allLanguages = $languageDataProvider->getLanguageList();
|
||||
$allCountries = $regionDataProvider->getCountryList();
|
||||
|
||||
if (!preg_match('/^([a-z]{2})_([A-Z]{2})\.UTF-8$/', $translations['General']['Locale'], $matches)) {
|
||||
$this->message = self::ERRORSTATE_LOCALEINVALID;
|
||||
return false;
|
||||
} else if (!array_key_exists($matches[1], $allLanguages)) {
|
||||
$this->message = self::ERRORSTATE_LOCALEINVALIDLANGUAGE;
|
||||
return false;
|
||||
} else if (!array_key_exists(strtolower($matches[2]), $allCountries)) {
|
||||
$this->message = self::ERRORSTATE_LOCALEINVALIDCOUNTRY;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?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\TranslationWriter\Validate;
|
||||
|
||||
class NoScripts extends ValidateAbstract
|
||||
{
|
||||
/**
|
||||
* Validates the given translations
|
||||
* * No script like parts should be present in any part of the translations
|
||||
*
|
||||
* @param array $translations
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isValid($translations)
|
||||
{
|
||||
$this->message = null;
|
||||
|
||||
// check if any translation contains restricted script tags
|
||||
$serializedStrings = serialize($translations);
|
||||
$invalids = array("<script", 'document.', 'javascript:', 'src=', 'background=', 'onload=');
|
||||
|
||||
foreach ($invalids as $invalid) {
|
||||
if (stripos($serializedStrings, $invalid) !== false) {
|
||||
$this->message = 'script tags restricted for language files';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?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\TranslationWriter\Validate;
|
||||
|
||||
abstract class ValidateAbstract
|
||||
{
|
||||
protected $message = null;
|
||||
|
||||
/**
|
||||
* Returns if the given translations are valid
|
||||
*
|
||||
* @param array $translations
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function isValid($translations);
|
||||
|
||||
/**
|
||||
* Returns an array of messages that explain why the most recent isValid()
|
||||
* call returned false.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMessage()
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,387 @@
|
|||
<?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\TranslationWriter;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Container\StaticContainer;
|
||||
use Piwik\Filesystem;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Filter\FilterAbstract;
|
||||
use Piwik\Plugins\LanguagesManager\TranslationWriter\Validate\ValidateAbstract;
|
||||
|
||||
/**
|
||||
* Writes translations to file.
|
||||
*/
|
||||
class Writer
|
||||
{
|
||||
/**
|
||||
* current language to write files for
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $language = '';
|
||||
|
||||
/**
|
||||
* Name of a plugin (if set in constructor)
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $pluginName = null;
|
||||
|
||||
/**
|
||||
* translations to write to file
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $translations = array();
|
||||
|
||||
/**
|
||||
* Validators to check translations with
|
||||
*
|
||||
* @var ValidateAbstract[]
|
||||
*/
|
||||
protected $validators = array();
|
||||
|
||||
/**
|
||||
* Message why validation failed
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $validationMessage = null;
|
||||
|
||||
/**
|
||||
* Filters to to apply to translations
|
||||
*
|
||||
* @var FilterAbstract[]
|
||||
*/
|
||||
protected $filters = array();
|
||||
|
||||
/**
|
||||
* Messages which filter changed the data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $filterMessages = array();
|
||||
|
||||
const UNFILTERED = 'unfiltered';
|
||||
const FILTERED = 'filtered';
|
||||
|
||||
protected $currentState = self::UNFILTERED;
|
||||
|
||||
/**
|
||||
* If $pluginName is given, Writer will be initialized for the given plugin if it exists
|
||||
* Otherwise it will be initialized for core translations
|
||||
*
|
||||
* @param string $language ISO 639-1 alpha-2 language code
|
||||
* @param string $pluginName optional plugin name
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($language, $pluginName = null)
|
||||
{
|
||||
$this->setLanguage($language);
|
||||
|
||||
if (!empty($pluginName)) {
|
||||
$installedPlugins = \Piwik\Plugin\Manager::getInstance()->readPluginsDirectory();
|
||||
|
||||
if (!in_array($pluginName, $installedPlugins)) {
|
||||
|
||||
throw new Exception(Piwik::translate('General_ExceptionLanguageFileNotFound', array($pluginName)));
|
||||
}
|
||||
|
||||
$this->pluginName = $pluginName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $language ISO 639-1 alpha-2 language code
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setLanguage($language)
|
||||
{
|
||||
if (!preg_match('/^([a-z]{2,3}(-[a-z]{2,3})?)$/i', $language)) {
|
||||
throw new Exception(Piwik::translate('General_ExceptionLanguageFileNotFound', array($language)));
|
||||
}
|
||||
|
||||
$this->language = strtolower($language);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string ISO 639-1 alpha-2 language code
|
||||
*/
|
||||
public function getLanguage()
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if there are translations available or not
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTranslations()
|
||||
{
|
||||
return !empty($this->translations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the translations to write (and cleans them)
|
||||
*
|
||||
* @param $translations
|
||||
*/
|
||||
public function setTranslations($translations)
|
||||
{
|
||||
$this->currentState = self::UNFILTERED;
|
||||
$this->translations = $translations;
|
||||
$this->applyFilters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translations from file
|
||||
*
|
||||
* @param string $lang ISO 639-1 alpha-2 language code
|
||||
* @throws Exception
|
||||
* @return array Array of translations ( plugin => ( key => translated string ) )
|
||||
*/
|
||||
public function getTranslations($lang)
|
||||
{
|
||||
$path = $this->getTranslationPathBaseDirectory('lang', $lang);
|
||||
|
||||
if (!is_readable($path)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$data = file_get_contents($path);
|
||||
$translations = json_decode($data, true);
|
||||
|
||||
return $translations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the temporary path for translations
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemporaryTranslationPath()
|
||||
{
|
||||
return $this->getTranslationPathBaseDirectory('tmp');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to translation files
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTranslationPath()
|
||||
{
|
||||
return $this->getTranslationPathBaseDirectory('lang');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translation file path based on given params
|
||||
*
|
||||
* @param string $base Optional base directory (either 'lang' or 'tmp')
|
||||
* @param string|null $lang forced language
|
||||
* @throws \Exception
|
||||
* @return string path
|
||||
*/
|
||||
protected function getTranslationPathBaseDirectory($base, $lang = null)
|
||||
{
|
||||
if (empty($lang)) {
|
||||
$lang = $this->getLanguage();
|
||||
}
|
||||
|
||||
if (!empty($this->pluginName)) {
|
||||
|
||||
if ($base == 'tmp') {
|
||||
return sprintf('%s/plugins/%s/lang/%s.json', StaticContainer::get('path.tmp'), $this->pluginName, $lang);
|
||||
} else {
|
||||
return sprintf('%s/plugins/%s/lang/%s.json', PIWIK_INCLUDE_PATH, $this->pluginName, $lang);
|
||||
}
|
||||
}
|
||||
|
||||
if ($base == 'tmp') {
|
||||
return sprintf('%s/%s.json', StaticContainer::get('path.tmp'), $lang);
|
||||
}
|
||||
|
||||
return sprintf('%s/%s/%s.json', PIWIK_INCLUDE_PATH, $base, $lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts translations to a string that can be written to a file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
/*
|
||||
* Use JSON_UNESCAPED_UNICODE and JSON_PRETTY_PRINT for PHP >= 5.4
|
||||
*/
|
||||
$options = 0;
|
||||
if (defined('JSON_UNESCAPED_UNICODE')) {
|
||||
$options |= JSON_UNESCAPED_UNICODE;
|
||||
}
|
||||
if (defined('JSON_PRETTY_PRINT')) {
|
||||
$options |= JSON_PRETTY_PRINT;
|
||||
}
|
||||
|
||||
return json_encode($this->translations, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save translations to file; translations should already be cleaned.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return bool|int False if failure, or number of bytes written
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$this->applyFilters();
|
||||
|
||||
if (!$this->hasTranslations() || !$this->isValid()) {
|
||||
throw new Exception('unable to save empty or invalid translations');
|
||||
}
|
||||
|
||||
$path = $this->getTranslationPath();
|
||||
|
||||
Filesystem::mkdir(dirname($path));
|
||||
|
||||
return file_put_contents($path, $this->__toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Save translations to temporary file; translations should already be cleansed.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return bool|int False if failure, or number of bytes written
|
||||
*/
|
||||
public function saveTemporary()
|
||||
{
|
||||
$this->applyFilters();
|
||||
|
||||
if (!$this->hasTranslations() || !$this->isValid()) {
|
||||
throw new Exception('unable to save empty or invalid translations');
|
||||
}
|
||||
|
||||
$path = $this->getTemporaryTranslationPath();
|
||||
|
||||
Filesystem::mkdir(dirname($path));
|
||||
|
||||
return file_put_contents($path, $this->__toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an validator to check before saving
|
||||
*
|
||||
* @param ValidateAbstract $validator
|
||||
*/
|
||||
public function addValidator(ValidateAbstract $validator)
|
||||
{
|
||||
$this->validators[] = $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if translations are valid to save or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid()
|
||||
{
|
||||
$this->applyFilters();
|
||||
|
||||
$this->validationMessage = null;
|
||||
|
||||
foreach ($this->validators as $validator) {
|
||||
if (!$validator->isValid($this->translations)) {
|
||||
$this->validationMessage = $validator->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns last validation message
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getValidationMessage()
|
||||
{
|
||||
return $this->validationMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the were translations removed while cleaning
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function wasFiltered()
|
||||
{
|
||||
return !empty($this->filterMessages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cleaning errors
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFilterMessages()
|
||||
{
|
||||
return $this->filterMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FilterAbstract $filter
|
||||
*/
|
||||
public function addFilter(FilterAbstract $filter)
|
||||
{
|
||||
$this->filters[] = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return bool error state
|
||||
*/
|
||||
protected function applyFilters()
|
||||
{
|
||||
// skip if already cleaned
|
||||
if ($this->currentState == self::FILTERED) {
|
||||
return $this->wasFiltered();
|
||||
}
|
||||
|
||||
$this->filterMessages = array();
|
||||
|
||||
// skip if not translations available
|
||||
if (!$this->hasTranslations()) {
|
||||
$this->currentState = self::FILTERED;
|
||||
return false;
|
||||
}
|
||||
|
||||
$cleanedTranslations = $this->translations;
|
||||
|
||||
foreach ($this->filters as $filter) {
|
||||
|
||||
$cleanedTranslations = $filter->filter($cleanedTranslations);
|
||||
$filteredData = $filter->getFilteredData();
|
||||
if (!empty($filteredData)) {
|
||||
$this->filterMessages[] = get_class($filter) . " changed: " . var_export($filteredData, 1);
|
||||
}
|
||||
}
|
||||
|
||||
$this->currentState = self::FILTERED;
|
||||
|
||||
if ($cleanedTranslations != $this->translations) {
|
||||
$this->filterMessages[] = 'translations have been cleaned';
|
||||
}
|
||||
|
||||
$this->translations = $cleanedTranslations;
|
||||
return $this->wasFiltered();
|
||||
}
|
||||
}
|
||||
32
www/analytics/plugins/LanguagesManager/Updates/2.15.1-b1.php
Normal file
32
www/analytics/plugins/LanguagesManager/Updates/2.15.1-b1.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?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;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Updater;
|
||||
use Piwik\Updates;
|
||||
|
||||
|
||||
class Updates_2_15_1_b1 extends Updates
|
||||
{
|
||||
public function getMigrationQueries(Updater $updater)
|
||||
{
|
||||
$updateSql = array(
|
||||
'ALTER TABLE `' . Common::prefixTable('user_language')
|
||||
. '` ADD COLUMN `use_12_hour_clock` TINYINT(1) NOT NULL DEFAULT 0 AFTER `language`' => array(1060)
|
||||
);
|
||||
return $updateSql;
|
||||
}
|
||||
|
||||
public function doUpdate(Updater $updater)
|
||||
{
|
||||
$updater->executeMigrationQueries(__FILE__, $this->getMigrationQueries($updater));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* <div class="languageSelection">
|
||||
* </div>
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').directive('languageSelection', languageSelection);
|
||||
|
||||
function languageSelection() {
|
||||
|
||||
return {
|
||||
restrict: 'C',
|
||||
link: function(scope, element, attr, ctrl) {
|
||||
|
||||
function postLanguageChange () {
|
||||
var value = $(this).attr('value');
|
||||
if (value) {
|
||||
element.find('#language').val(value).parents('form').submit();
|
||||
}
|
||||
}
|
||||
|
||||
element.on('click', 'a[value]', postLanguageChange);
|
||||
scope.$on('$destroy', function() {
|
||||
element.off('click', 'a[value]', postLanguageChange);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').controller('TranslationSearchController', TranslationSearchController);
|
||||
|
||||
TranslationSearchController.$inject = ['piwikApi'];
|
||||
|
||||
function TranslationSearchController(piwikApi) {
|
||||
|
||||
var vm = this;
|
||||
vm.existingTranslations = [];
|
||||
|
||||
fetchTranslations();
|
||||
|
||||
function fetchTranslations() {
|
||||
piwikApi.fetch({
|
||||
method: 'LanguagesManager.getTranslationsForLanguage',
|
||||
filter_limit: -1,
|
||||
languageCode: 'en'
|
||||
}).then(function (response) {
|
||||
if (response) {
|
||||
vm.existingTranslations = response;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<div>
|
||||
|
||||
<p class="adminTable">
|
||||
This page helps you to find existing translations that you can reuse in your Plugin.
|
||||
If you want to know more about translations have a look at our <a href="http://developer.piwik.org/guides/internationalization" rel="noreferrer" target="_blank">Internationalization guide</a>.
|
||||
Enter a search term to find translations and their corresponding keys:
|
||||
</p>
|
||||
|
||||
<input type="text" placeholder="Search for English translation" title="Search for English translation. Max 1000 results will be shown." ng-model="translationSearch.searchTerm" style="width:271px">
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<table ng-show="translationSearch.searchTerm" class="entityTable dataTable" style="width: 800px;word-break: break-all;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:250px;">Key</th>
|
||||
<th>English translation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="translation in translationSearch.existingTranslations | filter:translationSearch.searchTerm | limitTo: 1000">
|
||||
<td>{{ translation.label }}</td>
|
||||
<td>{{ translation.value }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*!
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* <div piwik-translation-search></div>
|
||||
*
|
||||
* Will show a text box which allows the user to search for translation keys and actual translations. Currently,
|
||||
* only english is supported.
|
||||
*/
|
||||
(function () {
|
||||
angular.module('piwikApp').directive('piwikTranslationSearch', piwikTranslationSearch);
|
||||
|
||||
piwikTranslationSearch.$inject = ['piwik'];
|
||||
|
||||
function piwikTranslationSearch(piwik){
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {},
|
||||
templateUrl: 'plugins/LanguagesManager/angularjs/translationsearch/translationsearch.directive.html?cb=' + piwik.cacheBuster,
|
||||
controller: 'TranslationSearchController',
|
||||
controllerAs: 'translationSearch'
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
var languageSelector = $("#languageSelection");
|
||||
|
||||
// no Language sector on the page
|
||||
if (languageSelector.size() == 0) return;
|
||||
|
||||
languageSelector.find("input").hide();
|
||||
var select = $("#language").hide();
|
||||
var langSelect = $("<a>")
|
||||
.insertAfter(select)
|
||||
.text(select.children(':selected').text())
|
||||
.autocomplete({
|
||||
delay: 0,
|
||||
position: { my : "right top", at: "right bottom" },
|
||||
minLength: 0,
|
||||
appendTo: '#languageSelection',
|
||||
source: function (request, response) {
|
||||
response(select.children("option").map(function () {
|
||||
var text = $(this).text();
|
||||
return {
|
||||
label: text,
|
||||
value: this.value,
|
||||
title: $(this).attr('title'),
|
||||
href: $(this).attr('href'),
|
||||
option: this
|
||||
};
|
||||
}));
|
||||
},
|
||||
select: function (event, ui) {
|
||||
event.preventDefault();
|
||||
ui.item.option.selected = true;
|
||||
if (ui.item.value) {
|
||||
langSelect.text(ui.item.label);
|
||||
$('#languageSelection').find('form').submit();
|
||||
} else if (ui.item.href) {
|
||||
window.open(ui.item.href);
|
||||
}
|
||||
}
|
||||
})
|
||||
.click(function () {
|
||||
// close if already visible
|
||||
if ($(this).autocomplete("widget").is(":visible")) {
|
||||
$(this).autocomplete("close");
|
||||
return;
|
||||
}
|
||||
|
||||
// pass empty string as value to search for, displaying all results
|
||||
$(this).autocomplete("search", "");
|
||||
});
|
||||
|
||||
langSelect.data( "ui-autocomplete" )._renderItem = function( ul, item ) {
|
||||
$(ul).attr('id', 'languageSelect');
|
||||
return $( "<li></li>" )
|
||||
.data( "item.ui-autocomplete", item )
|
||||
.append( "<a title=\"" + item.title + "\" href=\"javascript:;\">" + item.label + "</a>" )
|
||||
.appendTo( ul );
|
||||
};
|
||||
|
||||
$('body').on('mouseup', function (e) {
|
||||
if (!$(e.target).parents('#languageSelection').length && !$(e.target).is('#languageSelection') && !$(e.target).parents('#languageSelect').length) {
|
||||
langSelect.autocomplete("close");
|
||||
}
|
||||
});
|
||||
});
|
||||
5
www/analytics/plugins/LanguagesManager/lang/ar.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/ar.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "حول ترجمة Piwik"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/be.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/be.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Аб перакладах Piwik"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/bg.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/bg.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "За Piwik преводите"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/ca.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/ca.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Quant a les traduccions del Piwik",
|
||||
"TranslationSearch": "Cerca traduccions"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/cs.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/cs.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "O překladech Piwiku",
|
||||
"TranslationSearch": "Vyhledávání v překladech"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/da.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/da.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Om Piwik oversættelser",
|
||||
"TranslationSearch": "Oversættelse søgning"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/de.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/de.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Über Piwik Übersetzungen",
|
||||
"TranslationSearch": "Übersetzungssuche"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/el.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/el.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Πληροφόρηση",
|
||||
"TranslationSearch": "Αναζήτηση Μετάφρασης"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/en.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/en.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "About Piwik translations",
|
||||
"TranslationSearch": "Translation Search"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/es.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/es.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Acerca de las traducciones de Piwik",
|
||||
"TranslationSearch": "Buscar traducción"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/et.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/et.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Rohkem infot Piwiku tõlkimisest"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/fa.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/fa.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "درباره ترجمه های پیویک",
|
||||
"TranslationSearch": "جستجوی ترجمه"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/fi.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/fi.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Tietoja Piwikin käännöksistä",
|
||||
"TranslationSearch": "Käännösten haku"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/fr.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/fr.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "À propos des traductions de Piwik",
|
||||
"TranslationSearch": "Recherche de traduction"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/hi.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/hi.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Piwik अनुवाद के बारे में",
|
||||
"TranslationSearch": "अनुवाद खोजें"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/hu.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/hu.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "A Piwik fordításokról"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/id.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/id.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Tentang penerjemahan Piwik"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/is.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/is.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Um Þýðendur Piwik"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/it.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/it.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Riguardo alle traduzioni di Piwik",
|
||||
"TranslationSearch": "Ricerca Traduzione"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/ja.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/ja.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Piwik の翻訳について",
|
||||
"TranslationSearch": "翻訳の検索"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/ka.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/ka.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Piwik თარგმანების შესახებ"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/ko.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/ko.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Piwik 번역에 대해"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/lt.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/lt.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Apie Piwik vertimus"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/lv.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/lv.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Par Piwik tulkojumiem"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/nb.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/nb.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Om Piwik-oversettelser",
|
||||
"TranslationSearch": "Oversettelsessøk"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/nl.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/nl.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Over de Piwik vertalingen",
|
||||
"TranslationSearch": "Vertaling Zoeken"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/nn.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/nn.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Om Piwik-omsetjingane"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/pl.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/pl.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "O tłumaczeniach Piwik"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/pt-br.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/pt-br.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Sobre traduções do Piwik.",
|
||||
"TranslationSearch": "Pesquisa de tradução"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/pt.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/pt.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Acerca das traduções Piwik"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/ro.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/ro.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Despre traduceri Piwik"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/ru.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/ru.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "О переводах Piwik",
|
||||
"TranslationSearch": "Поиск перевода"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/sk.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/sk.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "O prekladoch Piwik"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/sl.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/sl.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "O prevodih Piwik-a"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/sq.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/sq.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Mbi përkthimet e Piwik-ut"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/sr.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/sr.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "O Piwik prevodima",
|
||||
"TranslationSearch": "Pretraživanje prevoda"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/sv.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/sv.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Om Piwik's översättningar",
|
||||
"TranslationSearch": "Sök översättning"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/te.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/te.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "పివిక్ అనువాదాల గురించి"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/th.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/th.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "เกี่ยวกับการแปล Piwik"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/tl.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/tl.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Tungkol sa pagsasaling ng Piwik",
|
||||
"TranslationSearch": "Paghahanap ng Pagsasalin"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/tr.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/tr.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Piwik çevirileri hakkında"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/uk.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/uk.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Про переклади Piwik"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/vi.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/vi.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "Về Piwik dịch"
|
||||
}
|
||||
}
|
||||
6
www/analytics/plugins/LanguagesManager/lang/zh-cn.json
Normal file
6
www/analytics/plugins/LanguagesManager/lang/zh-cn.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "关于 Piwik 翻译",
|
||||
"TranslationSearch": "交易搜索"
|
||||
}
|
||||
}
|
||||
5
www/analytics/plugins/LanguagesManager/lang/zh-tw.json
Normal file
5
www/analytics/plugins/LanguagesManager/lang/zh-tw.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"LanguagesManager": {
|
||||
"AboutPiwikTranslations": "關於 Piwik 翻譯"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,20 @@
|
|||
<span class="topBarElem">
|
||||
<span id="languageSelection">
|
||||
<form action="index.php?module=LanguagesManager&action=saveLanguage" method="post">
|
||||
<select name="language" id="language">
|
||||
<option title="" value=""
|
||||
href="?module=Proxy&action=redirect&url=http://piwik.org/translations/">{{ 'LanguagesManager_AboutPiwikTranslations'|translate }}</option>
|
||||
{% for language in languages %}
|
||||
<option value="{{ language.code }}" {% if language.code == currentLanguageCode %}selected="selected"{% endif %}
|
||||
title="{{ language.name }} ({{ language.english_name }})">{{ language.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="languageSelection"
|
||||
ng-cloak
|
||||
menu-title="{{ currentLanguageName|e('html_attr') }}"
|
||||
piwik-menudropdown>
|
||||
<a class="item"
|
||||
href="?module=Proxy&action=redirect&url=http://piwik.org/translations/">{{ 'LanguagesManager_AboutPiwikTranslations'|translate }}</a>
|
||||
{% for language in languages %}
|
||||
<a class="item {% if language.code == currentLanguageCode %}active{% endif %}"
|
||||
value="{{ language.code }}"
|
||||
title="{{ language.name }} ({{ language.english_name }})">{{ language.name }}</a>
|
||||
{% endfor %}
|
||||
|
||||
<form action="index.php?module=LanguagesManager&action=saveLanguage" method="post">
|
||||
<input type="hidden" name="language" id="language">
|
||||
{# During installation token_auth is not set #}
|
||||
{% if token_auth is defined %}<input type="hidden" name="token_auth" value="{{ token_auth }}"/>{% endif %}
|
||||
<input type="submit" value="go"/>
|
||||
</form>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'admin.twig' %}
|
||||
|
||||
{% set title %}{{ 'LanguagesManager_TranslationSearch'|translate }}{% endset %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h2 piwik-enriched-headline>{{ title }}</h2>
|
||||
|
||||
<div piwik-translation-search></div>
|
||||
|
||||
{% endblock %}
|
||||
Loading…
Add table
Add a link
Reference in a new issue