diff --git a/src/Command/TranslationCommand.php b/src/Command/TranslationCommand.php new file mode 100644 index 00000000..e70ea7a1 --- /dev/null +++ b/src/Command/TranslationCommand.php @@ -0,0 +1,135 @@ +projectDirectory = $projectDirectory; + $this->environment = $kernelEnvironment; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('kimai:translations') + ->setDescription('Translation adjustments') + ->addOption('resname', null, InputOption::VALUE_NONE, 'Fix the resname vs. id attribute') + ->addOption('duplicates', null, InputOption::VALUE_NONE, 'Find duplicate translation keys') + ->addOption('extension', null, InputOption::VALUE_NONE, 'Find translation files with wrong extensions') + ; + } + + public function isEnabled(): bool + { + return $this->environment !== 'prod'; + } + + protected function execute(InputInterface $input, OutputInterface $output): ?int + { + $io = new SymfonyStyle($input, $output); + + $bases = [ + 'core' => $this->projectDirectory . '/translations', + 'plugins' => $this->projectDirectory . Kernel::PLUGIN_DIRECTORY . '/*/Resources/translations', + ]; + + if ($input->getOption('resname')) { + foreach ($bases as $id => $directory) { + $files = glob($directory . '/*.xlf'); + + foreach ($files as $file) { + $this->fixXlfFile($file); + } + } + } + + if ($input->getOption('extension')) { + foreach ($bases as $id => $directory) { + $files = glob($directory . '/*.xliff'); + + foreach ($files as $file) { + $file = str_replace($this->projectDirectory, '', $file); + $io->warning($file); + } + } + } + + if ($input->getOption('duplicates')) { + $duplicates = []; + + $files = glob($bases['core'] . '/*.xlf'); + foreach ($files as $file) { + $xml = simplexml_load_file($file); + foreach ($xml->file->body->{'trans-unit'} as $unit) { + $n = (string) $unit['resname']; + if (!\array_key_exists($n, $duplicates)) { + $duplicates[$n] = []; + } + $b = explode('.', basename($file))[0]; + if (!\in_array($b, $duplicates[$n])) { + $duplicates[$n][] = $b; + } + } + } + + foreach ($duplicates as $id => $files) { + if (\count($files) > 1) { + $io->text($id . ' => ' . implode(', ', $files)); + } + } + } + + return 0; + } + + private function fixXlfFile(string $file): void + { + $xml = simplexml_load_file($file); + if (isset($xml->file->header)) { + unset($xml->file->header); + } + + foreach ($xml->file->body->{'trans-unit'} as $unit) { + $source = $unit->source; + if (!isset($unit['resname'])) { + $unit['resname'] = $source; + } + $unit['id'] = strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._'); + } + + $xmlDocument = new \DOMDocument('1.0'); + $xmlDocument->preserveWhiteSpace = false; + $xmlDocument->formatOutput = true; + $xmlDocument->loadXML($xml->asXML()); + + file_put_contents($file, $xmlDocument->saveXML()); + } +} diff --git a/src/Kernel.php b/src/Kernel.php index 6e5988ab..7c779484 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -45,6 +45,7 @@ class Kernel extends BaseKernel { use MicroKernelTrait; + public const PLUGIN_DIRECTORY = '/var/plugins'; public const CONFIG_EXTS = '.{php,xml,yaml,yml}'; public const TAG_PLUGIN = 'kimai.plugin'; @@ -128,7 +129,7 @@ class Kernel extends BaseKernel private function getBundleClasses(): array { - $pluginsDir = $this->getProjectDir() . '/var/plugins'; + $pluginsDir = $this->getProjectDir() . self::PLUGIN_DIRECTORY; if (!file_exists($pluginsDir)) { return []; }