diff options
author | webchick <webchick@24967.no-reply.drupal.org> | 2012-03-26 22:25:40 -0700 |
---|---|---|
committer | webchick <webchick@24967.no-reply.drupal.org> | 2012-03-26 22:25:40 -0700 |
commit | 0932803a2c0a61924209dfe277dec32bced63c0c (patch) | |
tree | b39ef4cb8019dc2e5e272cd52c3349789c5e3b38 /modules/locale | |
parent | 505974084d248ebcbb225fe328409ef59a9d4e5a (diff) | |
download | brdo-0932803a2c0a61924209dfe277dec32bced63c0c.tar.gz brdo-0932803a2c0a61924209dfe277dec32bced63c0c.tar.bz2 |
Issue #1221276 by gumanist, fietserwin, Gábor Hojtsy, sun, kalman.hosszu: Fixed locale_get_plural() only works for a single language within a request and does not work for English.
Diffstat (limited to 'modules/locale')
-rw-r--r-- | modules/locale/locale.module | 43 | ||||
-rw-r--r-- | modules/locale/locale.test | 131 | ||||
-rw-r--r-- | modules/locale/tests/locale_test.module | 124 |
3 files changed, 287 insertions, 11 deletions
diff --git a/modules/locale/locale.module b/modules/locale/locale.module index d685eeabd..e0981b2fb 100644 --- a/modules/locale/locale.module +++ b/modules/locale/locale.module @@ -737,30 +737,51 @@ function locale_reset() { * @param $langcode * Optional language code to translate to a language other than * what is used to display the page. + * + * @return + * The numeric index of the plural variant to use for this $langcode and + * $count combination or -1 if the language was not found or does not have a + * plural formula. */ function locale_get_plural($count, $langcode = NULL) { global $language; - $locale_formula = &drupal_static(__FUNCTION__, array()); - $plurals = &drupal_static(__FUNCTION__ . ':plurals', array()); + + // Used to locally cache the plural formulas for all languages. + $plural_formulas = &drupal_static(__FUNCTION__, array()); + + // Used to store precomputed plural indexes corresponding to numbers + // individually for each language. + $plural_indexes = &drupal_static(__FUNCTION__ . ':plurals', array()); $langcode = $langcode ? $langcode : $language->language; - if (!isset($plurals[$langcode][$count])) { - if (empty($locale_formula)) { + if (!isset($plural_indexes[$langcode][$count])) { + // Retrieve and statically cache the plural formulas for all languages. + if (empty($plural_formulas)) { $language_list = language_list(); - $locale_formula[$langcode] = $language_list[$langcode]->formula; + foreach ($language_list as $langcode => $lang) { + $plural_formulas[$langcode] = $lang->formula; + } } - if ($locale_formula[$langcode]) { + // If there is a plural formula for the language, evaluate it for the given + // $count and statically cache the result for the combination of language + // and count, since the result will always be identical. + if (!empty($plural_formulas[$langcode])) { + // $n is used inside the expression in the eval(). $n = $count; - $plurals[$langcode][$count] = @eval('return intval(' . $locale_formula[$langcode] . ');'); - return $plurals[$langcode][$count]; + $plural_indexes[$langcode][$count] = @eval('return intval(' . $plural_formulas[$langcode] . ');'); + } + // In case there is no plural formula for English (no imported translation + // for English), use a default formula. + elseif ($langcode == 'en') { + $plural_indexes[$langcode][$count] = (int) ($count != 1); } + // Otherwise, return -1 (unknown). else { - $plurals[$langcode][$count] = -1; - return -1; + $plural_indexes[$langcode][$count] = -1; } } - return $plurals[$langcode][$count]; + return $plural_indexes[$langcode][$count]; } diff --git a/modules/locale/locale.test b/modules/locale/locale.test index c922c1df6..0a8ed42f7 100644 --- a/modules/locale/locale.test +++ b/modules/locale/locale.test @@ -694,6 +694,136 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase { } /** + * Tests plural index computation functionality. + */ +class LocalePluralFormatTest extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Plural formula evaluation', + 'description' => 'Tests plural formula evaluation for various languages.', + 'group' => 'Locale', + ); + } + + function setUp() { + parent::setUp('locale', 'locale_test'); + + $admin_user = $this->drupalCreateUser(array('administer languages', 'translate interface', 'access administration pages')); + $this->drupalLogin($admin_user); + + // Import some .po files with formulas to set up the environment. + // These will also add the languages to the system and enable them. + $this->importPoFile($this->getPoFileWithSimplePlural(), array( + 'langcode' => 'fr', + )); + $this->importPoFile($this->getPoFileWithComplexPlural(), array( + 'langcode' => 'hr', + )); + } + + /** + * Tests locale_get_plural() functionality. + */ + function testGetPluralFormat() { + $this->drupalGet('locale_test_plural_format_page'); + $tests = _locale_test_plural_format_tests(); + $result = array(); + foreach ($tests as $test) { + $this->assertPluralFormat($test['count'], $test['language'], $test['expected-result']); + } + } + + /** + * Helper assert to test locale_get_plural page. + * + * @param $count + * Number for testing. + * @param $lang + * Language for testing + * @param $expected_result + * Expected result. + * @param $message + */ + function assertPluralFormat($count, $lang, $expected_result) { + $message_param = array( + '@lang' => $lang, + '@count' => $count, + '@expected_result' => $expected_result, + ); + $message = t("Computed plural index for '@lang' with count @count is @expected_result.", $message_param); + + $message_param = array( + '@lang' => $lang, + '@expected_result' => $expected_result, + ); + $this->assertText(format_string('Language: @lang, locale_get_plural: @expected_result.', $message_param, $message)); + } + + /** + * Imports a standalone .po file in a given language. + * + * @param $contents + * Contents of the .po file to import. + * @param $options + * Additional options to pass to the translation import form. + */ + 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); + } + + /** + * Returns a .po file with a simple plural formula. + */ + function getPoFileWithSimplePlural() { + return <<< EOF +msgid "" +msgstr "" +"Project-Id-Version: Drupal 7\\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 "One sheep" +msgid_plural "@count sheep" +msgstr[0] "un mouton" +msgstr[1] "@count moutons" + +msgid "Monday" +msgstr "lundi" +EOF; + } + + /** + * Returns a .po file with a complex plural formula. + */ + function getPoFileWithComplexPlural() { + return <<< EOF +msgid "" +msgstr "" +"Project-Id-Version: Drupal 7\\n" +"MIME-Version: 1.0\\n" +"Content-Type: text/plain; charset=UTF-8\\n" +"Content-Transfer-Encoding: 8bit\\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\\n" + +msgid "1 hour" +msgid_plural "@count hours" +msgstr[0] "@count sat" +msgstr[1] "@count sata" +msgstr[2] "@count sati" + +msgid "Monday" +msgstr "Ponedjeljak" +EOF; + } +} + +/** * Functional tests for the import of translation files. */ class LocaleImportFunctionalTest extends DrupalWebTestCase { @@ -2835,3 +2965,4 @@ class LocaleLanguageNegotiationInfoFunctionalTest extends DrupalWebTestCase { } } } + diff --git a/modules/locale/tests/locale_test.module b/modules/locale/tests/locale_test.module index 2af50a69d..64f4aed57 100644 --- a/modules/locale/tests/locale_test.module +++ b/modules/locale/tests/locale_test.module @@ -55,6 +55,22 @@ function locale_test_language_types_info() { } /** + * Implements hook_menu(). + * + * @return array + */ +function locale_test_menu() { + $items = array(); + $items['locale_test_plural_format_page'] = array( + 'page callback' => 'locale_test_plural_format_page', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** * Implements hook_language_types_info_alter(). */ function locale_test_language_types_info_alter(array &$language_types) { @@ -116,3 +132,111 @@ function locale_test_store_language_negotiation() { function locale_test_language_provider($languages) { return 'it'; } + +/** + * Returns markup for locale_get_plural testing. + * + * @return array + */ +function locale_test_plural_format_page() { + $tests = _locale_test_plural_format_tests(); + $result = array(); + foreach ($tests as $test) { + $string_param = array( + '@lang' => $test['language'], + '@locale_get_plural' => locale_get_plural($test['count'], $test['language']) + ); + $result[] = array( + '#prefix' => '<br/>', + '#markup' => format_string('Language: @lang, locale_get_plural: @locale_get_plural.', $string_param), + ); + } + return $result; +} + +/** + * Helper function with list of test cases + * + * @return array + */ +function _locale_test_plural_format_tests() { + return array( + // Test data for English (no formula present). + array( + 'count' => 1, + 'language' => 'en', + 'expected-result' => 0, + ), + array( + 'count' => 0, + 'language' => 'en', + 'expected-result' => 1, + ), + array( + 'count' => 5, + 'language' => 'en', + 'expected-result' => 1, + ), + + // Test data for French (simpler formula). + array( + 'count' => 1, + 'language' => 'fr', + 'expected-result' => 0, + ), + array( + 'count' => 0, + 'language' => 'fr', + 'expected-result' => 1, + ), + array( + 'count' => 5, + 'language' => 'fr', + 'expected-result' => 1, + ), + + // Test data for Croatian (more complex formula). + array( + 'count' => 1, + 'language' => 'hr', + 'expected-result' => 0, + ), + array( + 'count' => 21, + 'language' => 'hr', + 'expected-result' => 0, + ), + array( + 'count' => 0, + 'language' => 'hr', + 'expected-result' => 2, + ), + array( + 'count' => 2, + 'language' => 'hr', + 'expected-result' => 1, + ), + array( + 'count' => 8, + 'language' => 'hr', + 'expected-result' => 2, + ), + + // Test data for Hungarian (nonexistent language). + array( + 'count' => 1, + 'language' => 'hu', + 'expected-result' => -1, + ), + array( + 'count' => 21, + 'language' => 'hu', + 'expected-result' => -1, + ), + array( + 'count' => 0, + 'language' => 'hu', + 'expected-result' => -1, + ), + ); +} |