Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/translations.yml156
-rw-r--r--README.md6
-rw-r--r--core/Translation/Weblate/API.php (renamed from core/Translation/Transifex/API.php)68
-rw-r--r--lang/README.md4
m---------plugins/Bandwidth0
m---------plugins/CustomAlerts0
m---------plugins/CustomVariables0
m---------plugins/DeviceDetectorCache0
-rw-r--r--plugins/Intl/Commands/GenerateIntl.php28
-rw-r--r--plugins/LanguagesManager/API.php51
-rw-r--r--plugins/LanguagesManager/Commands/CreatePull.php233
-rw-r--r--plugins/LanguagesManager/Commands/FetchTranslations.php45
-rw-r--r--plugins/LanguagesManager/Commands/LanguageCodes.php4
-rw-r--r--plugins/LanguagesManager/Commands/LanguageInfo.php4
-rw-r--r--plugins/LanguagesManager/Commands/LanguageNames.php4
-rw-r--r--plugins/LanguagesManager/Commands/SetTranslations.php2
-rw-r--r--plugins/LanguagesManager/Commands/Update.php35
-rw-r--r--plugins/LanguagesManager/Commands/Validate.php17
-rw-r--r--plugins/LanguagesManager/tests/Integration/LanguagesManagerTest.php2
m---------plugins/LogViewer0
m---------plugins/LoginLdap0
m---------plugins/MarketingCampaignsReporting0
m---------plugins/Provider0
m---------plugins/QueuedTracking0
m---------plugins/SecurityInfo0
m---------plugins/TagManager0
m---------plugins/TasksTimetable0
m---------plugins/TrackingSpamPrevention0
m---------plugins/VisitorGenerator0
-rw-r--r--tests/PHPUnit/System/expected/test_apiGetReportMetadata_year__LanguagesManager.getAvailableLanguageNames.xml3
-rw-r--r--tests/PHPUnit/System/expected/test_reportLimitingdimension_2_rankingQuery__CustomDimensions.getCustomDimension_day.xml4
-rw-r--r--tests/PHPUnit/Unit/Translation/FilesTest.php2
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_admin_diagnostics_configfile.png4
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png4
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png4
35 files changed, 145 insertions, 535 deletions
diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml
deleted file mode 100644
index 61567a4d37..0000000000
--- a/.github/workflows/translations.yml
+++ /dev/null
@@ -1,156 +0,0 @@
-name: Translation Updates
-
-on:
- workflow_dispatch:
- schedule:
- - cron: "0 2 * * 6"
-
-permissions:
- actions: read
- checks: none
- contents: write
- deployments: none
- issues: read
- packages: none
- pull-requests: write
- repository-projects: none
- security-events: none
- statuses: none
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- services:
- mysql:
- image: mysql:5.7
- env:
- MYSQL_ALLOW_EMPTY_PASSWORD: true
- MYSQL_ROOT_PASSWORD: ""
- MYSQL_DATABASE: piwik_tests
- ports:
- - 3306/tcp
-
-
- steps:
- - uses: shivammathur/setup-php@36cb9fb0fccf887130d6c5a3d40a3b3479310026
- with:
- php-version: '7.3'
- - uses: actions/checkout@v2
- with:
- ref: '4.x-dev'
- lfs: false
- - name: Prepare branches
- run: |
- cat <<- EOF > $HOME/.netrc
- machine github.com
- login $GITHUB_ACTOR
- password $GITHUB_TOKEN
- machine api.github.com
- login $GITHUB_ACTOR
- password $GITHUB_TOKEN
- EOF
- chmod 600 $HOME/.netrc
-
- git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"
- git config --global user.name "$GITHUB_ACTOR"
-
- git remote add upstream https://github.com/matomo-org/matomo.git
-
- git push origin --delete translationupdates || true
- git branch -D translationupdates || true
- git fetch upstream 4.x-dev
- git checkout -f upstream/4.x-dev
- git branch translationupdates
- git checkout -f translationupdates
- - name: Checkout submodules
- run: git submodule update --init --force
- - name: Install Dependencies
- run: composer install --prefer-dist
- - name: Initialize Matomo
- run: |
- cp ./tests/travis/config.ini.travis.php ./config/config.ini.php
- ./console development:enable
- - name: Sync translations
- run: ./console translations:update --username ${{ secrets.TransifexUsername }} --password ${{ secrets.TransifexPassword }} --force --no-interaction
- - name: Check for changes
- id: changes
- run: |
- git add lang/
- git add "*.json"
- IFS=$'\n'
- changes=( $(git diff --numstat HEAD | grep -E '([0-9]+)\s+([0-9]+)\s+[a-zA-Z\/]*lang\/([a-z]{2,3}(-[a-z]{2,3})?)\.json' ) )
- unset IFS
-
- # abort here if no change available
- if [[ ${#changes[@]} -eq 0 ]]
- then
- exit 0
- fi
-
- declare -i totaladditions=0
- declare -A additionsByLang
-
- for (( i=0; i < ${#changes[@]}; i++ )); do
- line=( ${changes[$i]} )
- additions=${line[0]}
-
- if [[ ${line[0]} = "0" ]]
- then
- continue;
- fi
-
- file=${line[2]}
- lang=$( echo ${line[2]} | grep -oE '([a-z]{2,3}(-[a-z]{2,3})?)\.json' | cut -d'.' -f 1 )
-
- totaladditions=$(( totaladditions + additions ))
- additionsByLang[$lang]=$(( additionsByLang[$lang] + additions ))
- done
-
- title="Updated $totaladditions strings in ${#additionsByLang[@]} languages (${!additionsByLang[@]})"
-
- languageInfo=( $( ./console translations:languageinfo | tr " " "_" ) )
-
- for i in ${!additionsByLang[@]}; do
- for j in ${languageInfo[@]}; do
- if [[ "$j" == "$i|"* ]];
- then
- IFS=$'\n'
- info=( $( echo "$j" | tr "|" "\n" ) )
- unset IFS
- break
- fi
- done
-
- name=$( echo ${info[1]} | tr "_" " " )
- message="$message- Updated $name (${additionsByLang[$i]} changes / ${info[2]} translated)\n"
- done
-
- message="$message\n\nHelp us translate Matomo in your language!\nSignup at https://www.transifex.com/matomo/matomo/\nIf you have any questions, get in touch with us at translations@matomo.org"
-
- echo $title
- echo $message
-
- echo ::set-output name=title::$title
- echo ::set-output name=message::$message
- shell: bash
- - name: Push changes
- run: |
- git commit -m "language update"
- git push --set-upstream origin translationupdates
- - name: Create PR
- run: |
- curl \
- --request POST \
- --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \
- --header 'content-type: application/json' \
- --data '{
- "title":"[automatic translation update] ${{ steps.changes.outputs.title }}",
- "body":"${{ steps.changes.outputs.message }}",
- "head":"translationupdates",
- "base":"4.x-dev"
- }' \
- --url https://api.github.com/repos/${GITHUB_REPOSITORY}/pulls
- shell: bash
- if: steps.changes.outputs.title
diff --git a/README.md b/README.md
index 3ad3d7d7c2..726dc87d44 100644
--- a/README.md
+++ b/README.md
@@ -69,6 +69,12 @@ For the list of all tickets closed in the current and past releases, see [matomo
We believe in liberating Web Analytics, providing a free platform for simple and advanced analytics. Matomo was built by dozens of people like you,
and we need your help to make Matomo better… Why not participate in a useful project today? [Learn how you can contribute to Matomo](https://matomo.org/get-involved).
+## Translations
+
+Our translations are managed on [Weblate](https://hosted.weblate.org/engage/matomo/).
+
+[![Translation Status](https://hosted.weblate.org/widgets/matomo/-/horizontal-auto.svg)](https://hosted.weblate.org/engage/matomo/)
+
## Quality Assurance
The Matomo project uses an ever-expanding comprehensive set of thousands of unit tests and hundreds of automated integration tests, system tests, JavaScript tests, and screenshot UI tests, running on a continuous integration server as part of its software quality assurance. [Learn more](https://developer.matomo.org/guides/tests).
diff --git a/core/Translation/Transifex/API.php b/core/Translation/Weblate/API.php
index b6bcfbed04..dad14ee6ac 100644
--- a/core/Translation/Transifex/API.php
+++ b/core/Translation/Weblate/API.php
@@ -6,7 +6,7 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
-namespace Piwik\Translation\Transifex;
+namespace Piwik\Translation\Weblate;
use Exception;
use Piwik\Cache;
@@ -15,40 +15,51 @@ use Piwik\Http;
class API
{
- protected $apiUrl = 'https://www.transifex.com/api/2/';
- protected $username = '';
- protected $password = '';
+ protected $apiUrl = 'https://hosted.weblate.org/api/';
+ protected $apiToken = '';
protected $projectSlug = '';
- public function __construct($username, $password, $project = 'matomo')
+ public function __construct($apiToken, $project = 'matomo')
{
- $this->username = $username;
- $this->password = $password;
+ $this->apiToken = $apiToken;
$this->projectSlug = $project;
}
/**
- * Returns all resources available on Transifex project
+ * Returns all resources available on Weblate project
*
* @return array
*/
public function getAvailableResources()
{
$cache = Cache::getTransientCache();
- $cacheId = 'transifex_resources_' . $this->projectSlug;
- $resources = $cache->fetch($cacheId);
+ $cacheId = 'weblate_resources_' . $this->projectSlug;
+ $result = $cache->fetch($cacheId);
- if (empty($resources)) {
- $apiPath = 'project/' . $this->projectSlug . '/resources';
+ if (empty($result)) {
+ $apiPath = 'projects/' . $this->projectSlug . '/components/';
$resources = $this->getApiResults($apiPath);
- $cache->save($cacheId, $resources);
+ $result = [];
+
+ while($resources->results) {
+ $result = array_merge($result, $resources->results);
+
+ if ($resources->next) {
+ $apiPath = str_replace($this->apiUrl, '', $resources->next);
+ $resources = $this->getApiResults($apiPath);
+ } else {
+ break;
+ }
+ }
+
+ $cache->save($cacheId, $result);
}
- return $resources;
+ return $result;
}
/**
- * Checks if the given resource exists in Transifex project
+ * Checks if the given resource exists in Weblate project
*
* @param string $resource
* @return bool
@@ -65,7 +76,7 @@ class API
}
/**
- * Returns all language codes the transifex project is available for
+ * Returns all language codes the Weblate project is available for
*
* @return array
* @throws AuthenticationFailedException
@@ -74,13 +85,13 @@ class API
public function getAvailableLanguageCodes()
{
$cache = Cache::getTransientCache();
- $cacheId = 'transifex_languagescodes_' . $this->projectSlug;
+ $cacheId = 'weblate_languagescodes_' . $this->projectSlug;
$languageCodes = $cache->fetch($cacheId);
if (empty($languageCodes)) {
- $apiData = $this->getApiResults('project/' . $this->projectSlug . '/languages');
+ $apiData = $this->getApiResults('projects/' . $this->projectSlug . '/languages/');
foreach ($apiData as $languageData) {
- $languageCodes[] = $languageData->language_code;
+ $languageCodes[] = $languageData->code;
}
$cache->save($cacheId, $languageCodes);
}
@@ -88,19 +99,6 @@ class API
}
/**
- * Returns statistic data for the given resource
- *
- * @param string $resource e.g. piwik-base, piwik-plugin-api,...
- * @return array
- * @throws AuthenticationFailedException
- * @throws Exception
- */
- public function getStatistics($resource)
- {
- return $this->getApiResults('project/' . $this->projectSlug . '/resource/' . $resource . '/stats/');
- }
-
- /**
* Return the translations for the given resource and language
*
* @param string $resource e.g. piwik-base, piwik-plugin-api,...
@@ -113,7 +111,7 @@ class API
public function getTranslations($resource, $language, $raw = false)
{
if ($this->resourceExists($resource)) {
- $apiPath = 'project/' . $this->projectSlug . '/resource/' . $resource . '/translation/' . $language . '/?mode=onlytranslated&file';
+ $apiPath = 'translations/' . $this->projectSlug . '/' . $resource . '/' . $language . '/file/';
return $this->getApiResults($apiPath, $raw);
}
return null;
@@ -132,7 +130,9 @@ class API
{
$apiUrl = $this->apiUrl . $apiPath;
- $response = Http::sendHttpRequest($apiUrl, 1000, null, null, 5, false, false, true, 'GET', $this->username, $this->password);
+ $response = Http::sendHttpRequestBy(Http::getTransportMethod(), $apiUrl, 60, null, null, null, 5, false,
+ false, false, true, 'GET', null, null, null,
+ ['Authorization: Token ' . $this->apiToken]);
$httpStatus = $response['status'];
$response = $response['data'];
diff --git a/lang/README.md b/lang/README.md
index de47630b84..fa213e881c 100644
--- a/lang/README.md
+++ b/lang/README.md
@@ -1,7 +1,7 @@
## Contribute
-If you want to improve an existing Matomo translation or contribute a new translation, please have a look at our [Transifex project](https://translations.piwik.org).
+If you want to improve an existing Matomo translation or contribute a new translation, please have a look at our [Weblate project](https://hosted.weblate.org/engage/matomo/).
-We cannot accept pull requests for translations on GitHub since we manage all translations in this separate system. Translations will automatically be transferred to GitHub from time to time!
+We likely won't accept pull requests for translations on GitHub since we manage all translations in this separate system. Translations will automatically be transferred to GitHub from time to time!
If you have any questions feel free to contact the team at translations@matomo.org.
diff --git a/plugins/Bandwidth b/plugins/Bandwidth
-Subproject 9f591fdb82980ddf3a4e36f1b1c71e135bd5992
+Subproject a04b8c3de354b8547e2d54ee3e748c1d102175b
diff --git a/plugins/CustomAlerts b/plugins/CustomAlerts
-Subproject 28c937b253b5b94c6e9d1d39451c6228bf69647
+Subproject 2af4a1d48dc6d67101c75f0bd7cccd8ba69c2b1
diff --git a/plugins/CustomVariables b/plugins/CustomVariables
-Subproject b84e62768e37a8cd4b93bffbd273336c8ddd315
+Subproject b998e663991bc3000cce0af5f918d2a53bcca5e
diff --git a/plugins/DeviceDetectorCache b/plugins/DeviceDetectorCache
-Subproject dd3f240bf8b850ab5d5ab0811f3b7e772eefbca
+Subproject ec65d1736713a8b984f3ad5ad48cac293d07561
diff --git a/plugins/Intl/Commands/GenerateIntl.php b/plugins/Intl/Commands/GenerateIntl.php
index 207029f9ca..af7ad7903d 100644
--- a/plugins/Intl/Commands/GenerateIntl.php
+++ b/plugins/Intl/Commands/GenerateIntl.php
@@ -314,6 +314,10 @@ class GenerateIntl extends ConsoleCommand
$territoryData = json_decode($territoryData, true);
$territoryData = $territoryData['main'][$requestLangCode]['localeDisplayNames']['territories'];
+ if (empty($territoryData)) {
+ throw new \Exception();
+ }
+
foreach ($countryCodes AS $code) {
if (!empty($territoryData[$code]) && $territoryData[$code] != $code) {
$translations['Intl']['Country_' . $code] = $this->transform($territoryData[$code]);
@@ -341,6 +345,10 @@ class GenerateIntl extends ConsoleCommand
$calendarData = json_decode($calendarData, true);
$calendarData = $calendarData['main'][$requestLangCode]['dates']['calendars']['gregorian'];
+ if (empty($calendarData)) {
+ throw new \Exception();
+ }
+
for ($i = 1; $i <= 12; $i++) {
$translations['Intl']['Month_Short_' . $i] = $calendarData['months']['format']['abbreviated'][$i];
$translations['Intl']['Month_Long_' . $i] = $calendarData['months']['format']['wide'][$i];
@@ -413,6 +421,10 @@ class GenerateIntl extends ConsoleCommand
$dateFieldData = json_decode($dateFieldData, true);
$dateFieldData = $dateFieldData['main'][$requestLangCode]['dates']['fields'];
+ if (empty($dateFieldData)) {
+ throw new \Exception();
+ }
+
$translations['Intl']['PeriodWeek'] = $dateFieldData['week']['displayName'];
$translations['Intl']['PeriodYear'] = $dateFieldData['year']['displayName'];
$translations['Intl']['PeriodDay'] = $dateFieldData['day']['displayName'];
@@ -436,6 +448,10 @@ class GenerateIntl extends ConsoleCommand
$timeZoneData = json_decode($timeZoneData, true);
$timeZoneData = $timeZoneData['main'][$requestLangCode]['dates']['timeZoneNames'];
+ if (empty($timeZoneData)) {
+ throw new \Exception();
+ }
+
$cities = array();
foreach ($timeZoneData['zone'] as $key1 => $level1) {
foreach ($level1 as $key2 => $level2) {
@@ -495,6 +511,10 @@ class GenerateIntl extends ConsoleCommand
$unitsData = json_decode($unitsData, true);
$unitsData = $unitsData['main'][$requestLangCode]['numbers'];
+ if (empty($unitsData)) {
+ throw new \Exception();
+ }
+
$numberingSystem = $unitsData['defaultNumberingSystem'];
$translations['Intl']['NumberSymbolDecimal'] = $unitsData['symbols-numberSystem-' . $numberingSystem]['decimal'];
@@ -521,6 +541,10 @@ class GenerateIntl extends ConsoleCommand
$unitsData = json_decode($unitsData, true);
$unitsData = $unitsData['main'][$requestLangCode]['units'];
+ if (empty($unitsData)) {
+ throw new \Exception();
+ }
+
$translations['Intl']['NSeconds'] = $this->replacePlaceHolder($unitsData['long']['duration-second']['unitPattern-count-other']);
$translations['Intl']['NSecondsShort'] = $this->replacePlaceHolder($unitsData['narrow']['duration-second']['unitPattern-count-other']);
$translations['Intl']['Seconds'] = $unitsData['long']['duration-second']['displayName'];
@@ -575,6 +599,10 @@ class GenerateIntl extends ConsoleCommand
$currencyData = json_decode($currencyData, true);
$currencyData = $currencyData['main'][$requestLangCode]['numbers']['currencies'];
+ if (empty($currencyData)) {
+ throw new \Exception();
+ }
+
$dataProvider = StaticContainer::get('Piwik\Intl\Data\Provider\CurrencyDataProvider');
foreach ($dataProvider->getCurrencyList() as $code => $currency) {
if (isset($currencyData[$code]['displayName'])) {
diff --git a/plugins/LanguagesManager/API.php b/plugins/LanguagesManager/API.php
index fa80210065..8b071ae5da 100644
--- a/plugins/LanguagesManager/API.php
+++ b/plugins/LanguagesManager/API.php
@@ -32,31 +32,33 @@ use Piwik\Translation\Loader\DevelopmentLoader;
*/
class API extends \Piwik\Plugin\API
{
- protected $availableLanguageNames = null;
- protected $languageNames = null;
+ protected $availableLanguageNames = [];
+ protected $languageNames = [];
/**
* Returns true if specified language is available
*
* @param string $languageCode
+ * @param bool $_ignoreConfig
* @return bool true if language available; false otherwise
*/
- public function isLanguageAvailable($languageCode)
+ public function isLanguageAvailable($languageCode, $_ignoreConfig = false)
{
return $languageCode !== false
&& Filesystem::isValidFilename($languageCode)
- && in_array($languageCode, $this->getAvailableLanguages());
+ && in_array($languageCode, $this->getAvailableLanguages($_ignoreConfig));
}
/**
* Return array of available languages
*
+ * @param bool $_ignoreConfig
* @return array Array of strings, each containing its ISO language code
*/
- public function getAvailableLanguages()
+ public function getAvailableLanguages($_ignoreConfig = false)
{
- if (!is_null($this->languageNames)) {
- return $this->languageNames;
+ if (!empty($this->languageNames[$_ignoreConfig])) {
+ return $this->languageNames[$_ignoreConfig];
}
$path = PIWIK_INCLUDE_PATH . "/lang/";
$languagesPath = _glob($path . "*.json");
@@ -71,7 +73,12 @@ class API extends \Piwik\Plugin\API
$configLanguages = Config::getInstance()->Languages["Languages"];
- $languages = array_intersect($filesystemLanguages, $configLanguages);
+ if ($_ignoreConfig) {
+ $languages = $filesystemLanguages;
+ } else {
+ $languages = array_intersect($filesystemLanguages, $configLanguages);
+ }
+
$this->enableDevelopmentLanguageInDevEnvironment($languages);
/**
@@ -83,18 +90,19 @@ class API extends \Piwik\Plugin\API
*/
Piwik::postEvent('LanguagesManager.getAvailableLanguages', array(&$languages));
- $this->languageNames = $languages;
+ $this->languageNames[$_ignoreConfig] = $languages;
return $languages;
}
/**
* Return information on translations (code, language, % translated, etc)
*
- * @param boolean $excludeNonCorePlugins excludes non core plugin from percentage calculation
+ * @param bool $excludeNonCorePlugins excludes non core plugin from percentage calculation
+ * @param bool $_ignoreConfig
*
* @return array Array of arrays
*/
- public function getAvailableLanguagesInfo($excludeNonCorePlugins=true)
+ public function getAvailableLanguagesInfo($excludeNonCorePlugins=true, $_ignoreConfig = false)
{
$data = file_get_contents(PIWIK_INCLUDE_PATH . '/lang/en.json');
$englishTranslation = json_decode($data, true);
@@ -120,7 +128,7 @@ class API extends \Piwik\Plugin\API
}
}
- $filenames = $this->getAvailableLanguages();
+ $filenames = $this->getAvailableLanguages($_ignoreConfig);
$languagesInfo = array();
foreach ($filenames as $filename) {
$data = file_get_contents(sprintf('%s/lang/%s.json', PIWIK_INCLUDE_PATH, $filename));
@@ -168,7 +176,7 @@ class API extends \Piwik\Plugin\API
$languageInfo = array('code' => $filename,
'name' => $translations['Intl']['OriginalLanguageName'],
'english_name' => $translations['Intl']['EnglishLanguageName'],
- 'translators' => $translations['General']['TranslatorName'],
+ 'translators' => $translations['General']['TranslatorName'] ?? '-',
'percentage_complete' => $percentageComplete . '%',
);
$languagesInfo[] = $languageInfo;
@@ -179,12 +187,13 @@ class API extends \Piwik\Plugin\API
/**
* Return array of available languages
*
+ * @param bool $_ignoreConfig
* @return array Array of array, each containing its ISO language code and name of the language
*/
- public function getAvailableLanguageNames()
+ public function getAvailableLanguageNames($_ignoreConfig = false)
{
- $this->loadAvailableLanguages();
- return $this->availableLanguageNames;
+ $this->loadAvailableLanguages($_ignoreConfig);
+ return $this->availableLanguageNames[$_ignoreConfig];
}
/**
@@ -342,19 +351,19 @@ class API extends \Piwik\Plugin\API
return $lang;
}
- private function loadAvailableLanguages()
+ private function loadAvailableLanguages($_ignoreConfig = false)
{
- if (!is_null($this->availableLanguageNames)) {
+ if (!empty($this->availableLanguageNames[$_ignoreConfig])) {
return;
}
- $cacheId = 'availableLanguages';
+ $cacheId = 'availableLanguages' . (int) $_ignoreConfig;
$cache = PiwikCache::getEagerCache();
if ($cache->contains($cacheId)) {
$languagesInfo = $cache->fetch($cacheId);
} else {
- $languages = $this->getAvailableLanguages();
+ $languages = $this->getAvailableLanguages($_ignoreConfig);
$languagesInfo = array();
foreach ($languages as $languageCode) {
$data = @file_get_contents(PIWIK_INCLUDE_PATH . "/plugins/Intl/lang/$languageCode.json");
@@ -375,7 +384,7 @@ class API extends \Piwik\Plugin\API
$cache->save($cacheId, $languagesInfo);
}
- $this->availableLanguageNames = $languagesInfo;
+ $this->availableLanguageNames[$_ignoreConfig] = $languagesInfo;
}
private function enableDevelopmentLanguageInDevEnvironment(&$languages)
diff --git a/plugins/LanguagesManager/Commands/CreatePull.php b/plugins/LanguagesManager/Commands/CreatePull.php
deleted file mode 100644
index 683f6e9c2b..0000000000
--- a/plugins/LanguagesManager/Commands/CreatePull.php
+++ /dev/null
@@ -1,233 +0,0 @@
-<?php
-/**
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-
-namespace Piwik\Plugins\LanguagesManager\Commands;
-
-use Piwik\Plugins\LanguagesManager\API;
-use Symfony\Component\Console\Input\ArrayInput;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Output\OutputInterface;
-
-/**
- */
-class CreatePull extends TranslationBase
-{
- const GIT_BASE_BRANCH = '4.x-dev';
-
- protected function configure()
- {
- $this->setName('translations:createpull')
- ->setDescription('Updates translation files')
- ->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'Transifex username')
- ->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Transifex password')
- ->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'Transifex project slug')
- ->addOption('plugin', 'P', InputOption::VALUE_OPTIONAL, 'optional name of plugin to update translations for');
- }
-
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $changes = shell_exec('git status --porcelain -uno');
-
- if (!empty($changes)) {
-
- $output->writeln("You have uncommitted changes. Creating pull request is only available with a clean working directory");
- return;
- }
-
- $unpushedCommits = shell_exec('git log origin/' . self::GIT_BASE_BRANCH . '..HEAD');
-
- if (!empty($unpushedCommits)) {
-
- $output->writeln("You have unpushed commits. Creating pull request is only available with a clean working directory");
- return;
- }
-
- chdir(PIWIK_DOCUMENT_ROOT);
-
- shell_exec('
- git checkout -f ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
- git pull > /dev/null 2>&1
- git submodule init > /dev/null 2>&1
- git submodule update > /dev/null 2>&1
- ');
-
- $plugin = $input->getOption('plugin');
- if (!empty($plugin)) {
-
- chdir(PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR.'plugins'.DIRECTORY_SEPARATOR.$plugin);
- shell_exec('
- git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
- git pull > /dev/null 2>&1
- ');
- }
-
- // check if branch exists localy and track it if not
- $branch = shell_exec('git branch | grep translationupdates');
-
- if (empty($branch)) {
-
- shell_exec('git checkout -b translationupdates origin/translationupdates');
- }
-
- // switch to branch and update it to latest $GIT_BASE_BRANCH
- shell_exec('
- git checkout -f translationupdates > /dev/null 2>&1
- git reset --hard origin/' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
- git push origin translationupdates > /dev/null 2>&1
- ');
-
- // update translation files
- $command = $this->getApplication()->find('translations:update');
- $arguments = array(
- 'command' => 'translations:update',
- '--username' => $input->getOption('username'),
- '--password' => $input->getOption('password'),
- '--slug' => $input->getOption('slug'),
- '--plugin' => $plugin
- );
- $inputObject = new ArrayInput($arguments);
- $inputObject->setInteractive($input->isInteractive());
- $command->run($inputObject, $output);
-
- shell_exec('git add lang/. > /dev/null 2>&1');
-
- if (empty($plugin)) {
- foreach (Update::getPluginsInCore() as $pluginName) {
- shell_exec(sprintf('git add plugins/%s/lang/. > /dev/null 2>&1', $pluginName));
- }
- }
-
- $changes = shell_exec('git status --porcelain -uno');
-
- if (empty($changes)) {
-
- $output->writeln("Nothing changed. Everything is already up to date.");
- shell_exec('git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1');
- return;
- }
-
- API::unsetInstance(); // reset languagemanager api (to force refresh of data)
-
- $stats = shell_exec('git diff --numstat HEAD');
-
- preg_match_all('/([0-9]+)\t([0-9]+)\t[a-zA-Z\/]*lang\/([a-z]{2,3}(?:-[a-z]{2,3})?)\.json/', $stats, $lineChanges);
-
- $addedLinesSum = 0;
- if (!empty($lineChanges[1])) {
- $addedLinesSum = array_sum($lineChanges[1]);
- }
-
- $linesSumByLang = array();
- $lineChangesCount = count($lineChanges[0]);
- for ($i = 0; $i < $lineChangesCount; $i++) {
- @$linesSumByLang[$lineChanges[3][$i]] += $lineChanges[1][$i];
- }
-
- preg_match_all('/M [a-zA-Z\/]*lang\/([a-z]{2,3}(?:-[a-z]{2,3})?)\.json/', $changes, $modifiedFiles);
- preg_match_all('/A [a-zA-Z\/]*lang\/([a-z]{2,3}(?:-[a-z]{2,3})?)\.json/', $changes, $addedFiles);
-
- $messages = array();
-
- $languageCodesTouched = array();
- if (!empty($addedFiles[1])) {
- foreach ($addedFiles[1] as $addedFile) {
- $languageInfo = $this->getLanguageInfoByIsoCode($addedFile);
- $messages[$addedFile] = sprintf('- Added %s (%s changes / %s translated)\n', $languageInfo['english_name'], $linesSumByLang[$addedFile], $languageInfo['percentage_complete']);
- }
- $languageCodesTouched = array_merge($languageCodesTouched, $addedFiles[1]);
- }
-
- if (!empty($modifiedFiles[1])) {
- foreach ($modifiedFiles[1] as $modifiedFile) {
- if ($linesSumByLang[$modifiedFile]) {
- $languageInfo = $this->getLanguageInfoByIsoCode($modifiedFile);
- $messages[$modifiedFile] = sprintf(
- '- Updated %s (%s changes / %s translated)\n',
- $languageInfo['english_name'],
- $linesSumByLang[$modifiedFile],
- $languageInfo['percentage_complete']
- );
- $languageCodesTouched[] = $modifiedFile;
- }
- }
- $languageCodesTouched = array_unique($languageCodesTouched);
- }
-
- $message = implode('', $messages);
-
- $message .= '\n\nHelp us translate Matomo in your language!\nSignup at https://www.transifex.com/matomo/matomo/\nIf you have any questions, get in touch with us at translations@matomo.org';
-
- $languageCodesTouched = array_unique($languageCodesTouched, SORT_REGULAR);
-
- $title = sprintf(
- 'Updated %s strings in %u languages (%s)',
- $addedLinesSum,
- count($languageCodesTouched),
- implode(', ', $languageCodesTouched)
- );
-
- shell_exec('git commit -m "language update ${pluginName}"');
- shell_exec('git push');
- shell_exec('git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1');
-
- $this->createPullRequest($output, $title, $message);
- }
-
- private function getLanguageInfoByIsoCode($isoCode)
- {
- $languages = API::getInstance()->getAvailableLanguagesInfo();
- foreach ($languages as $languageInfo) {
- if ($languageInfo['code'] == $isoCode) {
- return $languageInfo;
- }
- }
- return array();
- }
-
- private function createPullRequest(OutputInterface $output, $title, $message)
- {
- $dialog = $this->getHelperSet()->get('dialog');
-
- while (true) {
-
- $username = $dialog->ask($output, 'Please provide your GitHub username (to create a pull request using GitHub API): ');
-
- $returnCode = shell_exec('curl \
- -X POST \
- -k \
- --silent \
- --write-out %{http_code} \
- --stderr /dev/null \
- -o /dev/null \
- -u '.$username.' \
- --data "{\"title\":\"[automatic translation update] '.$title.'\",\"body\":\"'.$message.'\",\"head\":\"translationupdates\",\"base\":\"' . self::GIT_BASE_BRANCH . '\"}" \
- -H "Accept: application/json" \
- https://api.github.com/repos/matomo-org/matomo/pulls');
-
- switch ($returnCode) {
- case 401:
- $output->writeln("Pull request failed. Bad credentials... Please try again");
- continue 2;
-
- case 422:
- $output->writeln("Pull request failed. Unprocessable Entity. Maybe a pull request was already created before.");
- return;
-
- case 201:
- case 200:
- $output->writeln("Pull request successfully created.");
- return;
-
- default:
- $output->writeln("Pull request failed... Please try again");
- }
- }
- }
-}
diff --git a/plugins/LanguagesManager/Commands/FetchTranslations.php b/plugins/LanguagesManager/Commands/FetchTranslations.php
index e69fd49761..87dd5076f8 100644
--- a/plugins/LanguagesManager/Commands/FetchTranslations.php
+++ b/plugins/LanguagesManager/Commands/FetchTranslations.php
@@ -12,7 +12,7 @@ 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 Piwik\Translation\Weblate\API;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -22,18 +22,16 @@ use Symfony\Component\Console\Output\OutputInterface;
*/
class FetchTranslations extends TranslationBase
{
- const DOWNLOAD_PATH = '/transifex';
+ const DOWNLOAD_PATH = '/weblate';
protected function configure()
{
$path = StaticContainer::get('path.tmp') . self::DOWNLOAD_PATH;
$this->setName('translations:fetch')
- ->setDescription('Fetches translations files from Transifex to ' . $path)
- ->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'Transifex username')
- ->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Transifex password')
- ->addOption('lastupdate', 'l', InputOption::VALUE_OPTIONAL, 'Last time update ran', time()-30*24*3600)
- ->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'project slug on transifex', 'matomo')
+ ->setDescription('Fetches translations files from Weblate to ' . $path)
+ ->addOption('token', 't', InputOption::VALUE_OPTIONAL, 'Weblate API token')
+ ->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'project slug on weblate', 'matomo')
->addOption('plugin', 'r', InputOption::VALUE_OPTIONAL, 'Plugin to update');
}
@@ -41,37 +39,35 @@ class FetchTranslations extends TranslationBase
{
$output->setDecorated(true);
- $username = $input->getOption('username');
- $password = $input->getOption('password');
+ $apiToken = $input->getOption('token');
$plugin = $input->getOption('plugin');
- $lastUpdate = $input->getOption('lastupdate');
$slug = $input->getOption('slug');
- $resource = 'matomo-'. ($plugin ? 'plugin-'.strtolower($plugin) : 'base');
+ $resource = $plugin ? 'plugin-'.strtolower($plugin) : 'matomo-base';
- $transifexApi = new API($username, $password, $slug);
+ $weblateApi = new API($apiToken, $slug);
// remove all existing translation files in download path
$files = glob($this->getDownloadPath() . DIRECTORY_SEPARATOR . '*.json');
array_map('unlink', $files);
- if (!$transifexApi->resourceExists($resource)) {
- $output->writeln("Skipping resource $resource as it doesn't exist on Transifex");
+ if (!$weblateApi->resourceExists($resource)) {
+ $output->writeln("Skipping resource $resource as it doesn't exist on Weblate");
return;
}
- $output->writeln("Fetching translations from Transifex for resource $resource");
+ $output->writeln("Fetching translations from Weblate for resource $resource");
try {
- $languages = $transifexApi->getAvailableLanguageCodes();
+ $languages = $weblateApi->getAvailableLanguageCodes();
if (!empty($plugin)) {
$languages = array_filter($languages, function ($language) {
- return LanguagesManagerApi::getInstance()->isLanguageAvailable(str_replace('_', '-', strtolower($language)));
+ return LanguagesManagerApi::getInstance()->isLanguageAvailable(str_replace('_', '-', strtolower($language)), true);
});
}
} catch (AuthenticationFailedException $e) {
- $availableLanguages = LanguagesManagerApi::getInstance()->getAvailableLanguageNames();
+ $availableLanguages = LanguagesManagerApi::getInstance()->getAvailableLanguageNames(true);
$languageCodes = array();
foreach ($availableLanguages as $languageInfo) {
@@ -96,20 +92,9 @@ class FetchTranslations extends TranslationBase
$progress->start();
- $statistics = $transifexApi->getStatistics($resource);
-
foreach ($languages as $language) {
try {
- // if we have modification date given from statistics api compare it with given last update time to ignore not update resources
- if (LanguagesManagerApi::getInstance()->isLanguageAvailable(str_replace('_', '-', strtolower($language))) && isset($statistics->$language)) {
- $lastupdated = strtotime($statistics->$language->last_update);
- if ($lastUpdate > $lastupdated) {
- $progress->advance();
- continue;
- }
- }
-
- $translations = $transifexApi->getTranslations($resource, $language, true);
+ $translations = $weblateApi->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());
diff --git a/plugins/LanguagesManager/Commands/LanguageCodes.php b/plugins/LanguagesManager/Commands/LanguageCodes.php
index 79129107a9..323aa0febb 100644
--- a/plugins/LanguagesManager/Commands/LanguageCodes.php
+++ b/plugins/LanguagesManager/Commands/LanguageCodes.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\LanguagesManager\Commands;
use Piwik\Plugins\LanguagesManager\API;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
@@ -20,12 +21,13 @@ class LanguageCodes extends TranslationBase
protected function configure()
{
$this->setName('translations:languagecodes')
+ ->addOption('all', 'a', InputOption::VALUE_NONE, 'Displays all languages (ignores language configuration)')
->setDescription('Shows available language codes');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
- $languages = API::getInstance()->getAvailableLanguageNames();
+ $languages = API::getInstance()->getAvailableLanguageNames($input->getOption('all'));
$languageCodes = array();
foreach ($languages as $languageInfo) {
diff --git a/plugins/LanguagesManager/Commands/LanguageInfo.php b/plugins/LanguagesManager/Commands/LanguageInfo.php
index 5571db8cc3..ef38f3c2a8 100644
--- a/plugins/LanguagesManager/Commands/LanguageInfo.php
+++ b/plugins/LanguagesManager/Commands/LanguageInfo.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\LanguagesManager\Commands;
use Piwik\Plugins\LanguagesManager\API;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
@@ -20,12 +21,13 @@ class LanguageInfo extends TranslationBase
protected function configure()
{
$this->setName('translations:languageinfo')
+ ->addOption('all', 'a', InputOption::VALUE_NONE, 'Displays all languages (ignores language configuration)')
->setDescription('Shows available languages info');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
- $languages = API::getInstance()->getAvailableLanguagesInfo();
+ $languages = API::getInstance()->getAvailableLanguagesInfo(true, $input->getOption('all'));
foreach ($languages as $languageInfo) {
$output->writeln($languageInfo['code'].'|' . $languageInfo['english_name'] . '|' . $languageInfo['percentage_complete']);
diff --git a/plugins/LanguagesManager/Commands/LanguageNames.php b/plugins/LanguagesManager/Commands/LanguageNames.php
index 7e41d5057a..d30c81141e 100644
--- a/plugins/LanguagesManager/Commands/LanguageNames.php
+++ b/plugins/LanguagesManager/Commands/LanguageNames.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\LanguagesManager\Commands;
use Piwik\Plugins\LanguagesManager\API;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
@@ -20,12 +21,13 @@ class LanguageNames extends TranslationBase
protected function configure()
{
$this->setName('translations:languagenames')
+ ->addOption('all', 'a', InputOption::VALUE_NONE, 'Displays all languages (ignores language configuration)')
->setDescription('Shows available language names');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
- $languages = API::getInstance()->getAvailableLanguageNames();
+ $languages = API::getInstance()->getAvailableLanguageNames($input->getOption('all'));
$languageNames = array();
foreach ($languages as $languageInfo) {
diff --git a/plugins/LanguagesManager/Commands/SetTranslations.php b/plugins/LanguagesManager/Commands/SetTranslations.php
index 6790d40158..4952e62962 100644
--- a/plugins/LanguagesManager/Commands/SetTranslations.php
+++ b/plugins/LanguagesManager/Commands/SetTranslations.php
@@ -43,7 +43,7 @@ class SetTranslations extends TranslationBase
$languageCode = $input->getOption('code');
$filename = $input->getOption('file');
- $languageCodes = (new API())->getAvailableLanguages();
+ $languageCodes = (new API())->getAvailableLanguages(true);
if (empty($languageCode) || !in_array($languageCode, $languageCodes)) {
$languageCode = $dialog->askAndValidate($output, 'Please provide a valid language code: ', function ($code) use ($languageCodes) {
diff --git a/plugins/LanguagesManager/Commands/Update.php b/plugins/LanguagesManager/Commands/Update.php
index 7fe598985d..4103b27f2b 100644
--- a/plugins/LanguagesManager/Commands/Update.php
+++ b/plugins/LanguagesManager/Commands/Update.php
@@ -28,10 +28,8 @@ class Update extends TranslationBase
{
$this->setName('translations:update')
->setDescription('Updates translation files')
- ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force update of all language files')
- ->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'Transifex username')
- ->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Transifex password')
- ->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'Transifex project slug')
+ ->addOption('token', 't', InputOption::VALUE_OPTIONAL, 'Weblate API token')
+ ->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'Weblate project slug')
->addOption('all', 'a', InputOption::VALUE_NONE, 'Force to update all plugins (even non core). Can not be used with plugin option')
->addOption('plugin', 'P', InputOption::VALUE_OPTIONAL, 'optional name of plugin to update translations for');
}
@@ -45,7 +43,7 @@ class Update extends TranslationBase
/** @var DialogHelper $dialog */
$dialog = $this->getHelperSet()->get('dialog');
- $languages = API::getInstance()->getAvailableLanguageNames();
+ $languages = API::getInstance()->getAvailableLanguageNames(true);
$languageCodes = array();
foreach ($languages as $languageInfo) {
@@ -63,8 +61,6 @@ class Update extends TranslationBase
if (empty($plugin)) {
$pluginList = $forceAllPlugins ? self::getAllPlugins() : self::getPluginsInCore();
array_unshift($pluginList, '');
- } else {
- $input->setOption('force', true); // force plugin only updates
}
foreach ($pluginList as $plugin) {
@@ -220,34 +216,11 @@ class Update extends TranslationBase
$command = $this->getApplication()->find('translations:fetch');
$arguments = array(
'command' => 'translations:fetch',
- '--username' => $input->getOption('username'),
- '--password' => $input->getOption('password'),
+ '--token' => $input->getOption('token'),
'--slug' => $input->getOption('slug'),
'--plugin' => $plugin
);
- if ($input->getOption('force')) {
- $arguments['--lastupdate'] = 1;
- } else {
- $lastModDate = strtotime('2015-01-04 00:00:00'); // date of initial transifex setup
- try {
- // try to find the language file (of given plugin) with the newest modification date in git log
- $path = ($plugin ? 'plugins/' . $plugin . '/' : '') . 'lang';
- $files = explode("\n", trim(shell_exec('git ls-tree -r --name-only HEAD ' . $path)));
-
- foreach ($files as $file) {
- $fileModDate = shell_exec('git log -1 --format="%at" -- ' . $file);
- if (basename($file) != 'en.json' && $fileModDate > $lastModDate) {
- $lastModDate = $fileModDate;
- }
- }
- } catch (\Exception $e) {
- }
-
- if ($lastModDate != 0) {
- $arguments['--lastupdate'] = $lastModDate;
- }
- }
$inputObject = new ArrayInput($arguments);
$inputObject->setInteractive($input->isInteractive());
$command->run($inputObject, $output);
diff --git a/plugins/LanguagesManager/Commands/Validate.php b/plugins/LanguagesManager/Commands/Validate.php
index 07082ba730..c14273c0c2 100644
--- a/plugins/LanguagesManager/Commands/Validate.php
+++ b/plugins/LanguagesManager/Commands/Validate.php
@@ -24,9 +24,8 @@ class Validate extends TranslationBase
{
$this->setName('translations:validate')
->setDescription('Validates translation files')
- ->addOption('username', 'u', InputOption::VALUE_OPTIONAL, 'Transifex username')
- ->addOption('password', 'p', InputOption::VALUE_OPTIONAL, 'Transifex password')
- ->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'Transifex project slug')
+ ->addOption('token', 't', InputOption::VALUE_OPTIONAL, 'Weblate API token')
+ ->addOption('slug', 's', InputOption::VALUE_OPTIONAL, 'Weblate project slug')
->addOption('all', 'a', InputOption::VALUE_NONE, 'Force to update all plugins (even non core). Can not be used with plugin option')
->addOption('plugin', 'P', InputOption::VALUE_OPTIONAL, 'optional name of plugin to update translations for');
}
@@ -37,7 +36,7 @@ class Validate extends TranslationBase
$start = microtime(true);
- $languages = API::getInstance()->getAvailableLanguageNames();
+ $languages = API::getInstance()->getAvailableLanguageNames(true);
$languageCodes = array();
foreach ($languages as $languageInfo) {
@@ -127,12 +126,10 @@ class Validate extends TranslationBase
$command = $this->getApplication()->find('translations:fetch');
$arguments = array(
- 'command' => 'translations:fetch',
- '--username' => $input->getOption('username'),
- '--password' => $input->getOption('password'),
- '--slug' => $input->getOption('slug'),
- '--plugin' => $plugin,
- '--lastupdate' => 1
+ 'command' => 'translations:fetch',
+ '--token' => $input->getOption('token'),
+ '--slug' => $input->getOption('slug'),
+ '--plugin' => $plugin
);
$inputObject = new ArrayInput($arguments);
diff --git a/plugins/LanguagesManager/tests/Integration/LanguagesManagerTest.php b/plugins/LanguagesManager/tests/Integration/LanguagesManagerTest.php
index 5b776c7d24..48456239dc 100644
--- a/plugins/LanguagesManager/tests/Integration/LanguagesManagerTest.php
+++ b/plugins/LanguagesManager/tests/Integration/LanguagesManagerTest.php
@@ -107,7 +107,7 @@ class LanguagesManagerTest extends \PHPUnit\Framework\TestCase
$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"
+ . "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 Weblate: \n"
. "$ ./console translations:update [--plugin=XYZ] \n"
);
}
diff --git a/plugins/LogViewer b/plugins/LogViewer
-Subproject 9c893d29c64f5ca60ed093cf553b897c83a755c
+Subproject 3204e829f960ccfc0a9ddb4b509dea5a4f6529e
diff --git a/plugins/LoginLdap b/plugins/LoginLdap
-Subproject 3fe227f67469ab4e45b61c656db85cd56458d81
+Subproject ca493a3b1147db7626adac4f1baec0e2b0315d8
diff --git a/plugins/MarketingCampaignsReporting b/plugins/MarketingCampaignsReporting
-Subproject c1bfe8f24c30283c2a8e88dcac15ea68fb91d23
+Subproject 67ce24997dad02146dd3333d609eddb3bee314c
diff --git a/plugins/Provider b/plugins/Provider
-Subproject f46d3a6cc4a4715e962f3f893a822d7125d9bd8
+Subproject b04a23f50c6e050904ad83e927a49dfe10b8134
diff --git a/plugins/QueuedTracking b/plugins/QueuedTracking
-Subproject d91ac1a0855ea0ad7c113111364e4f3b4076c47
+Subproject 277f5d0419cff1d560d0274f8545b1088e61f52
diff --git a/plugins/SecurityInfo b/plugins/SecurityInfo
-Subproject aecd4763c9065cde6aafd4f972701831a6f4fde
+Subproject 9164ac73a2cb9c7ef03dc71eb064c455044c462
diff --git a/plugins/TagManager b/plugins/TagManager
-Subproject 629a4132a3324fc1d6ecfa67b1790fef6b01dfc
+Subproject 08b3f02cae322525c001b5dac17b898581a9739
diff --git a/plugins/TasksTimetable b/plugins/TasksTimetable
-Subproject 55914c9a44a1cf35278ad94fb8eadb128fa242d
+Subproject 7287cd7ea0c7320a1f2345923d8794d8f5f2999
diff --git a/plugins/TrackingSpamPrevention b/plugins/TrackingSpamPrevention
-Subproject 86dc97a5b1ba2ff3eacda3cd08ff96ff2820c54
+Subproject 3051e8eb481cf89ce6a1811f805247a6c596f4a
diff --git a/plugins/VisitorGenerator b/plugins/VisitorGenerator
-Subproject 3bb5dcf98aa68de38a9fb1450977aa58fef057d
+Subproject 8cc8882aeee4ea345069d7274ac2e3e913ea958
diff --git a/tests/PHPUnit/System/expected/test_apiGetReportMetadata_year__LanguagesManager.getAvailableLanguageNames.xml b/tests/PHPUnit/System/expected/test_apiGetReportMetadata_year__LanguagesManager.getAvailableLanguageNames.xml
index 0186ba6d3f..f27a6388f6 100644
--- a/tests/PHPUnit/System/expected/test_apiGetReportMetadata_year__LanguagesManager.getAvailableLanguageNames.xml
+++ b/tests/PHPUnit/System/expected/test_apiGetReportMetadata_year__LanguagesManager.getAvailableLanguageNames.xml
@@ -280,5 +280,4 @@
<name>繁體中文</name>
<english_name>Traditional Chinese</english_name>
</row>
-</result>
-
+</result> \ No newline at end of file
diff --git a/tests/PHPUnit/System/expected/test_reportLimitingdimension_2_rankingQuery__CustomDimensions.getCustomDimension_day.xml b/tests/PHPUnit/System/expected/test_reportLimitingdimension_2_rankingQuery__CustomDimensions.getCustomDimension_day.xml
index eccf657358..ecd14db85a 100644
--- a/tests/PHPUnit/System/expected/test_reportLimitingdimension_2_rankingQuery__CustomDimensions.getCustomDimension_day.xml
+++ b/tests/PHPUnit/System/expected/test_reportLimitingdimension_2_rankingQuery__CustomDimensions.getCustomDimension_day.xml
@@ -81,8 +81,6 @@
<avg_time_on_dimension>0</avg_time_on_dimension>
-
-
</row>
<row>
@@ -123,8 +121,6 @@
<avg_time_on_dimension>0</avg_time_on_dimension>
-
-
</row>
</subtable>
</row>
diff --git a/tests/PHPUnit/Unit/Translation/FilesTest.php b/tests/PHPUnit/Unit/Translation/FilesTest.php
index 9a7f162138..ad41a3fba4 100644
--- a/tests/PHPUnit/Unit/Translation/FilesTest.php
+++ b/tests/PHPUnit/Unit/Translation/FilesTest.php
@@ -24,7 +24,7 @@ class FilesTest extends \PHPUnit\Framework\TestCase
{
$json = json_decode(file_get_contents($file), true);
- $this->assertNotEmpty($json, "translation file $file seems to be corrupted or empty");
+ $this->assertIsArray($json, "translation file $file seems to be corrupted or empty");
}
public function getTranslationFiles()
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_admin_diagnostics_configfile.png b/tests/UI/expected-screenshots/UIIntegrationTest_admin_diagnostics_configfile.png
index 7765aba1c6..412f49b00c 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_admin_diagnostics_configfile.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_admin_diagnostics_configfile.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1fe0595c6839632c82a240f8afffd6edd62fde19095d5f17db27ee1b0517cd52
-size 5136262
+oid sha256:0b0a79eab39fdae3db8868a0bfa8bb9ddb6e24109d67a9770750879905ea3b5b
+size 5187957
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png
index e3243baf71..5c6e98ae95 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f72555e443655cbd8a8cb5a748693a79e1ea58d64a63d9e00dfee99d23052e11
-size 1084898
+oid sha256:adea21d64c4043f6c74d766fae109c778ccf5925d4821cb06d02572ec15f416c
+size 1084865
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png
index b03ea8a5cb..a3a9307440 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:eae87c89382a0090f86042e3136f9bbf24772154292b4e6909472d30282f751d
-size 1086330
+oid sha256:22f5133b2fc7be7178753cf6e620131e07dd9e8c40ec2a0dcda2b1b010245d01
+size 1086277