You are here

public function LocalePluralFormatTest::testGetPluralFormat in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/locale/tests/src/Functional/LocalePluralFormatTest.php \Drupal\Tests\locale\Functional\LocalePluralFormatTest::testGetPluralFormat()

Tests locale_get_plural() and \Drupal::translation()->formatPlural() functionality.

File

core/modules/locale/tests/src/Functional/LocalePluralFormatTest.php, line 54

Class

LocalePluralFormatTest
Tests plural handling for various languages.

Namespace

Drupal\Tests\locale\Functional

Code

public function testGetPluralFormat() {

  // Import some .po files with formulas to set up the environment.
  // These will also add the languages to the system.
  $this
    ->importPoFile($this
    ->getPoFileWithSimplePlural(), [
    'langcode' => 'fr',
  ]);
  $this
    ->importPoFile($this
    ->getPoFileWithComplexPlural(), [
    'langcode' => 'hr',
  ]);

  // Attempt to import some broken .po files as well to prove that these
  // will not overwrite the proper plural formula imported above.
  $this
    ->importPoFile($this
    ->getPoFileWithMissingPlural(), [
    'langcode' => 'fr',
    'overwrite_options[not_customized]' => TRUE,
  ]);
  $this
    ->importPoFile($this
    ->getPoFileWithBrokenPlural(), [
    'langcode' => 'hr',
    'overwrite_options[not_customized]' => TRUE,
  ]);

  // Reset static caches from locale_get_plural() to ensure we get fresh data.
  drupal_static_reset('locale_get_plural');
  drupal_static_reset('locale_get_plural:plurals');
  drupal_static_reset('locale');

  // Expected plural translation strings for each plural index.
  $plural_strings = [
    // English is not imported in this case, so we assume built-in text
    // and formulas.
    'en' => [
      0 => '1 hour',
      1 => '@count hours',
    ],
    'fr' => [
      0 => '@count heure',
      1 => '@count heures',
    ],
    'hr' => [
      0 => '@count sat',
      1 => '@count sata',
      2 => '@count sati',
    ],
    // Hungarian is not imported, so it should assume the same text as
    // English, but it will always pick the plural form as per the built-in
    // logic, so only index -1 is relevant with the plural value.
    'hu' => [
      0 => '1 hour',
      -1 => '@count hours',
    ],
  ];

  // Expected plural indexes precomputed base on the plural formulas with
  // given $count value.
  $plural_tests = [
    'en' => [
      1 => 0,
      0 => 1,
      5 => 1,
      123 => 1,
      235 => 1,
    ],
    'fr' => [
      1 => 0,
      0 => 0,
      5 => 1,
      123 => 1,
      235 => 1,
    ],
    'hr' => [
      1 => 0,
      21 => 0,
      0 => 2,
      2 => 1,
      8 => 2,
      123 => 1,
      235 => 2,
    ],
    'hu' => [
      1 => -1,
      21 => -1,
      0 => -1,
    ],
  ];
  foreach ($plural_tests as $langcode => $tests) {
    foreach ($tests as $count => $expected_plural_index) {

      // Assert that the we get the right plural index.
      $this
        ->assertSame($expected_plural_index, locale_get_plural($count, $langcode), 'Computed plural index for ' . $langcode . ' for count ' . $count . ' is ' . $expected_plural_index);

      // Assert that the we get the right translation for that. Change the
      // expected index as per the logic for translation lookups.
      $expected_plural_index = $count == 1 ? 0 : $expected_plural_index;
      $expected_plural_string = str_replace('@count', $count, $plural_strings[$langcode][$expected_plural_index]);
      $this
        ->assertSame($expected_plural_string, \Drupal::translation()
        ->formatPlural($count, '1 hour', '@count hours', [], [
        'langcode' => $langcode,
      ])
        ->render(), 'Plural translation of 1 hours / @count hours for count ' . $count . ' in ' . $langcode . ' is ' . $expected_plural_string);

      // DO NOT use translation to pass translated strings into
      // PluralTranslatableMarkup::createFromTranslatedString() this way. It
      // is designed to be used with *already* translated text like settings
      // from configuration. We use PHP translation here just because we have
      // the expected result data in that format.
      $translated_string = \Drupal::translation()
        ->translate('1 hour' . PoItem::DELIMITER . '@count hours', [], [
        'langcode' => $langcode,
      ]);
      $plural = PluralTranslatableMarkup::createFromTranslatedString($count, $translated_string, [], [
        'langcode' => $langcode,
      ]);
      $this
        ->assertSame($expected_plural_string, $plural
        ->render());
    }
  }
}