Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Composer dependencies (installed with composer install)
vendor
composer.lock

# PhpStorm IDE configuration and cache
.idea
Expand Down
27 changes: 15 additions & 12 deletions Command/ExportTranslationsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,24 @@ protected function configure(): void
{

$this->addOption(
'locales', 'l', InputOption::VALUE_OPTIONAL,
'Only export files for given locales. e.g. "--locales=en,de"', null
'locales',
'l',
InputOption::VALUE_OPTIONAL,
'Only export files for given locales. e.g. "--locales=en,de"',
null
);
$this->addOption(
'domains', 'd', InputOption::VALUE_OPTIONAL,
'Only export files for given domains. e.g. "--domains=messages,validators"', null
'domains',
'd',
InputOption::VALUE_OPTIONAL,
'Only export files for given domains. e.g. "--domains=messages,validators"',
null
);
$this->addOption('format', 'f', InputOption::VALUE_OPTIONAL, 'Force the output format.', null);
$this->addOption(
'override', 'o', InputOption::VALUE_NONE,
'override',
'o',
InputOption::VALUE_NONE,
'Only export modified phrases (app/Resources/translations are exported fully anyway)'
);
$this->addOption('export-path', 'p', InputOption::VALUE_REQUIRED, 'Export files to given path.');
Expand Down Expand Up @@ -164,15 +172,10 @@ protected function exportFile(FileInterface $file)

/**
* If the output file exists we merge existing translations with those from the database.
*
* @param FileInterface $file
* @param string $outputFile
* @param array $translations
* @return array
*/
protected function mergeExistingTranslations($file, $outputFile, $translations)
protected function mergeExistingTranslations(FileInterface $file, string $outputFile, array $translations): array
{
if (file_exists($outputFile)) {
if (file_exists($outputFile) && method_exists($this->translator, 'getLoader')) {
$extension = pathinfo($outputFile, PATHINFO_EXTENSION);
$loader = $this->translator->getLoader($extension);
$messageCatalogue = $loader->load($outputFile, $file->getLocale(), $file->getDomain());
Expand Down
64 changes: 22 additions & 42 deletions Command/ImportTranslationsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Validator\Validation;
use Symfony\Contracts\Translation\TranslatorInterface;
Expand Down Expand Up @@ -53,13 +54,13 @@
)]
class ImportTranslationsCommand extends Command
{
/**
* @param TranslatorInterface $translator
*/
public function __construct(
private readonly TranslatorInterface $translator,
private readonly LocaleManagerInterface $localeManager,
private readonly FileImporter $fileImporter,
private readonly KernelInterface $kernel,
#[Autowire('%kernel.project_dir%')]
private readonly string $projectDir,
) {
parent::__construct();
}
Expand Down Expand Up @@ -106,7 +107,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$bundleName = $this->input->getArgument('bundle');
if ($bundleName) {
$bundle = $this->getApplication()->getKernel()->getBundle($bundleName);
$bundle = $this->kernel->getBundle($bundleName);
$this->importBundleTranslationFiles($bundle, $locales, $domains, (bool)$this->input->getOption('globals'));
} else {
if (!$this->input->getOption('import-path')) {
Expand Down Expand Up @@ -141,7 +142,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$this->importTranslationFilesFromPath($importPath, $locales, $domains);
}

if ($this->input->getOption('cache-clear')) {
if ($this->input->getOption('cache-clear') && method_exists($this->translator, 'removeLocalesCacheFiles')) {
$this->output->writeln('<info>Removing translations cache files ...</info>');
$this->translator->removeLocalesCacheFiles($locales);
}
Expand Down Expand Up @@ -181,8 +182,8 @@ protected function importTranslationFilesFromPath($path, array $locales, array $
protected function importComponentTranslationFiles(array $locales, array $domains)
{
$classes = [
Validation::class => '/Resources/translations',
Form::class => '/Resources/translations',
Validation::class => '/Resources/translations',
Form::class => '/Resources/translations',
AuthenticationException::class => '/../Resources/translations',
];

Expand All @@ -203,14 +204,10 @@ protected function importComponentTranslationFiles(array $locales, array $domain
/**
* Imports application translation files.
*/
protected function importAppTranslationFiles(array $locales, array $domains)
protected function importAppTranslationFiles(array $locales, array $domains): void
{
if (Kernel::MAJOR_VERSION >= 4) {
$translationPath = $this->getApplication()->getKernel()->getProjectDir() . '/translations';
$finder = $this->findTranslationsFiles($translationPath, $locales, $domains, false);
} else {
$finder = $this->findTranslationsFiles($this->getApplication()->getKernel()->getRootDir(), $locales, $domains);
}
$translationPath = $this->projectDir . '/translations';
$finder = $this->findTranslationsFiles($translationPath, $locales, $domains, false);
$this->importTranslationFiles($finder);
}

Expand All @@ -221,7 +218,7 @@ protected function importAppTranslationFiles(array $locales, array $domains)
*/
protected function importBundlesTranslationFiles(array $locales, array $domains, $global = false)
{
$bundles = $this->getApplication()->getKernel()->getBundles();
$bundles = $this->kernel->getBundles();

foreach ($bundles as $bundle) {
$this->importBundleTranslationFiles($bundle, $locales, $domains, $global);
Expand All @@ -230,20 +227,11 @@ protected function importBundlesTranslationFiles(array $locales, array $domains,

/**
* Imports translation files form the specific bundles.
*
* @param array $locales
* @param array $domains
* @param boolean $global
*/
protected function importBundleTranslationFiles(BundleInterface $bundle, $locales, $domains, $global = false)
protected function importBundleTranslationFiles(BundleInterface $bundle, array $locales, array $domains, bool $global = false): void
{
if ($global) {
$kernel = $this->getApplication()->getKernel();
if (Kernel::MAJOR_VERSION >= 4) {
$path = $kernel->getProjectDir() . '/app';
} else {
$path = $kernel->getRootDir();
}
$path = $this->projectDir . '/app';

$path .= '/Resources/' . $bundle->getName() . '/translations';

Expand All @@ -261,7 +249,7 @@ protected function importBundleTranslationFiles(BundleInterface $bundle, $locale
$bundle->getPath() . '/Resources/translations',
];

foreach($paths as $path) {
foreach ($paths as $path) {
$this->output->writeln(sprintf('<info># %s:</info>', $bundle->getName()));
$finder = $this->findTranslationsFiles($path, $locales, $domains, false);
$this->importTranslationFiles($finder);
Expand All @@ -270,10 +258,8 @@ protected function importBundleTranslationFiles(BundleInterface $bundle, $locale

/**
* Imports some translations files.
*
* @param Finder $finder
*/
protected function importTranslationFiles($finder)
protected function importTranslationFiles(?Finder $finder): void
{
if (!$finder instanceof Finder) {
$this->output->writeln('No file to import');
Expand All @@ -297,20 +283,17 @@ protected function importTranslationFiles($finder)

/**
* Return a Finder object if $path has a Resources/translations folder.
*
* @param string $path
* @return Finder
*/
protected function findTranslationsFiles($path, array $locales, array $domains, $autocompletePath = true)
protected function findTranslationsFiles(string $path, array $locales, array $domains, $autocompletePath = true): ?Finder
{
$finder = null;

if (preg_match('#^win#i', PHP_OS)) {
if (0 === stripos(PHP_OS_FAMILY, "win")) {
$path = preg_replace('#' . preg_quote(DIRECTORY_SEPARATOR, '#') . '#', '/', $path);
}

if (true === $autocompletePath) {
$dir = (str_starts_with((string) $path, $this->getApplication()->getKernel()->getProjectDir() . '/Resources')) ? $path : $path . '/Resources/translations';
$dir = (str_starts_with((string) $path, $this->projectDir . '/Resources')) ? $path : $path . '/Resources/translations';
} else {
$dir = $path;
}
Expand All @@ -327,12 +310,9 @@ protected function findTranslationsFiles($path, array $locales, array $domains,
return (null !== $finder && $finder->count() > 0) ? $finder : null;
}

/**
* @return string
*/
protected function getFileNamePattern(array $locales, array $domains)
protected function getFileNamePattern(array $locales, array $domains): string
{
$formats = $this->translator->getFormats();
$formats = method_exists($this->translator, 'getFormats') ? $this->translator->getFormats() : [];

if (count($domains)) {
$regex = sprintf('/((%s)\.(%s)\.(%s))/', implode('|', $domains), implode('|', $locales), implode('|', $formats));
Expand Down
9 changes: 4 additions & 5 deletions Controller/RestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
* @author Cédric Girard <c.girard@lexik.fr>
Expand All @@ -18,8 +19,6 @@ class RestController extends AbstractController
{
use CsrfCheckerTrait;

private $csrfTokenManager;

public function __construct(
private readonly DataGridRequestHandler $dataGridRequestHandler,
private readonly DataGridFormatter $dataGridFormatter,
Expand All @@ -43,7 +42,7 @@ public function listByProfileAction(Request $request, string $token): JsonRespon
}

/**
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* @throws NotFoundHttpException
*/
public function updateAction(Request $request, int $id): JsonResponse
{
Expand All @@ -55,7 +54,7 @@ public function updateAction(Request $request, int $id): JsonResponse
}

/**
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* @throws NotFoundHttpException
*/
public function deleteAction(int $id): JsonResponse
{
Expand All @@ -73,7 +72,7 @@ public function deleteAction(int $id): JsonResponse
}

/**
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* @throws NotFoundHttpException
*/
public function deleteTranslationAction(int $id, string $locale): JsonResponse
{
Expand Down
47 changes: 33 additions & 14 deletions Controller/TranslationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
use Lexik\Bundle\TranslationBundle\Form\Type\TransUnitType;
use Lexik\Bundle\TranslationBundle\Manager\LocaleManagerInterface;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
use Lexik\Bundle\TranslationBundle\Translation\TranslatorDecorator;
use Lexik\Bundle\TranslationBundle\Util\Csrf\CsrfCheckerTrait;
use Lexik\Bundle\TranslationBundle\Util\Overview\StatsAggregator;
use Lexik\Bundle\TranslationBundle\Util\Profiler\TokenFinder;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\SubmitButton;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand All @@ -23,8 +23,14 @@ class TranslationController extends AbstractController
{
use CsrfCheckerTrait;

public function __construct(private readonly StorageInterface $translationStorage, private readonly StatsAggregator $statsAggregator, private readonly TransUnitFormHandler $transUnitFormHandler, private readonly TranslatorInterface $lexikTranslator, private readonly TranslatorInterface $translator, private readonly LocaleManagerInterface $localeManager, private readonly ?TokenFinder $tokenFinder)
{
public function __construct(
private readonly StorageInterface $translationStorage,
private readonly StatsAggregator $statsAggregator,
private readonly TransUnitFormHandler $transUnitFormHandler,
private readonly TranslatorInterface $translator,
private readonly LocaleManagerInterface $localeManager,
private readonly ?TokenFinder $tokenFinder
) {
}

/**
Expand All @@ -34,7 +40,13 @@ public function overviewAction(): Response
{
$stats = $this->statsAggregator->getStats();

return $this->render('@LexikTranslation/Translation/overview.html.twig', ['layout' => $this->getParameter('lexik_translation.base_layout'), 'locales' => $this->getManagedLocales(), 'domains' => $this->translationStorage->getTransUnitDomains(), 'latestTrans' => $this->translationStorage->getLatestUpdatedAt(), 'stats' => $stats]);
return $this->render('@LexikTranslation/Translation/overview.html.twig', [
'layout' => $this->getParameter('lexik_translation.base_layout'),
'locales' => $this->getManagedLocales(),
'domains' => $this->translationStorage->getTransUnitDomains(),
'latestTrans' => $this->translationStorage->getLatestUpdatedAt(),
'stats' => $stats,
]);
}

/**
Expand All @@ -47,16 +59,23 @@ public function gridAction(): Response
$tokens = $this->tokenFinder->find();
}

return $this->render('@LexikTranslation/Translation/grid.html.twig', ['layout' => $this->getParameter('lexik_translation.base_layout'), 'inputType' => $this->getParameter('lexik_translation.grid_input_type'), 'autoCacheClean' => $this->getParameter('lexik_translation.auto_cache_clean'), 'toggleSimilar' => $this->getParameter('lexik_translation.grid_toggle_similar'), 'locales' => $this->getManagedLocales(), 'tokens' => $tokens]);
return $this->render('@LexikTranslation/Translation/grid.html.twig', [
'layout' => $this->getParameter('lexik_translation.base_layout'),
'inputType' => $this->getParameter('lexik_translation.grid_input_type'),
'autoCacheClean' => $this->getParameter('lexik_translation.auto_cache_clean'),
'toggleSimilar' => $this->getParameter('lexik_translation.grid_toggle_similar'),
'locales' => $this->getManagedLocales(),
'tokens' => $tokens,
]);
}

/**
* Remove cache files for managed locales.
*/
public function invalidateCacheAction(Request $request): Response
{
if (method_exists($this->lexikTranslator, 'removeLocalesCacheFiles')) {
$this->lexikTranslator->removeLocalesCacheFiles($this->getManagedLocales());
if (method_exists($this->translator, 'removeLocalesCacheFiles')) {
$this->translator->removeLocalesCacheFiles($this->getManagedLocales());
}

$message = $this->translator->trans('translations.cache_removed', [], 'LexikTranslationBundle');
Expand All @@ -67,7 +86,7 @@ public function invalidateCacheAction(Request $request): Response
return new JsonResponse(['message' => $message]);
}

$request->getSession()->getFlashBag()->add('success', $message);
$this->addFlash('success', $message);

return $this->redirect($this->generateUrl('lexik_translation_grid'));
}
Expand All @@ -82,22 +101,22 @@ public function newAction(Request $request): Response
if ($this->transUnitFormHandler->process($form, $request)) {
$message = $this->translator->trans('translations.successfully_added', [], 'LexikTranslationBundle');

$request->getSession()->getFlashBag()->add('success', $message);
$this->addFlash('success', $message);

$redirectUrl = $form->get('save_add')->isClicked() ? 'lexik_translation_new' : 'lexik_translation_grid';
/** @var SubmitButton $btn */
$btn = $form->get('save_add');
$redirectUrl = $btn->isClicked() ? 'lexik_translation_new' : 'lexik_translation_grid';

return $this->redirect($this->generateUrl($redirectUrl));
}

return $this->render('@LexikTranslation/Translation/new.html.twig', ['layout' => $this->getParameter('lexik_translation.base_layout'), 'form' => $form->createView()]);
return $this->render('@LexikTranslation/Translation/new.html.twig', ['layout' => $this->getParameter('lexik_translation.base_layout'), 'form' => $form->createView()]);
}

/**
* Returns managed locales.
*
* @return array
*/
protected function getManagedLocales()
protected function getManagedLocales(): array
{
return $this->localeManager->getLocales();
}
Expand Down
4 changes: 2 additions & 2 deletions DependencyInjection/Compiler/RegisterMappingPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver;
use Lexik\Bundle\TranslationBundle\Storage\StorageInterface;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

/**
* Doctrine metadata pass to add a driver to load model class mapping.
Expand All @@ -26,7 +26,7 @@ public function process(ContainerBuilder $container): void

$name = empty($storage['object_manager']) ? 'default' : $storage['object_manager'];

$ormDriverId = sprintf('doctrine.orm.%s_metadata_driver', $name);
$ormDriverId = sprintf('doctrine.orm.%s_metadata_driver', $name);
$mongodbDriverId = sprintf('doctrine_mongodb.odm.%s_metadata_driver', $name);

if (StorageInterface::STORAGE_ORM == $storage['type'] && $container->hasDefinition($ormDriverId)) {
Expand Down
Loading
Loading