add icons for Character groups
This commit is contained in:
commit
2d9a41a5fe
3461 changed files with 594457 additions and 0 deletions
270
www/analytics/plugins/LanguagesManager/API.php
Normal file
270
www/analytics/plugins/LanguagesManager/API.php
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
<?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;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Db;
|
||||
use Piwik\Filesystem;
|
||||
use Piwik\Piwik;
|
||||
|
||||
/**
|
||||
* 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>!).
|
||||
* 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",
|
||||
* or update it via "setLanguageForUser".
|
||||
*
|
||||
* @method static \Piwik\Plugins\LanguagesManager\API getInstance()
|
||||
*/
|
||||
class API extends \Piwik\Plugin\API
|
||||
{
|
||||
protected $availableLanguageNames = null;
|
||||
protected $languageNames = null;
|
||||
|
||||
/**
|
||||
* Returns true if specified language is available
|
||||
*
|
||||
* @param string $languageCode
|
||||
* @return bool true if language available; false otherwise
|
||||
*/
|
||||
public function isLanguageAvailable($languageCode)
|
||||
{
|
||||
return $languageCode !== false
|
||||
&& Filesystem::isValidFilename($languageCode)
|
||||
&& in_array($languageCode, $this->getAvailableLanguages());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of available languages
|
||||
*
|
||||
* @return array Arry of strings, each containing its ISO language code
|
||||
*/
|
||||
public function getAvailableLanguages()
|
||||
{
|
||||
if (!is_null($this->languageNames)) {
|
||||
return $this->languageNames;
|
||||
}
|
||||
$path = PIWIK_INCLUDE_PATH . "/lang/";
|
||||
$languagesPath = _glob($path . "*.json");
|
||||
|
||||
$pathLength = strlen($path);
|
||||
$languages = array();
|
||||
if ($languagesPath) {
|
||||
foreach ($languagesPath as $language) {
|
||||
$languages[] = substr($language, $pathLength, -strlen('.json'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook called after loading available language files.
|
||||
*
|
||||
* Use this hook to customise the list of languagesPath available in Piwik.
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
Piwik::postEvent('LanguageManager.getAvailableLanguages', array(&$languages));
|
||||
|
||||
$this->languageNames = $languages;
|
||||
return $languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return information on translations (code, language, % translated, etc)
|
||||
*
|
||||
* @return array Array of arrays
|
||||
*/
|
||||
public function getAvailableLanguagesInfo()
|
||||
{
|
||||
$data = file_get_contents(PIWIK_INCLUDE_PATH . '/lang/en.json');
|
||||
$englishTranslation = json_decode($data, true);
|
||||
|
||||
// merge with plugin translations if any
|
||||
$pluginFiles = glob(sprintf('%s/plugins/*/lang/en.json', PIWIK_INCLUDE_PATH));
|
||||
foreach ($pluginFiles AS $file) {
|
||||
|
||||
$data = file_get_contents($file);
|
||||
$pluginTranslations = json_decode($data, true);
|
||||
$englishTranslation = array_merge_recursive($englishTranslation, $pluginTranslations);
|
||||
}
|
||||
|
||||
$filenames = $this->getAvailableLanguages();
|
||||
$languagesInfo = array();
|
||||
foreach ($filenames as $filename) {
|
||||
$data = file_get_contents(sprintf('%s/lang/%s.json', PIWIK_INCLUDE_PATH, $filename));
|
||||
$translations = json_decode($data, true);
|
||||
|
||||
// merge with plugin translations if any
|
||||
$pluginFiles = glob(sprintf('%s/plugins/*/lang/%s.json', PIWIK_INCLUDE_PATH, $filename));
|
||||
foreach ($pluginFiles AS $file) {
|
||||
|
||||
$data = file_get_contents($file);
|
||||
$pluginTranslations = json_decode($data, true);
|
||||
$translations = array_merge_recursive($translations, $pluginTranslations);
|
||||
}
|
||||
|
||||
$intersect = function ($array, $array2) {
|
||||
$res = $array;
|
||||
foreach ($array as $module => $keys) {
|
||||
if (!isset($array2[$module])) {
|
||||
unset($res[$module]);
|
||||
} else {
|
||||
$res[$module] = array_intersect_key($res[$module], array_filter($array2[$module], 'strlen'));
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
};
|
||||
$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'],
|
||||
'translators' => $translations['General']['TranslatorName'],
|
||||
'translators_email' => $translations['General']['TranslatorEmail'],
|
||||
'percentage_complete' => $percentageComplete . '%',
|
||||
);
|
||||
$languagesInfo[] = $languageInfo;
|
||||
}
|
||||
return $languagesInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of available languages
|
||||
*
|
||||
* @return array Arry of array, each containing its ISO language code and name of the language
|
||||
*/
|
||||
public function getAvailableLanguageNames()
|
||||
{
|
||||
$this->loadAvailableLanguages();
|
||||
return $this->availableLanguageNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns translation strings by language
|
||||
*
|
||||
* @param string $languageCode ISO language code
|
||||
* @return array|false Array of arrays, each containing 'label' (translation index) and 'value' (translated string); false if language unavailable
|
||||
*/
|
||||
public function getTranslationsForLanguage($languageCode)
|
||||
{
|
||||
if (!$this->isLanguageAvailable($languageCode)) {
|
||||
return false;
|
||||
}
|
||||
$data = file_get_contents(PIWIK_INCLUDE_PATH . "/lang/$languageCode.json");
|
||||
$translations = json_decode($data, true);
|
||||
$languageInfo = array();
|
||||
foreach ($translations as $module => $keys) {
|
||||
foreach ($keys as $key => $value) {
|
||||
$languageInfo[] = array(
|
||||
'label' => sprintf("%s_%s", $module, $key),
|
||||
'value' => $value
|
||||
);
|
||||
}
|
||||
}
|
||||
return $languageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns translation strings by language for given plugin
|
||||
*
|
||||
* @param string $pluginName name of plugin
|
||||
* @param string $languageCode ISO language code
|
||||
* @return array|false Array of arrays, each containing 'label' (translation index) and 'value' (translated string); false if language unavailable
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
public function getPluginTranslationsForLanguage($pluginName, $languageCode)
|
||||
{
|
||||
if (!$this->isLanguageAvailable($languageCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$languageFile = PIWIK_INCLUDE_PATH . "/plugins/$pluginName/lang/$languageCode.json";
|
||||
|
||||
if (!file_exists($languageFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = file_get_contents($languageFile);
|
||||
$translations = json_decode($data, true);
|
||||
$languageInfo = array();
|
||||
foreach ($translations as $module => $keys) {
|
||||
foreach ($keys as $key => $value) {
|
||||
$languageInfo[] = array(
|
||||
'label' => sprintf("%s_%s", $module, $key),
|
||||
'value' => $value
|
||||
);
|
||||
}
|
||||
}
|
||||
return $languageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the language for the user
|
||||
*
|
||||
* @param string $login
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguageForUser($login)
|
||||
{
|
||||
if($login == 'anonymous') {
|
||||
return false;
|
||||
}
|
||||
Piwik::checkUserHasSuperUserAccessOrIsTheUser($login);
|
||||
return Db::fetchOne('SELECT language FROM ' . Common::prefixTable('user_language') .
|
||||
' WHERE login = ? ', array($login));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the language for the user
|
||||
*
|
||||
* @param string $login
|
||||
* @param string $languageCode
|
||||
* @return bool
|
||||
*/
|
||||
public function setLanguageForUser($login, $languageCode)
|
||||
{
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
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']
|
||||
);
|
||||
}
|
||||
$this->availableLanguageNames = $languagesInfo;
|
||||
}
|
||||
}
|
||||
220
www/analytics/plugins/LanguagesManager/Commands/CreatePull.php
Normal file
220
www/analytics/plugins/LanguagesManager/Commands/CreatePull.php
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
<?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\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;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class CreatePull extends ConsoleCommand
|
||||
{
|
||||
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('plugin', 'P', InputOption::VALUE_OPTIONAL, 'optional name of plugin to update translations for');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$changes = shell_exec('git status --porcelain -uno');
|
||||
|
||||
if (!empty($changes)) {
|
||||
|
||||
$output->writeln("You have uncommited changes. Creating pull request is only available with a clean working directory");
|
||||
return;
|
||||
}
|
||||
|
||||
$unpushedCommits = shell_exec('git log origin/master..HEAD');
|
||||
|
||||
if (!empty($unpushedCommits)) {
|
||||
|
||||
$output->writeln("You have unpushed commits. Creating pull request is only available with a clean working directory");
|
||||
return;
|
||||
}
|
||||
|
||||
chdir(PIWIK_DOCUMENT_ROOT);
|
||||
|
||||
shell_exec('
|
||||
git checkout 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
|
||||
');
|
||||
|
||||
$plugin = $input->getOption('plugin');
|
||||
if (!empty($plugin)) {
|
||||
|
||||
chdir(PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR.'plugins'.DIRECTORY_SEPARATOR.$plugin);
|
||||
shell_exec('
|
||||
git checkout master > /dev/null 2>&1
|
||||
git pull > /dev/null 2>&1
|
||||
');
|
||||
}
|
||||
|
||||
// check if branch exists localy and track it if not
|
||||
$branch = shell_exec('git branch | grep translationupdates');
|
||||
|
||||
if (empty($branch)) {
|
||||
|
||||
shell_exec('git checkout -b translationupdates origin/translationupdates');
|
||||
}
|
||||
|
||||
// switch to branch and update it to latest master
|
||||
shell_exec('
|
||||
git checkout translationupdates > /dev/null 2>&1
|
||||
git merge master > /dev/null 2>&1
|
||||
git push origin translationupdates > /dev/null 2>&1
|
||||
');
|
||||
|
||||
// update translation files
|
||||
$command = $this->getApplication()->find('translations:update');
|
||||
$arguments = array(
|
||||
'command' => 'translations:update',
|
||||
'--username' => $input->getOption('username'),
|
||||
'--password' => $input->getOption('password'),
|
||||
'--plugin' => $plugin
|
||||
);
|
||||
$inputObject = new ArrayInput($arguments);
|
||||
$inputObject->setInteractive($input->isInteractive());
|
||||
$command->run($inputObject, $output);
|
||||
|
||||
shell_exec('git add lang/. > /dev/null 2>&1');
|
||||
|
||||
if (empty($plugin)) {
|
||||
foreach (Update::getPluginsInCore() AS $pluginName) {
|
||||
shell_exec(sprintf('git add plugins/%s/lang/. > /dev/null 2>&1', $pluginName));
|
||||
}
|
||||
}
|
||||
|
||||
$changes = shell_exec('git status --porcelain -uno');
|
||||
|
||||
if (empty($changes)) {
|
||||
|
||||
$output->writeln("Nothing changed. Everything is already up to date.");
|
||||
shell_exec('git checkout master > /dev/null 2>&1');
|
||||
return;
|
||||
}
|
||||
|
||||
API::unsetInstance(); // reset languagemanager api (to force refresh of data)
|
||||
|
||||
$stats = shell_exec('git diff --numstat HEAD');
|
||||
|
||||
preg_match_all('/([0-9]+)\t([0-9]+)\t[a-zA-Z\/]*lang\/([a-z]{2,3})\.json/', $stats, $lineChanges);
|
||||
|
||||
$addedLinesSum = 0;
|
||||
if (!empty($lineChanges[1])) {
|
||||
$addedLinesSum = array_sum($lineChanges[1]);
|
||||
}
|
||||
|
||||
$linesSumByLang = array();
|
||||
for($i=0; $i<count($lineChanges[0]); $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);
|
||||
|
||||
$messages = array();
|
||||
|
||||
$languageCodesTouched = array();
|
||||
if (!empty($addedFiles[1])) {
|
||||
foreach ($addedFiles[1] AS $addedFile) {
|
||||
$languageInfo = $this->getLanguageInfoByIsoCode($addedFile);
|
||||
$messages[$addedFile] = sprintf('- Added %s (%s changes / %s translated)\n', $languageInfo['english_name'], $linesSumByLang[$addedFile], $languageInfo['percentage_complete']);
|
||||
}
|
||||
$languageCodesTouched = array_merge($languageCodesTouched, $addedFiles[1]);
|
||||
}
|
||||
|
||||
if (!empty($modifiedFiles[1])) {
|
||||
foreach ($modifiedFiles[1] AS $modifiedFile) {
|
||||
$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];
|
||||
}
|
||||
|
||||
$message = implode('', $messages);
|
||||
|
||||
$languageCodesTouched = array_unique($languageCodesTouched, SORT_REGULAR);
|
||||
|
||||
$title = sprintf(
|
||||
'Updated %s strings in %u languages (%s)',
|
||||
$addedLinesSum,
|
||||
count($languageCodesTouched),
|
||||
implode(', ', $languageCodesTouched)
|
||||
);
|
||||
|
||||
shell_exec('git commit -m "language update ${pluginName} refs #3430"');
|
||||
shell_exec('git push');
|
||||
shell_exec('git checkout master > /dev/null 2>&1');
|
||||
|
||||
$this->createPullRequest($output, $title, $message);
|
||||
}
|
||||
|
||||
private function getLanguageInfoByIsoCode($isoCode)
|
||||
{
|
||||
$languages = API::getInstance()->getAvailableLanguagesInfo();
|
||||
foreach ($languages AS $languageInfo) {
|
||||
if ($languageInfo['code'] == $isoCode) {
|
||||
return $languageInfo;
|
||||
}
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
private function createPullRequest(OutputInterface $output, $title, $message)
|
||||
{
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
|
||||
while (true) {
|
||||
|
||||
$username = $dialog->ask($output, 'Please provide your github username (to create a pull request using Github API): ');
|
||||
|
||||
$returnCode = shell_exec('curl \
|
||||
-X POST \
|
||||
-k \
|
||||
--silent \
|
||||
--write-out %{http_code} \
|
||||
--stderr /dev/null \
|
||||
-o /dev/null \
|
||||
-u '.$username.' \
|
||||
--data "{\"title\":\"[automatic translation update] '.$title.'\",\"body\":\"'.$message.'\",\"head\":\"translationupdates\",\"base\":\"master\"}" \
|
||||
-H "Accept: application/json" \
|
||||
https://api.github.com/repos/piwik/piwik/pulls');
|
||||
|
||||
switch ($returnCode) {
|
||||
case 401:
|
||||
$output->writeln("Pull request failed. Bad credentials... Please try again");
|
||||
continue;
|
||||
|
||||
case 422:
|
||||
$output->writeln("Pull request failed. Unprocessable Entity. Maybe a pull request was already created before.");
|
||||
return;
|
||||
|
||||
case 201:
|
||||
case 200:
|
||||
$output->writeln("Pull request successfully created.");
|
||||
return;
|
||||
|
||||
default:
|
||||
$output->writeln("Pull request failed... Please try again");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
<?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,41 @@
|
|||
<?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\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class LanguageCodes extends ConsoleCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:languagecodes')
|
||||
->setDescription('Shows available language codes');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageCodes = array();
|
||||
foreach ($languages AS $languageInfo) {
|
||||
$languageCodes[] = $languageInfo['code'];
|
||||
}
|
||||
|
||||
sort($languageCodes);
|
||||
|
||||
$output->writeln("Currently available languages:");
|
||||
$output->writeln(implode("\n", $languageCodes));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?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\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class LanguageNames extends ConsoleCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:languagenames')
|
||||
->setDescription('Shows available language names');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageNames = array();
|
||||
foreach ($languages AS $languageInfo) {
|
||||
$languageNames[] = $languageInfo['english_name'];
|
||||
}
|
||||
|
||||
sort($languageNames);
|
||||
|
||||
$output->writeln("Currently available languages:");
|
||||
$output->writeln(implode("\n", $languageNames));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?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 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
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:plugins')
|
||||
->setDescription('Shows all plugins that have own translation files');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->writeln("Following plugins contain their own translation files:");
|
||||
|
||||
$pluginFiles = glob(sprintf('%s/plugins/*/lang/en.json', PIWIK_INCLUDE_PATH));
|
||||
$pluginFiles = array_map(function($elem){
|
||||
return str_replace(array(sprintf('%s/plugins/', PIWIK_INCLUDE_PATH), '/lang/en.json'), '', $elem);
|
||||
}, $pluginFiles);
|
||||
|
||||
$output->writeln(join("\n", $pluginFiles));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
<?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\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 Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class SetTranslations extends ConsoleCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('translations:set')
|
||||
->setDescription('Sets new translations for a given language')
|
||||
->addOption('code', 'c', InputOption::VALUE_REQUIRED, 'code of the language to set translations for')
|
||||
->addOption('file', 'f', InputOption::VALUE_REQUIRED, 'json file to load new translations from')
|
||||
->addOption('plugin', 'pl', InputOption::VALUE_OPTIONAL, 'optional name of plugin to set translations for');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
|
||||
$languageCode = $input->getOption('code');
|
||||
$filename = $input->getOption('file');
|
||||
|
||||
$languageCodes = API::getInstance()->getAvailableLanguages();
|
||||
|
||||
if (empty($languageCode) || !in_array($languageCode, $languageCodes)) {
|
||||
$languageCode = $dialog->askAndValidate($output, 'Please provide a valid language code: ', function ($code) use ($languageCodes) {
|
||||
if (!in_array($code, array_values($languageCodes))) {
|
||||
throw new \InvalidArgumentException(sprintf('Language code "%s" is invalid.', $code));
|
||||
}
|
||||
|
||||
return $code;
|
||||
});
|
||||
}
|
||||
|
||||
if (empty($filename) || !file_exists($filename)) {
|
||||
$filename = $dialog->askAndValidate($output, 'Please provide a file to load translations from: ', function ($file) {
|
||||
if (!file_exists($file)) {
|
||||
throw new \InvalidArgumentException(sprintf('File "%s" does not exist.', $file));
|
||||
}
|
||||
|
||||
return $file;
|
||||
});
|
||||
}
|
||||
|
||||
$output->writeln("Starting to import data from '$filename' to language '$languageCode'");
|
||||
|
||||
$plugin = $input->getOption('plugin');
|
||||
$translationWriter = new Writer($languageCode, $plugin);
|
||||
|
||||
$baseTranslations = $translationWriter->getTranslations("en");
|
||||
|
||||
$translationWriter->addValidator(new NoScripts());
|
||||
if (empty($plugin)) {
|
||||
$translationWriter->addValidator(new CoreTranslations($baseTranslations));
|
||||
}
|
||||
|
||||
$translationWriter->addFilter(new ByBaseTranslations($baseTranslations));
|
||||
$translationWriter->addFilter(new EmptyTranslations());
|
||||
$translationWriter->addFilter(new ByParameterCount($baseTranslations));
|
||||
$translationWriter->addFilter(new UnnecassaryWhitespaces($baseTranslations));
|
||||
$translationWriter->addFilter(new EncodedEntities());
|
||||
|
||||
$translationData = file_get_contents($filename);
|
||||
$translations = json_decode($translationData, true);
|
||||
|
||||
$translationWriter->setTranslations($translations);
|
||||
|
||||
if (!$translationWriter->isValid()) {
|
||||
$output->writeln("Failed setting translations:" . $translationWriter->getValidationMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$translationWriter->hasTranslations()) {
|
||||
$output->writeln("No translations available");
|
||||
return;
|
||||
}
|
||||
|
||||
$translationWriter->save();
|
||||
|
||||
$output->writeln("Finished.");
|
||||
}
|
||||
}
|
||||
162
www/analytics/plugins/LanguagesManager/Commands/Update.php
Normal file
162
www/analytics/plugins/LanguagesManager/Commands/Update.php
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
<?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\Plugins\LanguagesManager\API;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\NullOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
*/
|
||||
class Update extends ConsoleCommand
|
||||
{
|
||||
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('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');
|
||||
|
||||
$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);
|
||||
|
||||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
|
||||
$languageCodes = array();
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$progress->finish();
|
||||
$output->writeln("Finished.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all plugins having their own translations that are bundled in core
|
||||
* @return array
|
||||
*/
|
||||
public static function getPluginsInCore()
|
||||
{
|
||||
static $pluginsInCore;
|
||||
|
||||
if (!empty($pluginsInCore)) {
|
||||
return $pluginsInCore;
|
||||
}
|
||||
|
||||
$submodules = shell_exec('git submodule status');
|
||||
preg_match_all('/plugins\/([a-zA-z]+) /', $submodules, $matches);
|
||||
$submodulePlugins = $matches[1];
|
||||
|
||||
// ignore complete new plugins aswell
|
||||
$changes = shell_exec('git status');
|
||||
preg_match_all('/plugins\/([a-zA-z]+)\/\n/', $changes, $matches);
|
||||
$newPlugins = $matches[1];
|
||||
|
||||
$pluginsNotInCore = array_merge($submodulePlugins, $newPlugins);
|
||||
|
||||
$pluginsWithTranslations = glob(sprintf('%s/plugins/*/lang/en.json', PIWIK_INCLUDE_PATH));
|
||||
$pluginsWithTranslations = array_map(function($elem){
|
||||
return str_replace(array(sprintf('%s/plugins/', PIWIK_INCLUDE_PATH), '/lang/en.json'), '', $elem);
|
||||
}, $pluginsWithTranslations);
|
||||
|
||||
$pluginsInCore = array_diff($pluginsWithTranslations, $pluginsNotInCore);
|
||||
|
||||
return $pluginsInCore;
|
||||
}
|
||||
}
|
||||
37
www/analytics/plugins/LanguagesManager/Controller.php
Normal file
37
www/analytics/plugins/LanguagesManager/Controller.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?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;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\DbHelper;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Url;
|
||||
|
||||
/**
|
||||
*/
|
||||
class Controller extends \Piwik\Plugin\Controller
|
||||
{
|
||||
/**
|
||||
* anonymous = in the session
|
||||
* authenticated user = in the session
|
||||
*/
|
||||
public function saveLanguage()
|
||||
{
|
||||
$language = Common::getRequestVar('language');
|
||||
|
||||
// Prevent CSRF only when piwik is not installed yet (During install user can change language)
|
||||
if (DbHelper::isInstalled()) {
|
||||
$this->checkTokenInUrl();
|
||||
}
|
||||
|
||||
LanguagesManager::setLanguageForSession($language);
|
||||
Url::redirectToReferrer();
|
||||
}
|
||||
}
|
||||
213
www/analytics/plugins/LanguagesManager/LanguagesManager.php
Normal file
213
www/analytics/plugins/LanguagesManager/LanguagesManager.php
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
<?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;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Common;
|
||||
use Piwik\Config;
|
||||
|
||||
use Piwik\Cookie;
|
||||
use Piwik\Db;
|
||||
use Piwik\DbHelper;
|
||||
use Piwik\Menu\MenuTop;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Translate;
|
||||
use Piwik\View;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class LanguagesManager extends \Piwik\Plugin
|
||||
{
|
||||
/**
|
||||
* @see Piwik\Plugin::getListHooksRegistered
|
||||
*/
|
||||
public function getListHooksRegistered()
|
||||
{
|
||||
return array(
|
||||
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
|
||||
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
|
||||
'Menu.Top.addItems' => 'showLanguagesSelector',
|
||||
'User.getLanguage' => 'getLanguageToLoad',
|
||||
'UsersManager.deleteUser' => 'deleteUserLanguage',
|
||||
'Template.topBar' => 'addLanguagesManagerToOtherTopBar',
|
||||
'Template.jsGlobalVariables' => 'jsGlobalVariables'
|
||||
);
|
||||
}
|
||||
|
||||
public function getStylesheetFiles(&$stylesheets)
|
||||
{
|
||||
$stylesheets[] = "plugins/Zeitgeist/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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the languages drop-down list to topbars other than the main one rendered
|
||||
* in CoreHome/templates/top_bar.twig. The 'other' topbars are on the Installation
|
||||
* and CoreUpdater screens.
|
||||
*/
|
||||
public function addLanguagesManagerToOtherTopBar(&$str)
|
||||
{
|
||||
// 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 .= $this->getLanguagesSelector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the languages drop-down list to topbars other than the main one rendered
|
||||
* in CoreHome/templates/top_bar.twig. The 'other' topbars are on the Installation
|
||||
* and CoreUpdater screens.
|
||||
*/
|
||||
public function jsGlobalVariables(&$str)
|
||||
{
|
||||
// piwik object & scripts aren't loaded in 'other' topbars
|
||||
$str .= "piwik.languageName = '" . self::getLanguageNameForCurrentUser() . "';";
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders and returns the language selector HTML.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getLanguagesSelector()
|
||||
{
|
||||
$view = new View("@LanguagesManager/getLanguagesSelector");
|
||||
$view->languages = API::getInstance()->getAvailableLanguageNames();
|
||||
$view->currentLanguageCode = self::getLanguageCodeForCurrentUser();
|
||||
return $view->render();
|
||||
}
|
||||
|
||||
function getLanguageToLoad(&$language)
|
||||
{
|
||||
if (empty($language)) {
|
||||
$language = self::getLanguageCodeForCurrentUser();
|
||||
}
|
||||
if (!API::getInstance()->isLanguageAvailable($language)) {
|
||||
$language = Translate::getLanguageDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteUserLanguage($userLogin)
|
||||
{
|
||||
Db::query('DELETE FROM ' . Common::prefixTable('user_language') . ' WHERE login = ?', $userLogin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception if non-recoverable error
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
$userLanguage = "login VARCHAR( 100 ) NOT NULL ,
|
||||
language VARCHAR( 10 ) NOT NULL ,
|
||||
PRIMARY KEY ( login )";
|
||||
DbHelper::createTable('user_language', $userLanguage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception if non-recoverable error
|
||||
*/
|
||||
public function uninstall()
|
||||
{
|
||||
Db::dropTables(Common::prefixTable('user_language'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Two letters language code, eg. "fr"
|
||||
*/
|
||||
static public function getLanguageCodeForCurrentUser()
|
||||
{
|
||||
$languageCode = self::getLanguageFromPreferences();
|
||||
if (!API::getInstance()->isLanguageAvailable($languageCode)) {
|
||||
$languageCode = Common::extractLanguageCodeFromBrowserLanguage(Common::getBrowserLanguage(), API::getInstance()->getAvailableLanguages());
|
||||
}
|
||||
if (!API::getInstance()->isLanguageAvailable($languageCode)) {
|
||||
$languageCode = Translate::getLanguageDefault();
|
||||
}
|
||||
return $languageCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Full english language string, eg. "French"
|
||||
*/
|
||||
static public function getLanguageNameForCurrentUser()
|
||||
{
|
||||
$languageCode = self::getLanguageCodeForCurrentUser();
|
||||
$languages = API::getInstance()->getAvailableLanguageNames();
|
||||
foreach ($languages as $language) {
|
||||
if ($language['code'] === $languageCode) {
|
||||
return $language['name'];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|false if language preference could not be loaded
|
||||
*/
|
||||
static protected function getLanguageFromPreferences()
|
||||
{
|
||||
if (($language = self::getLanguageForSession()) != null) {
|
||||
return $language;
|
||||
}
|
||||
|
||||
try {
|
||||
$currentUser = Piwik::getCurrentUserLogin();
|
||||
return API::getInstance()->getLanguageForUser($currentUser);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the language for the session
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
static public function getLanguageForSession()
|
||||
{
|
||||
$cookieName = Config::getInstance()->General['language_cookie_name'];
|
||||
$cookie = new Cookie($cookieName);
|
||||
if ($cookie->isCookieFound()) {
|
||||
return $cookie->get('language');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the language for the session
|
||||
*
|
||||
* @param string $languageCode ISO language code
|
||||
* @return bool
|
||||
*/
|
||||
static public function setLanguageForSession($languageCode)
|
||||
{
|
||||
if (!API::getInstance()->isLanguageAvailable($languageCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cookieName = Config::getInstance()->General['language_cookie_name'];
|
||||
$cookie = new Cookie($cookieName, 0);
|
||||
$cookie->set('language', $languageCode);
|
||||
$cookie->save();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*!
|
||||
* 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");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<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>
|
||||
{# 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>
|
||||
</span>
|
||||
Loading…
Add table
Add a link
Reference in a new issue