From b2a4c4147fc6c477b32718524089178394a831b0 Mon Sep 17 00:00:00 2001
From: Mark Carver <mark.carver@me.com>
Date: Wed, 10 Jul 2013 18:36:06 -0500
Subject: Issue #1927584 by Mark Carver, penyaskito, Cottser, drupalninja99,
 jenlampton, John Bickar, geoffreyr, ezeedub: Handle trans block as Twig
 extension

---
 .../Drupal/system/Tests/Theme/TwigTransTest.php    | 223 +++++++++++++++++++++
 .../twig_theme_test/TwigThemeTestController.php    |  10 +
 .../templates/twig_theme_test.trans.html.twig      |  53 +++++
 .../modules/twig_theme_test/twig_theme_test.module |   4 +
 .../twig_theme_test/twig_theme_test.routing.yml    |   6 +
 5 files changed, 296 insertions(+)
 create mode 100644 core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php
 create mode 100644 core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.trans.html.twig

diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php
new file mode 100644
index 0000000..b2687f1
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php
@@ -0,0 +1,223 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Theme\TwigTransTest.
+ */
+
+namespace Drupal\system\Tests\Theme;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests twig trans and format_plural blocks.
+ */
+class TwigTransTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array(
+    'theme_test',
+    'twig_theme_test',
+    'locale',
+    'language'
+  );
+
+  protected $admin_user;
+  protected $langcode = 'xx';
+  protected $name = 'Lolspeak';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Twig Translation',
+      'description' => 'Test Twig translation tags.',
+      'group' => 'Theme',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp();
+
+    // Setup test_theme.
+    theme_enable(array('test_theme'));
+    \Drupal::config('system.theme')->set('default', 'test_theme')->save();
+
+    // Enable twig debug and write to the test settings.php file.
+    $this->settingsSet('twig_debug', TRUE);
+    $settings['settings']['twig_debug'] = (object) array(
+      'value' => TRUE,
+      'required' => TRUE,
+    );
+    $this->writeSettings($settings);
+
+    // Rebuild the service container and clear all caches.
+    $this->rebuildContainer();
+    $this->resetAll();
+
+    // Create and log in as admin.
+    $this->admin_user = $this->drupalCreateUser(array(
+      'administer languages',
+      'access administration pages',
+      'administer site configuration',
+      'translate interface'
+    ));
+    $this->drupalLogin($this->admin_user);
+
+    // Add test language for translation testing.
+    $edit = array(
+      'predefined_langcode' => 'custom',
+      'langcode' => $this->langcode,
+      'name' => $this->name,
+      'direction' => '0',
+    );
+
+    // Install the lolspeak language.
+    $this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
+    $this->assertRaw('"edit-languages-' . $this->langcode . '-weight"', 'Language code found.');
+
+    // Import a custom .po file for the lolspeak language.
+    $this->importPoFile($this->examplePoFile(), array(
+      'langcode' => $this->langcode,
+      'customized' => TRUE,
+    ));
+
+    // Assign lolspeak to be the default language.
+    $edit = array('site_default_language' => $this->langcode);
+    $this->drupalpost('admin/config/regional/settings', $edit, t('Save configuration'));
+
+    // Reset the static cache of the language list.
+    drupal_static_reset('language_list');
+
+    // Check that lolspeak is the default language for the site.
+    $this->assertEqual(language_default()->id, $this->langcode, $this->name . ' is the default language');
+  }
+
+  /**
+   * Test valid Twig "trans" blocks.
+   */
+  public function testTwigTransBlocks() {
+    $this->drupalGet('twig-theme-test/trans', array('language' => language_load('xx')));
+
+    $this->assertText(
+      'OH HAI SUNZ',
+      '{% trans "Hello sun." %} was successfully translated.'
+    );
+
+    $this->assertText(
+      'OH HAI TEH MUUN',
+      '{% trans %}Hello moon.{% endtrans %} was successfully translated.'
+    );
+
+    $this->assertText(
+      'O HAI STARRRRR',
+      '{% trans %} with {% plural count = 1 %} was successfully translated.'
+    );
+
+    $this->assertText(
+      'O HAI 2 STARZZZZ',
+      '{% trans %} with {% plural count = 2 %} was successfully translated.'
+    );
+
+    $this->assertRaw(
+      '<!-- TRANSLATION: "Hello star.", PLURAL: "Hello @count stars." -->',
+      'The "twig_debug" translation comment markup printed successfully for the above test.'
+    );
+
+    $this->assertRaw(
+      'ESCAPEE: &amp;&quot;&lt;&gt;',
+      '{{ token }} was successfully translated and prefixed with "@".'
+    );
+
+    $this->assertRaw(
+      '<!-- TRANSLATION: "Escaped: @string" -->',
+      'The "twig_debug" translation comment markup printed successfully for the above test.'
+    );
+
+    $this->assertRaw(
+      'PAS-THRU: &"<>',
+      '{{ token|passthrough }} was successfully translated and prefixed with "!".'
+    );
+
+    $this->assertRaw(
+      '<!-- TRANSLATION: "Pass-through: !string" -->',
+      'The "twig_debug" translation comment markup printed successfully for the above test.'
+    );
+
+    $this->assertRaw(
+      'PLAYSHOLDR: <em class="placeholder">&amp;&quot;&lt;&gt;</em>',
+      '{{ token|placeholder }} was successfully translated and prefixed with "%".'
+    );
+
+    $this->assertRaw(
+      '<!-- TRANSLATION: "Placeholder: %string" -->',
+      'The "twig_debug" translation comment markup printed successfully for the above test.'
+    );
+
+    $this->assertRaw(
+      'DIS complex token HAZ LENGTH OV: 3. IT CONTAYNZ: <em class="placeholder">12345</em> AN &amp;&quot;&lt;&gt;. LETS PAS TEH BAD TEXT THRU: &"<>.',
+      '{{ complex.tokens }} were successfully translated with appropriate prefixes.'
+    );
+
+    $this->assertRaw(
+      '<!-- TRANSLATION: "This @name has a length of: @count. It contains: %numbers and @bad_text. Lets pass the bad text through: !bad_text." -->',
+      'The "twig_debug" translation comment markup printed successfully for the above test.'
+    );
+
+  }
+
+  /**
+   * Helper function: import a standalone .po file in a given language.
+   * Borrowed from Drupal\locale\Tests\LocaleImportFunctionalTest.
+   *
+   * @param $contents
+   *   Contents of the .po file to import.
+   * @param $options
+   *   Additional options to pass to the translation import form.
+   */
+  protected function importPoFile($contents, array $options = array()) {
+    $name = tempnam('temporary://', "po_") . '.po';
+    file_put_contents($name, $contents);
+    $options['files[file]'] = $name;
+    $this->drupalPost('admin/config/regional/translate/import', $options, t('Import'));
+    drupal_unlink($name);
+  }
+
+  protected function examplePoFile() {
+    return <<< EOF
+msgid ""
+msgstr ""
+"Project-Id-Version: Drupal 8\\n"
+"MIME-Version: 1.0\\n"
+"Content-Type: text/plain; charset=UTF-8\\n"
+"Content-Transfer-Encoding: 8bit\\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
+
+msgid "Hello sun."
+msgstr "OH HAI SUNZ"
+
+msgid "Hello moon."
+msgstr "OH HAI TEH MUUN"
+
+msgid "Hello star."
+msgid_plural "Hello @count stars."
+msgstr[0] "O HAI STARRRRR"
+msgstr[1] "O HAI @count STARZZZZ"
+
+msgid "Escaped: @string"
+msgstr "ESCAPEE: @string"
+
+msgid "Pass-through: !string"
+msgstr "PAS-THRU: !string"
+
+msgid "Placeholder: %string"
+msgstr "PLAYSHOLDR: %string"
+
+msgid "This @name has a length of: @count. It contains: %numbers and @bad_text. Lets pass the bad text through: !bad_text."
+msgstr "DIS @name HAZ LENGTH OV: @count. IT CONTAYNZ: %numbers AN @bad_text. LETS PAS TEH BAD TEXT THRU: !bad_text."
+EOF;
+  }
+
+}
diff --git a/core/modules/system/tests/modules/twig_theme_test/lib/Drupal/twig_theme_test/TwigThemeTestController.php b/core/modules/system/tests/modules/twig_theme_test/lib/Drupal/twig_theme_test/TwigThemeTestController.php
index ef5fb70..cd809c8 100644
--- a/core/modules/system/tests/modules/twig_theme_test/lib/Drupal/twig_theme_test/TwigThemeTestController.php
+++ b/core/modules/system/tests/modules/twig_theme_test/lib/Drupal/twig_theme_test/TwigThemeTestController.php
@@ -29,4 +29,14 @@ public function phpVariablesRender() {
     return theme('twig_theme_test_php_variables');
   }
 
