Skip to content

Commit 2b56e4a

Browse files
maelanleborgnekbond
authored andcommitted
[Translator] Add configuration to filter dumped translations by domain
1 parent 280e95d commit 2b56e4a

File tree

6 files changed

+215
-60
lines changed

6 files changed

+215
-60
lines changed

src/Translator/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
## 2.19.0
4+
5+
- Add configuration to filter dumped translations by domain.
6+
37
## 2.16.0
48

59
- Increase version range of `intl-messageformat` to `^10.5.11`, in order to see

src/Translator/doc/index.rst

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ After installing the bundle, the following file should be created, thanks to the
6565
Usage
6666
-----
6767

68-
When warming up the Symfony cache, all of your translations will be dumped as JavaScript into the ``var/translations/`` directory.
68+
When warming up the Symfony cache, your translations will be dumped as JavaScript into the ``var/translations/`` directory.
6969
For a better developer experience, TypeScript types definitions are also generated aside those JavaScript files.
7070

7171
Then, you will be able to import those JavaScript translations in your assets.
@@ -75,6 +75,24 @@ Don't worry about your final bundle size, only the translations you use will be
7575

7676
This package requires the `translator` to be enabled in your Symfony application. If you don't use the `translator` service, the warmup command will not generate any translations.
7777

78+
Configuring the dumped translations
79+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
80+
81+
By default, all your translations will be exported. You can restrict the dumped messages by either
82+
including or excluding translation domains in your ``config/packages/ux_translator.yaml`` file:
83+
84+
.. code-block:: yaml
85+
86+
ux_translator:
87+
domains: ~ # Include all the domains
88+
89+
domains: foo # Include only domain 'foo'
90+
domains: '!foo' # Include all domains, except 'foo'
91+
92+
domains: [foo, bar] # Include only domains 'foo' and 'bar'
93+
domains: ['!foo', '!bar'] # Include all domains, except 'foo' and 'bar'
94+
95+
7896
Configuring the default locale
7997
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8098

src/Translator/src/DependencyInjection/Configuration.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
1515
use Symfony\Component\Config\Definition\ConfigurationInterface;
16+
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
1617

1718
/**
1819
* @author Hugo Alliaume <hugo@alliau.me>
@@ -28,6 +29,59 @@ public function getConfigTreeBuilder(): TreeBuilder
2829
$rootNode
2930
->children()
3031
->scalarNode('dump_directory')->defaultValue('%kernel.project_dir%/var/translations')->end()
32+
->arrayNode('domains')
33+
->info('List of domains to include/exclude from the generated translations. Prefix with a `!` to exclude a domain.')
34+
->children()
35+
->scalarNode('type')
36+
->validate()
37+
->ifNotInArray(['inclusive', 'exclusive'])
38+
->thenInvalid('The type of domains has to be inclusive or exclusive')
39+
->end()
40+
->end()
41+
->arrayNode('elements')
42+
->scalarPrototype()->end()
43+
->end()
44+
->end()
45+
->canBeUnset()
46+
->beforeNormalization()
47+
->ifString()
48+
->then(fn ($v) => ['elements' => [$v]])
49+
->end()
50+
->beforeNormalization()
51+
->ifTrue(function ($v) { return \is_array($v) && is_numeric(key($v)); })
52+
->then(function ($v) { return ['elements' => $v]; })
53+
->end()
54+
->validate()
55+
->always(function ($v) {
56+
$isExclusive = null;
57+
$elements = [];
58+
if (isset($v['type'])) {
59+
$isExclusive = 'exclusive' === $v['type'];
60+
}
61+
foreach ($v['elements'] as $domain) {
62+
if (str_starts_with($domain, '!')) {
63+
if (false === $isExclusive) {
64+
throw new InvalidConfigurationException('You cannot mix included and excluded domains.');
65+
}
66+
$isExclusive = true;
67+
$elements[] = substr($domain, 1);
68+
} else {
69+
if (true === $isExclusive) {
70+
throw new InvalidConfigurationException('You cannot mix included and excluded domains.');
71+
}
72+
$isExclusive = false;
73+
$elements[] = $domain;
74+
}
75+
}
76+
77+
if (!\count($elements)) {
78+
return null;
79+
}
80+
81+
return ['type' => $isExclusive ? 'exclusive' : 'inclusive', 'elements' => array_unique($elements)];
82+
})
83+
->end()
84+
->end()
3185
->end()
3286
;
3387

src/Translator/src/DependencyInjection/UxTranslatorExtension.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,15 @@ public function load(array $configs, ContainerBuilder $container)
3535
$loader = (new PhpFileLoader($container, new FileLocator(\dirname(__DIR__).'/../config')));
3636
$loader->load('services.php');
3737

38-
$container->getDefinition('ux.translator.translations_dumper')->setArgument(0, $config['dump_directory']);
38+
$dumperDefinition = $container->getDefinition('ux.translator.translations_dumper');
39+
$dumperDefinition->setArgument(0, $config['dump_directory']);
40+
41+
if (isset($config['domains'])) {
42+
$method = 'inclusive' === $config['domains']['type'] ? 'addIncludedDomain' : 'addExcludedDomain';
43+
foreach ($config['domains']['elements'] as $domainName) {
44+
$dumperDefinition->addMethodCall($method, [$domainName]);
45+
}
46+
}
3947
}
4048

4149
public function prepend(ContainerBuilder $container)

src/Translator/src/TranslationsDumper.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
*/
3333
class TranslationsDumper
3434
{
35+
private array $excludedDomains = [];
36+
private array $includedDomains = [];
37+
3538
public function __construct(
3639
private string $dumpDir,
3740
private MessageParametersExtractor $messageParametersExtractor,
@@ -84,6 +87,22 @@ public function dump(MessageCatalogueInterface ...$catalogues): void
8487
);
8588
}
8689

90+
public function addExcludedDomain(string $domain): void
91+
{
92+
if ($this->includedDomains) {
93+
throw new \LogicException('You cannot set both "excluded_domains" and "included_domains" at the same time.');
94+
}
95+
$this->excludedDomains[] = $domain;
96+
}
97+
98+
public function addIncludedDomain(string $domain): void
99+
{
100+
if ($this->excludedDomains) {
101+
throw new \LogicException('You cannot set both "excluded_domains" and "included_domains" at the same time.');
102+
}
103+
$this->includedDomains[] = $domain;
104+
}
105+
87106
/**
88107
* @return array<MessageId, array<Domain, array<Locale, string>>>
89108
*/
@@ -94,6 +113,12 @@ private function getTranslations(MessageCatalogueInterface ...$catalogues): arra
94113
foreach ($catalogues as $catalogue) {
95114
$locale = $catalogue->getLocale();
96115
foreach ($catalogue->getDomains() as $domain) {
116+
if (\in_array($domain, $this->excludedDomains, true)) {
117+
continue;
118+
}
119+
if ($this->includedDomains && !\in_array($domain, $this->includedDomains, true)) {
120+
continue;
121+
}
97122
foreach ($catalogue->all($domain) as $id => $message) {
98123
$realDomain = $catalogue->has($id, $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX)
99124
? $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX

0 commit comments

Comments
 (0)