Chris@0: 'Lolspeak', Chris@0: 'zz' => 'Lolspeak2', Chris@0: ]; Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function setUp() { Chris@0: parent::setUp(); Chris@0: Chris@0: // Setup test_theme. Chris@0: \Drupal::service('theme_handler')->install(['test_theme']); Chris@0: $this->config('system.theme')->set('default', 'test_theme')->save(); Chris@0: Chris@0: // Create and log in as admin. Chris@0: $this->adminUser = $this->drupalCreateUser([ Chris@0: 'administer languages', Chris@0: 'access administration pages', Chris@0: 'administer site configuration', Chris@0: 'translate interface' Chris@0: ]); Chris@0: $this->drupalLogin($this->adminUser); Chris@0: Chris@0: // Install languages. Chris@0: $this->installLanguages(); Chris@0: Chris@0: // Assign Lolspeak (xx) to be the default language. Chris@0: $this->config('system.site')->set('default_langcode', 'xx')->save(); Chris@0: $this->rebuildContainer(); Chris@0: Chris@0: // Check that lolspeak is the default language for the site. Chris@0: $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), 'xx', 'Lolspeak is the default language'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Test Twig "trans" tags. Chris@0: */ Chris@0: public function testTwigTransTags() { Chris@0: // Run this once without and once with Twig debug because trans can work Chris@0: // differently depending on that setting. Chris@0: $this->drupalGet('twig-theme-test/trans', ['language' => \Drupal::languageManager()->getLanguage('xx')]); Chris@0: $this->assertTwigTransTags(); Chris@0: Chris@0: // Enable debug, rebuild the service container, and clear all caches. Chris@0: $parameters = $this->container->getParameter('twig.config'); Chris@0: $parameters['debug'] = TRUE; Chris@0: $this->setContainerParameter('twig.config', $parameters); Chris@0: $this->rebuildContainer(); Chris@0: $this->resetAll(); Chris@0: Chris@0: $this->drupalGet('twig-theme-test/trans', ['language' => \Drupal::languageManager()->getLanguage('xx')]); Chris@0: $this->assertTwigTransTags(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Test empty Twig "trans" tags. Chris@0: */ Chris@0: public function testEmptyTwigTransTags() { Chris@0: $elements = [ Chris@0: '#type' => 'inline_template', Chris@0: '#template' => '{% trans %}{% endtrans %}', Chris@0: ]; Chris@0: /** @var \Drupal\Core\Render\RendererInterface $renderer */ Chris@0: $renderer = \Drupal::service('renderer'); Chris@0: Chris@0: try { Chris@0: $renderer->renderPlain($elements); Chris@0: Chris@0: $this->fail('{% trans %}{% endtrans %} did not throw an exception.'); Chris@0: } Chris@0: catch (\Twig_Error_Syntax $e) { Chris@0: $this->assertTrue(strstr($e->getMessage(), '{% trans %} tag cannot be empty'), '{% trans %}{% endtrans %} threw the expected exception.'); Chris@0: } Chris@0: catch (\Exception $e) { Chris@0: $this->fail('{% trans %}{% endtrans %} threw an unexpected exception.'); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Asserts Twig trans tags. Chris@0: */ Chris@0: protected function assertTwigTransTags() { Chris@0: $this->assertText( Chris@0: 'OH HAI SUNZ', Chris@0: '{% trans "Hello sun." %} was successfully translated.' Chris@0: ); Chris@0: Chris@0: $this->assertText( Chris@0: 'O HAI SUNZZZZZZZ', Chris@0: '{% trans "Hello sun." with {"context": "Lolspeak"} %} was successfully translated.' Chris@0: ); Chris@0: Chris@0: $this->assertText( Chris@0: 'O HERRO ERRRF.', Chris@0: '{{ "Hello Earth."|trans }} was successfully translated.' Chris@0: ); Chris@0: Chris@0: $this->assertText( Chris@0: 'OH HAI TEH MUUN', Chris@0: '{% trans %}Hello moon.{% endtrans %} was successfully translated.' Chris@0: ); Chris@0: Chris@0: $this->assertText( Chris@0: 'O HAI STARRRRR', Chris@0: '{% trans %} with {% plural count = 1 %} was successfully translated.' Chris@0: ); Chris@0: Chris@0: $this->assertText( Chris@0: 'O HAI 2 STARZZZZ', Chris@0: '{% trans %} with {% plural count = 2 %} was successfully translated.' Chris@0: ); Chris@0: Chris@0: $this->assertRaw( Chris@0: 'ESCAPEE: &"<>', Chris@0: '{{ token }} was successfully translated and prefixed with "@".' Chris@0: ); Chris@0: Chris@0: $this->assertRaw( Chris@0: 'PLAYSHOLDR: &"<>', Chris@0: '{{ token|placeholder }} was successfully translated and prefixed with "%".' Chris@0: ); Chris@0: Chris@0: $this->assertRaw( Chris@0: 'DIS complex token HAZ LENGTH OV: 3. IT CONTAYNZ: 12345 AN &"<>.', Chris@0: '{{ complex.tokens }} were successfully translated with appropriate prefixes.' Chris@0: ); Chris@0: Chris@0: $this->assertText( Chris@0: 'I have context.', Chris@0: '{% trans %} with a context only msgid was excluded from translation.' Chris@0: ); Chris@0: Chris@0: $this->assertText( Chris@0: 'I HAZ KONTEX.', Chris@0: '{% trans with {"context": "Lolspeak"} %} was successfully translated with context.' Chris@0: ); Chris@0: Chris@0: $this->assertText( Chris@0: 'O HAI NU TXT.', Chris@0: '{% trans with {"langcode": "zz"} %} was successfully translated in specified language.' Chris@0: ); Chris@0: Chris@0: $this->assertText( Chris@0: 'O HAI NU TXTZZZZ.', Chris@0: '{% trans with {"context": "Lolspeak", "langcode": "zz"} %} was successfully translated with context in specified language.' Chris@0: ); Chris@0: // Makes sure https://www.drupal.org/node/2489024 doesn't happen without Chris@0: // twig debug. Chris@0: $this->assertNoText(pi(), 'Running php code inside a Twig trans is not possible.'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Helper function: install languages. Chris@0: */ Chris@0: protected function installLanguages() { Chris@0: foreach ($this->languages as $langcode => $name) { Chris@0: // Generate custom .po contents for the language. Chris@0: $contents = $this->poFileContents($langcode); Chris@0: if ($contents) { Chris@0: // Add test language for translation testing. Chris@0: $edit = [ Chris@0: 'predefined_langcode' => 'custom', Chris@0: 'langcode' => $langcode, Chris@0: 'label' => $name, Chris@0: 'direction' => LanguageInterface::DIRECTION_LTR, Chris@0: ]; Chris@0: Chris@0: // Install the language in Drupal. Chris@0: $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language')); Chris@0: $this->assertRaw('"edit-languages-' . $langcode . '-weight"', 'Language code found.'); Chris@0: Chris@0: // Import the custom .po contents for the language. Chris@0: $filename = \Drupal::service('file_system')->tempnam('temporary://', "po_") . '.po'; Chris@0: file_put_contents($filename, $contents); Chris@0: $options = [ Chris@0: 'files[file]' => $filename, Chris@0: 'langcode' => $langcode, Chris@0: 'customized' => TRUE, Chris@0: ]; Chris@0: $this->drupalPostForm('admin/config/regional/translate/import', $options, t('Import')); Chris@0: drupal_unlink($filename); Chris@0: } Chris@0: } Chris@0: $this->container->get('language_manager')->reset(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Generate a custom .po file for a specific test language. Chris@0: * Chris@0: * @param string $langcode Chris@0: * The langcode of the specified language. Chris@0: * Chris@0: * @return string|false Chris@0: * The .po contents for the specified language or FALSE if none exists. Chris@0: */ Chris@0: protected function poFileContents($langcode) { Chris@0: if ($langcode === 'xx') { Chris@0: return <<< EOF Chris@0: msgid "" Chris@0: msgstr "" Chris@0: "Project-Id-Version: Drupal 8\\n" Chris@0: "MIME-Version: 1.0\\n" Chris@0: "Content-Type: text/plain; charset=UTF-8\\n" Chris@0: "Content-Transfer-Encoding: 8bit\\n" Chris@0: "Plural-Forms: nplurals=2; plural=(n > 1);\\n" Chris@0: Chris@0: msgid "Hello sun." Chris@0: msgstr "OH HAI SUNZ" Chris@0: Chris@0: msgctxt "Lolspeak" Chris@0: msgid "Hello sun." Chris@0: msgstr "O HAI SUNZZZZZZZ" Chris@0: Chris@0: msgid "Hello Earth." Chris@0: msgstr "O HERRO ERRRF." Chris@0: Chris@0: msgid "Hello moon." Chris@0: msgstr "OH HAI TEH MUUN" Chris@0: Chris@0: msgid "Hello star." Chris@0: msgid_plural "Hello @count stars." Chris@0: msgstr[0] "O HAI STARRRRR" Chris@0: msgstr[1] "O HAI @count STARZZZZ" Chris@0: Chris@0: msgid "Escaped: @string" Chris@0: msgstr "ESCAPEE: @string" Chris@0: Chris@0: msgid "Placeholder: %string" Chris@0: msgstr "PLAYSHOLDR: %string" Chris@0: Chris@0: msgid "This @token.name has a length of: @count. It contains: %token.numbers and @token.bad_text." Chris@0: msgstr "DIS @token.name HAZ LENGTH OV: @count. IT CONTAYNZ: %token.numbers AN @token.bad_text." Chris@0: Chris@0: msgctxt "Lolspeak" Chris@0: msgid "I have context." Chris@0: msgstr "I HAZ KONTEX." Chris@0: EOF; Chris@0: } Chris@0: elseif ($langcode === 'zz') { Chris@0: return <<< EOF Chris@0: msgid "" Chris@0: msgstr "" Chris@0: "Project-Id-Version: Drupal 8\\n" Chris@0: "MIME-Version: 1.0\\n" Chris@0: "Content-Type: text/plain; charset=UTF-8\\n" Chris@0: "Content-Transfer-Encoding: 8bit\\n" Chris@0: "Plural-Forms: nplurals=2; plural=(n > 1);\\n" Chris@0: Chris@0: msgid "Hello new text." Chris@0: msgstr "O HAI NU TXT." Chris@0: Chris@0: msgctxt "Lolspeak" Chris@0: msgid "Hello new text." Chris@0: msgstr "O HAI NU TXTZZZZ." Chris@0: EOF; Chris@0: } Chris@0: return FALSE; Chris@0: } Chris@0: Chris@0: }