+  /**
+   * Menu callback for testing translation blocks in a Twig template.
+   */
+  public function transBlockRender() {
+    return array(
+      '#theme' => 'twig_theme_test_trans',
+    );
+  }
+
+
 }
diff --git a/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.trans.html.twig b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.trans.html.twig
new file mode 100644
index 0000000..bf2200b
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.trans.html.twig
@@ -0,0 +1,53 @@
+{# Output for the Twig trans block test. #}
+<div>
+  {% trans "Hello sun." %}
+</div>
+
+<div>
+  {% trans %}
+    Hello moon.
+  {% endtrans %}
+</div>
+
+<div>
+  {% set count = 1 %}
+  {% trans %}
+    Hello star.
+  {% plural count %}
+    Hello {{ count }} stars.
+  {% endtrans %}
+</div>
+
+<div>
+  {% set count = 2 %}
+  {% trans %}
+    Hello star.
+  {% plural count %}
+    Hello {{ count }} stars.
+  {% endtrans %}
+</div>
+
+{% set string = '&"<>' %}
+<div>
+  {% trans %}
+    Escaped: {{ string }}
+  {% endtrans %}
+</div>
+<div>
+  {% trans %}
+    Pass-through: {{ string|passthrough }}
+  {% endtrans %}
+</div>
+<div>
+  {% trans %}
+    Placeholder: {{ string|placeholder }}
+  {% endtrans %}
+</div>
+
+{% set token = {'name': 'complex token', 'numbers': '12345', 'bad_text': '&"<>' } %}
+{% set count = token|length %}
+<div>
+  {% trans %}
+    This {{ token.name }} has a length of: {{ count }}. It contains: {{ token.numbers|placeholder }} and {{ token.bad_text }}. Lets pass the bad text through: {{ token.bad_text|passthrough }}.
+  {% endtrans %}
+</div>
diff --git a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module
index 2ca2cd0..934d1b0 100644
--- a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module
+++ b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module
@@ -7,6 +7,10 @@ function twig_theme_test_theme($existing, $type, $theme, $path) {
   $items['twig_theme_test_php_variables'] = array(
     'template' => 'twig_theme_test.php_variables',
   );
+  $items['twig_theme_test_trans'] = array(
+    'variables' => array(),
+    'template' => 'twig_theme_test.trans',
+  );
   return $items;
 }
 
diff --git a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml
index cdc0ac1..17ac5b0 100644
--- a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml
+++ b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml
@@ -4,3 +4,9 @@ twig_theme_test_php_variables:
     _content: '\Drupal\twig_theme_test\TwigThemeTestController::phpVariablesRender'
   requirements:
     _permission: 'access content'
+twig_theme_test_trans:
+  pattern: '/twig-theme-test/trans'
+  defaults:
+    _content: '\Drupal\twig_theme_test\TwigThemeTestController::transBlockRender'
+  requirements:
+    _permission: 'access content'
-- 
1.8.2

