8000 Added Translation Providers · symfony/symfony@b9a0e5e · GitHub
[go: up one dir, main page]

Skip to content

Commit b9a0e5e

Browse files
Olivier DolbeauwelcoMattic
authored andcommitted
Added Translation Providers
1 parent 1b94d88 commit b9a0e5e

File tree

71 files changed

+4106
-57
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+4106
-57
lines changed

link

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ if (!is_dir("$pathToProject/vendor/symfony")) {
4141
$sfPackages = array('symfony/symfony' => __DIR__);
4242

4343
$filesystem = new Filesystem();
44-
$braces = array('Bundle', 'Bridge', 'Component', 'Component/Security', 'Component/Mailer/Bridge', 'Component/Messenger/Bridge', 'Component/Notifier/Bridge', 'Contracts');
44+
$braces = array('Bundle', 'Bridge', 'Component', 'Component/Security', 'Component/Mailer/Bridge', 'Component/Messenger/Bridge', 'Component/Notifier/Bridge', 'Contracts', 'Component/Translation/Bridge');
4545
$directories = array_merge(...array_values(array_map(function ($part) {
4646
return glob(__DIR__.'/src/Symfony/'.$part.'/*', GLOB_ONLYDIR | GLOB_NOSORT);
4747
}, $braces)));
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Command;
13+
14+
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Input\InputArgument;
16+
use Symfony\Component\Console\Input\InputInterface;
17+
use Symfony\Component\Console\Input\InputOption;
18+
use Symfony\Component\Console\Output\OutputInterface;
19+
use Symfony\Component\Console\Style\SymfonyStyle;
20+
use Symfony\Component\Translation\Catalogue\TargetOperation;
21+
use Symfony\Component\Translation\MessageCatalogue;
22+
use Symfony\Component\Translation\Provider\TranslationProviders;
23+
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
24+
use Symfony\Component\Translation\Writer\TranslationWriterInterface;
25+
26+
/**
27+
* @author Mathieu Santostefano <msantostefano@protonmail.com>
28+
*
29+
* @experimental in 5.3
30+
*/
31+
final class TranslationPullCommand extends Command
32+
{
33+
use TranslationTrait;
34+
35+
protected static $defaultName = 'translation:pull';
36+
37+
private $providers;
38+
private $writer;
39+
private $reader;
40+
private $defaultLocale;
41+
private $transPaths;
42+
private $enabledLocales;
43+
44+
public function __construct(TranslationProviders $providers, TranslationWriterInterface $writer, TranslationReaderInterface $reader, string $defaultLocale, string $defaultTransPath = null, array $transPaths = [], array $enabledLocales = [])
45+
{
46+
$this->providers = $providers;
47+
$this->writer = $writer;
48+
$this->reader = $reader;
49+
$this->defaultLocale = $defaultLocale;
50+
$this->transPaths = $transPaths;
51+
$this->enabledLocales = $enabledLocales;
52+
53+
if (null !== $defaultTransPath) {
54+
$this->transPaths[] = $defaultTransPath;
55+
}
56+
57+
parent::__construct();
58+
}
59+
60+
/**
61+
* {@inheritdoc}
62+
*/
63+
protected function configure()
64+
{
65+
$keys = $this->providers->keys();
66+
$defaultProvider = 1 === \count($keys) ? $keys[0] : null;
67+
68+
$this
69+
->setDefinition([
70+
new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to pull translations from.', $defaultProvider),
71+
new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with provider ones (it will delete not synchronized messages).'),
72+
new InputOption('delete-obsolete', null, InputOption::VALUE_NONE, 'Delete translations available locally but not on provider.'),
73+
new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'),
74+
new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'),
75+
new InputOption('output-format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format.', 'xlf'),
76+
new InputOption('xliff-version', null, InputOption::VALUE_OPTIONAL, 'Override the default xliff version.', '1.2'),
77+
])
78+
->setDescription('Pull translations from a given provider.')
79+
->setHelp(<<<'EOF'
80+
The <info>%command.name%</info> pull translations from the given provider. Only
81+
new translations are pulled, existing ones are not overwritten.
82+
83+
You can overwrite existing translations:
84+
85+
<info>php %command.full_name% --force provider</info>
86+
87+
You can remove local translations which are not present on the provider:
88+
89+
<info>php %command.full_name% --delete-obsolete provider</info>
90+
91+
Full example:
92+
93+
<info>php %command.full_name% provider --force --delete-obsolete --domains=messages,validators --locales=en</info>
94+
95+
This command will pull all translations linked to domains messages and validators
96+
for the locale en. Local translations for the specified domains and locale will
97+
be erased if they're not present on the provider and overwritten if it's the
98+
case. Local translations for others domains and locales will be ignored.
99+
EOF
100+
)
101+
;
102+
}
103+
104+
/**
105+
* {@inheritdoc}
106+
*/
107+
protected function execute(InputInterface $input, OutputInterface $output): int
108+
{
109+
$io = new SymfonyStyle($input, $output);
110+
111+
$provider = $this->providers->get($input->getArgument('provider'));
112+
$locales = $input->getOption('locales') ?: $this->enabledLocales;
113+
$domains = $input->getOption('domains');
114+
$force = $input->getOption('force');
115+
$deleteObsolete = $input->getOption('delete-obsolete');
116+
117+
$writeOptions = [
118+
'path' => end($this->transPaths),
119+
'xliff_version' => $input->getOption('xliff-version'),
120+
];
121+
122+
if (!$domains) {
123+
$domains = $provider->getDomains();
124+
}
125+
126+
$providerTranslations = $provider->read($domains, $locales);
127+
128+
if ($force) {
129+
if ($deleteObsolete) {
130+
$io->note('The --delete-obsolete option is ineffective with --force');
131+
}
132+
133+
foreach ($providerTranslations->getCatalogues() as $catalogue) {
134+
$operation = new TargetOperation((new MessageCatalogue($catalogue->getLocale())), $catalogue);
135+
$operation->moveMessagesToIntlDomainsIfPossible();
136+
$this->writer->write($operation->getResult(), $input->getOption('output-format'), $writeOptions);
137+
}
138+
139+
$io->success(sprintf(
140+
'Local translations has been updated from %s (for [%s] locale(s), and [%s] domain(s)).',
141+
$provider->getName(),
142+
implode(', ', $locales),
143+
implode(', ', $domains)
144+
));
145+
146+
return 0;
147+
}
148+
149+
$localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
150+
151+
if ($deleteObsolete) {
152+
$obsoleteTranslations = $localTranslations->diff($providerTranslations);
153+
$translationsWithoutObsoleteToWrite = $localTranslations->diff($obsoleteTranslations);
154+
155+
foreach ($translationsWithoutObsoleteToWrite->getCatalogues() as $catalogue) {
156+
$this->writer->write($catalogue, $input->getOption('output-format'), $writeOptions);
157+
}
158+
159+
$io->success('Obsolete translations has been locally removed.');
160+
}
161+
162+
$translationsToWrite = $providerTranslations->diff($localTranslations);
163+
164+
foreach ($translationsToWrite->getCatalogues() as $catalogue) {
165+
$this->writer->write($catalogue, $input->getOption('output-format'), $writeOptions);
166+
}
167+
168+
$io->success(sprintf(
169+
'New translations from %s has been written locally (for [%s] locale(s), and [%s] domain(s)).',
170+
$provider->getName(),
171+
implode(', ', $locales),
172+
implode(', ', $domains)
173+
));
174+
175+
return 0;
176+
}
177+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Command;
13+
14+
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Exception\InvalidArgumentException;
16+
use Symfony\Component\Console\Input\InputArgument;
17+
use Symfony\Component\Console\Input\InputInterface;
18+
use Symfony\Component\Console\Input\InputOption;
19+
use Symfony\Component\Console\Output\OutputInterface;
20+
use Symfony\Component\Console\Style\SymfonyStyle;
21+
use Symfony\Component\Translation\Provider\TranslationProviders;
22+
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
23+
24+
/**
25+
* @author Mathieu Santostefano <msantostefano@protonmail.com>
26+
*
27+
* @experimental in 5.3
28+
*/
29+
final class TranslationPushCommand extends Command
30+
{
31+
use TranslationTrait;
32+
33+
protected static $defaultName = 'translation:push';
34+
35+
private $providers;
36+
private $reader;
37+
private $transPaths;
38+
private $enabledLocales;
39+
40+
public function __construct(TranslationProviders $providers, TranslationReaderInterface $reader, string $defaultTransPath = null, array $transPaths = [], array $enabledLocales = [])
41+
{
42+
$this->providers = $providers;
43+
$this->reader = $reader;
44+
$this->transPaths = $transPaths;
45+
$this->enabledLocales = $enabledLocales;
46+
47+
if (null !== $defaultTransPath) {
48+
$this->transPaths[] = $defaultTransPath;
49+
}
50+
51+
parent::__construct();
52+
}
53+
54+
/**
55+
* {@inheritdoc}
56+
*/
57+
protected function configure()
58+
{
59+
$keys = $this->providers->keys();
60+
$defaultProvider = 1 === \count($keys) ? $keys[0] : null;
61+
62+
$this
63+
->setDefinition([
64+
new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to push translations to.', $defaultProvider),
65+
new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with local ones (it will delete not synchronized messages).'),
66+
new InputOption('delete-obsolete', null, InputOption::VALUE_NONE, 'Delete translations available on provider but not locally.'),
67+
new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to push.'),
68+
new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to push.', $this->enabledLocales),
69+
new InputOption('output-format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format.', 'xlf'),
70+
new InputOption('xliff-version', null, InputOption::VALUE_OPTIONAL, 'Override the default xliff version.', '1.2'),
71+
])
72+
->setDescription('Push translations to a given provider.')
73+
->setHelp(<<<'EOF'
74+
The <info>%command.name%</info> push translations to the given provider. Only new
75+
translations are pushed, existing ones are not overwritten.
76+
77+
You can overwrite existing translations:
78+
79+
<info>php %command.full_name% --force provider</info>
80+
81+
You can delete provider translations which are not present locally:
82+
83+
<info>php %command.full_name% --delete-obsolete provider</info>
84+
85+
Full example:
86+
87+
<info>php %command.full_name% provider --force --delete-obsolete --domains=messages,validators --locales=en</info>
88+
89+
This command will push all translations linked to domains messages and validators
90+
for the locale en. Provider translations for the specified domains and locale will
91+
be erased if they're not present locally and overwritten if it's the
92+
case. Provider translations for others domains and locales will be ignored.
93+
EOF
94+
)
95+
;
96+
}
97+
98+
/**
99+
* {@inheritdoc}
100+
*/
101+
protected function execute(InputInterface $input, OutputInterface $output): int
102+
{
103+
if (!$this->enabledLocales) {
104+
throw new InvalidArgumentException('You must defined framewor F41A k.translator.enabled_locales config key in order to work with providers.');
105+
}
106+
107+
$io = new SymfonyStyle($input, $output);
108+
109+
$provider = $this->providers->get($input->getArgument('provider'));
110+
$domains = $input->getOption('domains');
111+
$locales = $input->getOption('locales');
112+
$force = $input->getOption('force');
113+
$deleteObsolete = $input->getOption('delete-obsolete');
114+
115+
$localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
116+
117+
if (!$domains) {
118+
$domains = $localTranslations->getDomains();
119+
}
120+
121+
if (!$deleteObsolete && $force) {
122+
$provider->write($localTranslations);
123+
124+
$io->success(sprintf(
125+
'All local translations has been sent to %s (for [%s] locale(s), and [%s] domain(s)).',
126+
$provider->getName(),
127+
implode(', ', $locales),
128+
implode(', ', $domains)
129+
));
130+
131+
return 0;
132+
}
133+
134+
$providerTranslations = $provider->read($domains, $locales);
135+
136+
if ($deleteObsolete) {
137+
$obsoleteMessages = $providerTranslations->diff($localTranslations);
138+
$provider->delete($obsoleteMessages);
139+
140+
$io->success(sprintf(
141+
'Obsolete translations on %s has been deleted (for [%s] locale(s), and [%s] domain(s)).',
142+
$provider->getName(),
143+
implode(', ', $locales),
144+
implode(', ', $domains)
145+
));
146+
}
147+
148+
$translationsToWrite = $localTranslations->diff($providerTranslations);
149+
150+
if ($force) {
151+
$translationsToWrite->addBag($localTranslations->intersect($providerTranslations));
152+
}
153+
154+
$provider->write($translationsToWrite);
155+
156+
$io->success(sprintf(
157+
'%s local translations has been sent to %s (for [%s] locale(s), and [%s] domain(s)).',
158+
$force ? 'All' : 'New',
159+
$input->getArgument('provider'),
160+
implode(', ', $locales),
161+
implode(', ', $domains)
162+
));
163+
164+
return 0;
165+
}
166+
}

0 commit comments

Comments
 (0)
0