Skip to content

Commit a48b7f3

Browse files
authored
Make translations tool theme-aware (#2315)
* Make translation tools theme-aware * Add support for theme.controller (needed to render some module templates)
1 parent 73af14b commit a48b7f3

3 files changed

Lines changed: 106 additions & 8 deletions

File tree

src/SimpleSAML/Command/UnusedTranslatableStringsCommand.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ protected function configure(): void
5555
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
5656
'Which modules to perform this action on',
5757
);
58+
$this->addOption(
59+
'themes',
60+
null,
61+
InputOption::VALUE_NEGATABLE,
62+
'Include/exclude templates from themes directories of modules (default --themes)',
63+
true, /* safe default, so we don't lose translations */
64+
);
65+
$this->addOption(
66+
'theme-controller',
67+
null,
68+
InputOption::VALUE_REQUIRED,
69+
'Specify a custom TemplateControllerInterface class (usually for use with themes)',
70+
);
5871
}
5972

6073

@@ -99,6 +112,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
99112
$phpScanner = new PhpScanner(...$translationDomains);
100113
$phpScanner->setFunctions(['trans' => 'gettext', 'noop' => 'gettext']);
101114

115+
if ($input->getOption('theme-controller') !== null) {
116+
Configuration::setPreLoadedConfig(
117+
Configuration::loadFromArray(
118+
array_merge(
119+
Configuration::getInstance()->toArray(),
120+
['theme.controller' => $input->getOption('theme-controller'),],
121+
),
122+
),
123+
);
124+
}
125+
102126
$translationUtils = new Utils\Translate(Configuration::getInstance());
103127
$twigTranslations = [];
104128
// Scan files in base
@@ -110,7 +134,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
110134
$phpScanner = $translationUtils->getTranslationsFromPhp($module, $phpScanner);
111135

112136
// Scan Twig-templates
113-
$twigTranslations = array_merge($twigTranslations, $translationUtils->getTranslationsFromTwig($module));
137+
$twigTranslations = array_merge(
138+
$twigTranslations,
139+
$translationUtils->getTranslationsFromTwig($module, $input->getOption('themes')),
140+
);
114141
}
115142

116143
// The catalogue returns an array with strings, while the php-scanner returns Translations-objects.

src/SimpleSAML/Command/UpdateTranslatableStringsCommand.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,19 @@ protected function configure(): void
6363
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
6464
'Which modules to perform this action on',
6565
);
66+
$this->addOption(
67+
'themes',
68+
null,
69+
InputOption::VALUE_NEGATABLE,
70+
'Include/exclude templates from themes directories of modules (default --no-themes)',
71+
false,
72+
);
73+
$this->addOption(
74+
'theme-controller',
75+
null,
76+
InputOption::VALUE_REQUIRED,
77+
'Specify a custom TemplateControllerInterface class (usually for use with themes)',
78+
);
6679
}
6780

