Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\system\Tests\Theme;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Language\LanguageInterface;
|
Chris@0
|
6 use Drupal\simpletest\WebTestBase;
|
Chris@0
|
7
|
Chris@0
|
8 /**
|
Chris@0
|
9 * Tests Twig "trans" tags.
|
Chris@0
|
10 *
|
Chris@0
|
11 * @group Theme
|
Chris@0
|
12 */
|
Chris@0
|
13 class TwigTransTest extends WebTestBase {
|
Chris@0
|
14
|
Chris@0
|
15 /**
|
Chris@0
|
16 * Modules to enable.
|
Chris@0
|
17 *
|
Chris@0
|
18 * @var array
|
Chris@0
|
19 */
|
Chris@0
|
20 public static $modules = [
|
Chris@0
|
21 'theme_test',
|
Chris@0
|
22 'twig_theme_test',
|
Chris@0
|
23 'locale',
|
Chris@0
|
24 'language'
|
Chris@0
|
25 ];
|
Chris@0
|
26
|
Chris@0
|
27 /**
|
Chris@0
|
28 * An administrative user for testing.
|
Chris@0
|
29 *
|
Chris@0
|
30 * @var \Drupal\user\Entity\User
|
Chris@0
|
31 */
|
Chris@0
|
32 protected $adminUser;
|
Chris@0
|
33
|
Chris@0
|
34 /**
|
Chris@0
|
35 * Custom languages.
|
Chris@0
|
36 *
|
Chris@0
|
37 * @var array
|
Chris@0
|
38 */
|
Chris@0
|
39 protected $languages = [
|
Chris@0
|
40 'xx' => 'Lolspeak',
|
Chris@0
|
41 'zz' => 'Lolspeak2',
|
Chris@0
|
42 ];
|
Chris@0
|
43
|
Chris@0
|
44 /**
|
Chris@0
|
45 * {@inheritdoc}
|
Chris@0
|
46 */
|
Chris@0
|
47 protected function setUp() {
|
Chris@0
|
48 parent::setUp();
|
Chris@0
|
49
|
Chris@0
|
50 // Setup test_theme.
|
Chris@0
|
51 \Drupal::service('theme_handler')->install(['test_theme']);
|
Chris@0
|
52 $this->config('system.theme')->set('default', 'test_theme')->save();
|
Chris@0
|
53
|
Chris@0
|
54 // Create and log in as admin.
|
Chris@0
|
55 $this->adminUser = $this->drupalCreateUser([
|
Chris@0
|
56 'administer languages',
|
Chris@0
|
57 'access administration pages',
|
Chris@0
|
58 'administer site configuration',
|
Chris@0
|
59 'translate interface'
|
Chris@0
|
60 ]);
|
Chris@0
|
61 $this->drupalLogin($this->adminUser);
|
Chris@0
|
62
|
Chris@0
|
63 // Install languages.
|
Chris@0
|
64 $this->installLanguages();
|
Chris@0
|
65
|
Chris@0
|
66 // Assign Lolspeak (xx) to be the default language.
|
Chris@0
|
67 $this->config('system.site')->set('default_langcode', 'xx')->save();
|
Chris@0
|
68 $this->rebuildContainer();
|
Chris@0
|
69
|
Chris@0
|
70 // Check that lolspeak is the default language for the site.
|
Chris@0
|
71 $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), 'xx', 'Lolspeak is the default language');
|
Chris@0
|
72 }
|
Chris@0
|
73
|
Chris@0
|
74 /**
|
Chris@0
|
75 * Test Twig "trans" tags.
|
Chris@0
|
76 */
|
Chris@0
|
77 public function testTwigTransTags() {
|
Chris@0
|
78 // Run this once without and once with Twig debug because trans can work
|
Chris@0
|
79 // differently depending on that setting.
|
Chris@0
|
80 $this->drupalGet('twig-theme-test/trans', ['language' => \Drupal::languageManager()->getLanguage('xx')]);
|
Chris@0
|
81 $this->assertTwigTransTags();
|
Chris@0
|
82
|
Chris@0
|
83 // Enable debug, rebuild the service container, and clear all caches.
|
Chris@0
|
84 $parameters = $this->container->getParameter('twig.config');
|
Chris@0
|
85 $parameters['debug'] = TRUE;
|
Chris@0
|
86 $this->setContainerParameter('twig.config', $parameters);
|
Chris@0
|
87 $this->rebuildContainer();
|
Chris@0
|
88 $this->resetAll();
|
Chris@0
|
89
|
Chris@0
|
90 $this->drupalGet('twig-theme-test/trans', ['language' => \Drupal::languageManager()->getLanguage('xx')]);
|
Chris@0
|
91 $this->assertTwigTransTags();
|
Chris@0
|
92 }
|
Chris@0
|
93
|
Chris@0
|
94 /**
|
Chris@0
|
95 * Test empty Twig "trans" tags.
|
Chris@0
|
96 */
|
Chris@0
|
97 public function testEmptyTwigTransTags() {
|
Chris@0
|
98 $elements = [
|
Chris@0
|
99 '#type' => 'inline_template',
|
Chris@0
|
100 '#template' => '{% trans %}{% endtrans %}',
|
Chris@0
|
101 ];
|
Chris@0
|
102 /** @var \Drupal\Core\Render\RendererInterface $renderer */
|
Chris@0
|
103 $renderer = \Drupal::service('renderer');
|
Chris@0
|
104
|
Chris@0
|
105 try {
|
Chris@0
|
106 $renderer->renderPlain($elements);
|
Chris@0
|
107
|
Chris@0
|
108 $this->fail('{% trans %}{% endtrans %} did not throw an exception.');
|
Chris@0
|
109 }
|
Chris@0
|
110 catch (\Twig_Error_Syntax $e) {
|
Chris@0
|
111 $this->assertTrue(strstr($e->getMessage(), '{% trans %} tag cannot be empty'), '{% trans %}{% endtrans %} threw the expected exception.');
|
Chris@0
|
112 }
|
Chris@0
|
113 catch (\Exception $e) {
|
Chris@0
|
114 $this->fail('{% trans %}{% endtrans %} threw an unexpected exception.');
|
Chris@0
|
115 }
|
Chris@0
|
116 }
|
Chris@0
|
117
|
Chris@0
|
118 /**
|
Chris@0
|
119 * Asserts Twig trans tags.
|
Chris@0
|
120 */
|
Chris@0
|
121 protected function assertTwigTransTags() {
|
Chris@0
|
122 $this->assertText(
|
Chris@0
|
123 'OH HAI SUNZ',
|
Chris@0
|
124 '{% trans "Hello sun." %} was successfully translated.'
|
Chris@0
|
125 );
|
Chris@0
|
126
|
Chris@0
|
127 $this->assertText(
|
Chris@0
|
128 'O HAI SUNZZZZZZZ',
|
Chris@0
|
129 '{% trans "Hello sun." with {"context": "Lolspeak"} %} was successfully translated.'
|
Chris@0
|
130 );
|
Chris@0
|
131
|
Chris@0
|
132 $this->assertText(
|
Chris@0
|
133 'O HERRO ERRRF.',
|
Chris@0
|
134 '{{ "Hello Earth."|trans }} was successfully translated.'
|
Chris@0
|
135 );
|
Chris@0
|
136
|
Chris@0
|
137 $this->assertText(
|
Chris@0
|
138 'OH HAI TEH MUUN',
|
Chris@0
|
139 '{% trans %}Hello moon.{% endtrans %} was successfully translated.'
|
Chris@0
|
140 );
|
Chris@0
|
141
|
Chris@0
|
142 $this->assertText(
|
Chris@0
|
143 'O HAI STARRRRR',
|
Chris@0
|
144 '{% trans %} with {% plural count = 1 %} was successfully translated.'
|
Chris@0
|
145 );
|
Chris@0
|
146
|
Chris@0
|
147 $this->assertText(
|
Chris@0
|
148 'O HAI 2 STARZZZZ',
|
Chris@0
|
149 '{% trans %} with {% plural count = 2 %} was successfully translated.'
|
Chris@0
|
150 );
|
Chris@0
|
151
|
Chris@0
|
152 $this->assertRaw(
|
Chris@0
|
153 'ESCAPEE: &"<>',
|
Chris@0
|
154 '{{ token }} was successfully translated and prefixed with "@".'
|
Chris@0
|
155 );
|
Chris@0
|
156
|
Chris@0
|
157 $this->assertRaw(
|
Chris@0
|
158 'PLAYSHOLDR: <em class="placeholder">&"<></em>',
|
Chris@0
|
159 '{{ token|placeholder }} was successfully translated and prefixed with "%".'
|
Chris@0
|
160 );
|
Chris@0
|
161
|
Chris@0
|
162 $this->assertRaw(
|
Chris@0
|
163 'DIS complex token HAZ LENGTH OV: 3. IT CONTAYNZ: <em class="placeholder">12345</em> AN &"<>.',
|
Chris@0
|
164 '{{ complex.tokens }} were successfully translated with appropriate prefixes.'
|
Chris@0
|
165 );
|
Chris@0
|
166
|
Chris@0
|
167 $this->assertText(
|
Chris@0
|
168 'I have context.',
|
Chris@0
|
169 '{% trans %} with a context only msgid was excluded from translation.'
|
Chris@0
|
170 );
|
Chris@0
|
171
|
Chris@0
|
172 $this->assertText(
|
Chris@0
|
173 'I HAZ KONTEX.',
|
Chris@0
|
174 '{% trans with {"context": "Lolspeak"} %} was successfully translated with context.'
|
Chris@0
|
175 );
|
Chris@0
|
176
|
Chris@0
|
177 $this->assertText(
|
Chris@0
|
178 'O HAI NU TXT.',
|
Chris@0
|
179 '{% trans with {"langcode": "zz"} %} was successfully translated in specified language.'
|
Chris@0
|
180 );
|
Chris@0
|
181
|
Chris@0
|
182 $this->assertText(
|
Chris@0
|
183 'O HAI NU TXTZZZZ.',
|
Chris@0
|
184 '{% trans with {"context": "Lolspeak", "langcode": "zz"} %} was successfully translated with context in specified language.'
|
Chris@0
|
185 );
|
Chris@0
|
186 // Makes sure https://www.drupal.org/node/2489024 doesn't happen without
|
Chris@0
|
187 // twig debug.
|
Chris@0
|
188 $this->assertNoText(pi(), 'Running php code inside a Twig trans is not possible.');
|
Chris@0
|
189 }
|
Chris@0
|
190
|
Chris@0
|
191 /**
|
Chris@0
|
192 * Helper function: install languages.
|
Chris@0
|
193 */
|
Chris@0
|
194 protected function installLanguages() {
|
Chris@0
|
195 foreach ($this->languages as $langcode => $name) {
|
Chris@0
|
196 // Generate custom .po contents for the language.
|
Chris@0
|
197 $contents = $this->poFileContents($langcode);
|
Chris@0
|
198 if ($contents) {
|
Chris@0
|
199 // Add test language for translation testing.
|
Chris@0
|
200 $edit = [
|
Chris@0
|
201 'predefined_langcode' => 'custom',
|
Chris@0
|
202 'langcode' => $langcode,
|
Chris@0
|
203 'label' => $name,
|
Chris@0
|
204 'direction' => LanguageInterface::DIRECTION_LTR,
|
Chris@0
|
205 ];
|
Chris@0
|
206
|
Chris@0
|
207 // Install the language in Drupal.
|
Chris@0
|
208 $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
|
Chris@0
|
209 $this->assertRaw('"edit-languages-' . $langcode . '-weight"', 'Language code found.');
|
Chris@0
|
210
|
Chris@0
|
211 // Import the custom .po contents for the language.
|
Chris@0
|
212 $filename = \Drupal::service('file_system')->tempnam('temporary://', "po_") . '.po';
|
Chris@0
|
213 file_put_contents($filename, $contents);
|
Chris@0
|
214 $options = [
|
Chris@0
|
215 'files[file]' => $filename,
|
Chris@0
|
216 'langcode' => $langcode,
|
Chris@0
|
217 'customized' => TRUE,
|
Chris@0
|
218 ];
|
Chris@0
|
219 $this->drupalPostForm('admin/config/regional/translate/import', $options, t('Import'));
|
Chris@0
|
220 drupal_unlink($filename);
|
Chris@0
|
221 }
|
Chris@0
|
222 }
|
Chris@0
|
223 $this->container->get('language_manager')->reset();
|
Chris@0
|
224 }
|
Chris@0
|
225
|
Chris@0
|
226 /**
|
Chris@0
|
227 * Generate a custom .po file for a specific test language.
|
Chris@0
|
228 *
|
Chris@0
|
229 * @param string $langcode
|
Chris@0
|
230 * The langcode of the specified language.
|
Chris@0
|
231 *
|
Chris@0
|
232 * @return string|false
|
Chris@0
|
233 * The .po contents for the specified language or FALSE if none exists.
|
Chris@0
|
234 */
|
Chris@0
|
235 protected function poFileContents($langcode) {
|
Chris@0
|
236 if ($langcode === 'xx') {
|
Chris@0
|
237 return <<< EOF
|
Chris@0
|
238 msgid ""
|
Chris@0
|
239 msgstr ""
|
Chris@0
|
240 "Project-Id-Version: Drupal 8\\n"
|
Chris@0
|
241 "MIME-Version: 1.0\\n"
|
Chris@0
|
242 "Content-Type: text/plain; charset=UTF-8\\n"
|
Chris@0
|
243 "Content-Transfer-Encoding: 8bit\\n"
|
Chris@0
|
244 "Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
Chris@0
|
245
|
Chris@0
|
246 msgid "Hello sun."
|
Chris@0
|
247 msgstr "OH HAI SUNZ"
|
Chris@0
|
248
|
Chris@0
|
249 msgctxt "Lolspeak"
|
Chris@0
|
250 msgid "Hello sun."
|
Chris@0
|
251 msgstr "O HAI SUNZZZZZZZ"
|
Chris@0
|
252
|
Chris@0
|
253 msgid "Hello Earth."
|
Chris@0
|
254 msgstr "O HERRO ERRRF."
|
Chris@0
|
255
|
Chris@0
|
256 msgid "Hello moon."
|
Chris@0
|
257 msgstr "OH HAI TEH MUUN"
|
Chris@0
|
258
|
Chris@0
|
259 msgid "Hello star."
|
Chris@0
|
260 msgid_plural "Hello @count stars."
|
Chris@0
|
261 msgstr[0] "O HAI STARRRRR"
|
Chris@0
|
262 msgstr[1] "O HAI @count STARZZZZ"
|
Chris@0
|
263
|
Chris@0
|
264 msgid "Escaped: @string"
|
Chris@0
|
265 msgstr "ESCAPEE: @string"
|
Chris@0
|
266
|
Chris@0
|
267 msgid "Placeholder: %string"
|
Chris@0
|
268 msgstr "PLAYSHOLDR: %string"
|
Chris@0
|
269
|
Chris@0
|
270 msgid "This @token.name has a length of: @count. It contains: %token.numbers and @token.bad_text."
|
Chris@0
|
271 msgstr "DIS @token.name HAZ LENGTH OV: @count. IT CONTAYNZ: %token.numbers AN @token.bad_text."
|
Chris@0
|
272
|
Chris@0
|
273 msgctxt "Lolspeak"
|
Chris@0
|
274 msgid "I have context."
|
Chris@0
|
275 msgstr "I HAZ KONTEX."
|
Chris@0
|
276 EOF;
|
Chris@0
|
277 }
|
Chris@0
|
278 elseif ($langcode === 'zz') {
|
Chris@0
|
279 return <<< EOF
|
Chris@0
|
280 msgid ""
|
Chris@0
|
281 msgstr ""
|
Chris@0
|
282 "Project-Id-Version: Drupal 8\\n"
|
Chris@0
|
283 "MIME-Version: 1.0\\n"
|
Chris@0
|
284 "Content-Type: text/plain; charset=UTF-8\\n"
|
Chris@0
|
285 "Content-Transfer-Encoding: 8bit\\n"
|
Chris@0
|
286 "Plural-Forms: nplurals=2; plural=(n > 1);\\n"
|
Chris@0
|
287
|
Chris@0
|
288 msgid "Hello new text."
|
Chris@0
|
289 msgstr "O HAI NU TXT."
|
Chris@0
|
290
|
Chris@0
|
291 msgctxt "Lolspeak"
|
Chris@0
|
292 msgid "Hello new text."
|
Chris@0
|
293 msgstr "O HAI NU TXTZZZZ."
|
Chris@0
|
294 EOF;
|
Chris@0
|
295 }
|
Chris@0
|
296 return FALSE;
|
Chris@0
|
297 }
|
Chris@0
|
298
|
Chris@0
|
299 }
|