new command to delete empty translations (#3392)
* composer update and phpstan issues * bump version
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": "7.3.*||7.4.*||8.0.*",
|
"php": "7.3.*||7.4.*||8.0.*||8.1.*",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
"ext-intl": "*",
|
"ext-intl": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
@@ -77,6 +77,7 @@
|
|||||||
"twig/string-extra": "^3.0"
|
"twig/string-extra": "^3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"ext-simplexml": "*",
|
||||||
"dama/doctrine-test-bundle": "^6.0",
|
"dama/doctrine-test-bundle": "^6.0",
|
||||||
"doctrine/doctrine-fixtures-bundle": "^3.2",
|
"doctrine/doctrine-fixtures-bundle": "^3.2",
|
||||||
"fakerphp/faker": "^1.15",
|
"fakerphp/faker": "^1.15",
|
||||||
|
|||||||
387
composer.lock
generated
387
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,8 @@ parameters:
|
|||||||
tmpDir: %rootDir%/../../../var/cache/phpstan
|
tmpDir: %rootDir%/../../../var/cache/phpstan
|
||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
- '#Method Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface::dispatch\(\) invoked with 2 parameters, 1 required.#'
|
- '#Method Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface::dispatch\(\) invoked with 2 parameters, 1 required.#'
|
||||||
|
- '#Trait App\\Export\\Renderer\\RendererTrait is used zero times and is not analysed.#'
|
||||||
|
- '#Trait App\\Invoice\\Renderer\\RendererTrait is used zero times and is not analysed.#'
|
||||||
excludePaths:
|
excludePaths:
|
||||||
- %rootDir%/../../../src/Ldap/LdapDriver.php
|
- %rootDir%/../../../src/Ldap/LdapDriver.php
|
||||||
treatPhpDocTypesAsCertain: false
|
treatPhpDocTypesAsCertain: false
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ class TranslationCommand extends Command
|
|||||||
->addOption('delete-resname', null, InputOption::VALUE_REQUIRED, 'Deletes the translation by resname')
|
->addOption('delete-resname', null, InputOption::VALUE_REQUIRED, 'Deletes the translation by resname')
|
||||||
->addOption('extension', null, InputOption::VALUE_NONE, 'Find translation files with wrong extensions')
|
->addOption('extension', null, InputOption::VALUE_NONE, 'Find translation files with wrong extensions')
|
||||||
->addOption('fill-empty', null, InputOption::VALUE_NONE, 'Pre-fills empty translations with the english version')
|
->addOption('fill-empty', null, InputOption::VALUE_NONE, 'Pre-fills empty translations with the english version')
|
||||||
|
->addOption('delete-empty', null, InputOption::VALUE_NONE, 'Delete all empty kyes and files which have no translated key at all')
|
||||||
// DEEPL TRANSLATION FEATURE - UNTESTED
|
// DEEPL TRANSLATION FEATURE - UNTESTED
|
||||||
->addOption('translate-locale', null, InputOption::VALUE_REQUIRED, 'Translate into the given locale with Deepl')
|
->addOption('translate-locale', null, InputOption::VALUE_REQUIRED, 'Translate into the given locale with Deepl')
|
||||||
// @see https://www.deepl.com/de/pro#developer
|
// @see https://www.deepl.com/de/pro#developer
|
||||||
@@ -131,7 +132,7 @@ class TranslationCommand extends Command
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->fixEmptyTranslations($file, $translations[$fromLocale][$name]);
|
$this->fillEmptyTranslations($file, $translations[$fromLocale][$name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,6 +180,17 @@ class TranslationCommand extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Delete empty translation keys and files without any translation
|
||||||
|
// ==========================================================================
|
||||||
|
if ($input->getOption('delete-empty')) {
|
||||||
|
foreach ($bases as $directory) {
|
||||||
|
foreach (glob($directory) as $file) {
|
||||||
|
$this->removeEmptyTranslations($io, $file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// DEEPL
|
// DEEPL
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@@ -399,7 +411,7 @@ class TranslationCommand extends Command
|
|||||||
file_put_contents($file, $xmlDocument->saveXML());
|
file_put_contents($file, $xmlDocument->saveXML());
|
||||||
}
|
}
|
||||||
|
|
||||||
private function fixEmptyTranslations(string $file, array $translations): void
|
private function fillEmptyTranslations(string $file, array $translations): void
|
||||||
{
|
{
|
||||||
$xml = simplexml_load_file($file);
|
$xml = simplexml_load_file($file);
|
||||||
$foundEmpty = false;
|
$foundEmpty = false;
|
||||||
@@ -463,6 +475,51 @@ class TranslationCommand extends Command
|
|||||||
file_put_contents($file, $xmlDocument->saveXML());
|
file_put_contents($file, $xmlDocument->saveXML());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function removeEmptyTranslations(SymfonyStyle $io, string $file): void
|
||||||
|
{
|
||||||
|
$xml = simplexml_load_file($file);
|
||||||
|
$hasTranslation = false;
|
||||||
|
|
||||||
|
/** @var \SimpleXMLElement $unit */
|
||||||
|
foreach ($xml->file->body->{'trans-unit'} as $unit) {
|
||||||
|
$translation = (string) $unit->target;
|
||||||
|
if (\strlen($translation) > 0) {
|
||||||
|
$hasTranslation = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$hasTranslation) {
|
||||||
|
unlink($file);
|
||||||
|
$io->warning('Removed empty translation file: ' . basename($file));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$xmlDocument = new \DOMDocument('1.0');
|
||||||
|
$xmlDocument->preserveWhiteSpace = false;
|
||||||
|
$xmlDocument->loadXML($xml->asXML());
|
||||||
|
|
||||||
|
$removedTranslation = false;
|
||||||
|
$elements = $xmlDocument->getElementsByTagName('target');
|
||||||
|
foreach ($elements as $element) {
|
||||||
|
if ($element->nodeValue === '' || $element->nodeValue === null) {
|
||||||
|
/** @var \DOMElement $parent */
|
||||||
|
$parent = $element->parentNode;
|
||||||
|
$io->text('Remove empty translation: ' . $parent->getAttribute('resname'));
|
||||||
|
$parent->parentNode->removeChild($parent);
|
||||||
|
$removedTranslation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($removedTranslation) {
|
||||||
|
$xmlDocument->formatOutput = true;
|
||||||
|
|
||||||
|
file_put_contents($file, $xmlDocument->saveXML());
|
||||||
|
$io->warning('Removed empty translations from file: ' . basename($file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function generateId(string $source): string
|
private function generateId(string $source): string
|
||||||
{
|
{
|
||||||
return strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._');
|
return strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._');
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ class Constants
|
|||||||
/**
|
/**
|
||||||
* The current release version
|
* The current release version
|
||||||
*/
|
*/
|
||||||
public const VERSION = '1.20.5';
|
public const VERSION = '1.21';
|
||||||
/**
|
/**
|
||||||
* The current release: major * 10000 + minor * 100 + patch
|
* The current release: major * 10000 + minor * 100 + patch
|
||||||
*/
|
*/
|
||||||
public const VERSION_ID = 12005;
|
public const VERSION_ID = 12100;
|
||||||
/**
|
/**
|
||||||
* The current release status, either "stable" or "dev"
|
* The current release status, either "stable" or "dev"
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use App\Export\Base\RendererTrait as BaseRendererTrait;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated since 1.6, will be removed with 2.0
|
* @deprecated since 1.6, will be removed with 2.0
|
||||||
|
* @phpstan-ignore-next-line
|
||||||
*/
|
*/
|
||||||
trait RendererTrait
|
trait RendererTrait
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -328,9 +328,11 @@ class TimesheetRepository extends EntityRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (\is_array($select)) {
|
if (\is_array($select)) {
|
||||||
|
/* @phpstan-ignore-next-line */
|
||||||
return $qb->getQuery()->getOneOrNullResult();
|
return $qb->getQuery()->getOneOrNullResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$result = $qb->getQuery()->getSingleScalarResult();
|
$result = $qb->getQuery()->getSingleScalarResult();
|
||||||
|
|
||||||
return empty($result) ? 0 : $result;
|
return empty($result) ? 0 : $result;
|
||||||
|
|||||||
Reference in New Issue
Block a user