6881
/**
@@ -127,6 +140,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
127140
$phpScanner = new PhpScanner(...$translationDomains);
128141
$phpScanner->setFunctions(['trans' => 'gettext', 'noop' => 'gettext']);
129142

143+
if ($input->getOption('theme-controller') !== null) {
144+
Configuration::setPreLoadedConfig(
145+
Configuration::loadFromArray(
146+
array_merge(
147+
Configuration::getInstance()->toArray(),
148+
['theme.controller' => $input->getOption('theme-controller'),],
149+
),
150+
),
151+
);
152+
}
153+
130154
$translationUtils = new Utils\Translate(Configuration::getInstance());
131155
$twigTranslations = [];
132156
// Scan files in base
@@ -138,7 +162,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
138162
$phpScanner = $translationUtils->getTranslationsFromPhp($module, $phpScanner);
139163

140164
// Scan Twig-templates
141-
$twigTranslations = array_merge($twigTranslations, $translationUtils->getTranslationsFromTwig($module));
165+
$twigTranslations = array_merge(
166+
$twigTranslations,
167+
$translationUtils->getTranslationsFromTwig($module, $input->getOption('themes')),
168+
);
142169
}
143170

144171
// The catalogue returns an array with strings, while the php-scanner returns Translations-objects.

src/SimpleSAML/Utils/Translate.php

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,20 @@
66

77
use Gettext\Scanner\PhpScanner;
88
use SimpleSAML\Configuration;
9+
use SimpleSAML\Error\Exception;
10+
use SimpleSAML\Module;
911
use SimpleSAML\XHTML\Template;
1012
use Symfony\Bridge\Twig\Translation\TwigExtractor;
1113
use Symfony\Component\Finder\Finder;
1214
use Symfony\Component\Translation\MessageCatalogue;
1315

16+
use function array_merge;
17+
use function explode;
18+
use function is_dir;
19+
use function str_starts_with;
20+
use function strlen;
21+
use function substr;
22+
1423
/**
1524
* @package SimpleSAMLphp
1625
*/
@@ -45,19 +54,54 @@ public function getTranslationsFromPhp(string $module, PhpScanner $phpScanner):
4554
}
4655

4756

48-
public function getTranslationsFromTwig(string $module): array
57+
public function getTranslationsFromTwig(string $module, bool $includeThemes = false): array
4958
{
5059
$twigTranslations = [];
5160
$moduleDir = $this->baseDir . ($module === '' ? '' : 'modules/' . $module . '/');
5261
$moduleTemplateDir = $moduleDir . 'templates/';
62+
$moduleThemeDir = $moduleDir . 'themes/';
63+
$moduleDirs = [];
64+
if (is_dir($moduleTemplateDir)) {
65+
$moduleDirs[] = $moduleTemplateDir;
66+
}
67+
if ($includeThemes && is_dir($moduleThemeDir)) {
68+
$moduleDirs[] = $moduleThemeDir;
69+
}
5370

5471
// Scan Twig-templates
5572
$finder = new Finder();
56-
foreach ($finder->files()->in($moduleTemplateDir)->name('*.twig') as $file) {
57-
$template = new Template(
58-
$this->configuration,
59-
($module ? ($module . ':') : '') . $file->getRelativePathname(),
60-
);
73+
foreach ($finder->files()->in($moduleDirs)->name('*.twig') as $file) {
74+
if (!($includeThemes && str_starts_with($file->getPathname(), $moduleThemeDir))) {
75+
/* process templates/ directory */
76+
$template = new Template(
77+
$this->configuration,
78+
($module ? ($module . ':') : '') . $file->getRelativePathname(),
79+
);
80+
} else {
81+
/* process themed templates from other modules */
82+
list($theme, $themedModule) = explode(
83+
DIRECTORY_SEPARATOR,
84+
substr($file->getPath(), strlen($moduleThemeDir)),
85+
2,
86+
);
87+
if ($themedModule !== 'default' && !Module::isModuleEnabled($themedModule)) {
88+
throw new Exception(
89+
'The module \'' . $themedModule . '\' (themed by \'' . $module . ':' . $theme . '\') ' .
90+
'is not enabled. Perhaps you need to need to require --dev simplesamlphp-module-' .
91+
$themedModule . ' within the ' . $module . ' module?',
92+
);
93+
}
94+
$template = new Template(
95+
Configuration::loadFromArray(
96+
array_merge(
97+
$this->configuration->toArray(),
98+
['theme.use' => $module . ':' . $theme,],
99+
),
100+
),
101+
($themedModule !== 'default' ? ($themedModule . ':') : '') .
102+
substr($file->getRelativePathname(), strlen($theme . DIRECTORY_SEPARATOR . $themedModule) + 1),
103+
);
104+
}
61105

62106
$catalogue = new MessageCatalogue('en', []);
63107
$extractor = new TwigExtractor($template->getTwig());

0 commit comments

Comments
 (0)