diff --git a/core/misc/drupal.js b/core/misc/drupal.js index e994ec6..760b3c8 100644 --- a/core/misc/drupal.js +++ b/core/misc/drupal.js @@ -223,10 +223,61 @@ Drupal.formatString = function(str, args) { args[key] = Drupal.theme('placeholder', args[key]); break; } - str = str.replace(key, args[key]); } } - return str; + + return Drupal.stringReplace(str, args, null); +}; + +/** + * Replace substring. + * + * The longest keys will be tried first. + * Once a substring has been replaced, its new value will not be searched again. + * + * @param str + * A string with placeholders. + * @param args + * Key-value pairs. + * @param keys + * Array of keys from the "args". + * Internal use only. + * + * @return string + * Returns the replaced string. + */ +Drupal.stringReplace = function (str, args, keys) { + if (str.length === 0) { + return str; + } + + // If the array of keys is not passed then collect the keys from the args. + if (!Array.isArray(keys)) { + keys = []; + for (var k in args) { + if (args.hasOwnProperty(k)) { + keys.push(k); + } + } + + // Order the keys by the character length. The shortest one is the first. + keys.sort(function (a, b) { return a.length - b.length; }); + } + + if (keys.length === 0) { + return str; + } + + var key = keys.pop(); + var fragments = str.split(key); + + if (keys.length) { + for (var i = 0; i < fragments.length; i++) { + fragments[i] = Drupal.stringReplace(fragments[i], args, keys); + } + } + + return fragments.join(args[key]); }; /** @@ -302,20 +353,16 @@ Drupal.url = function (path) { Drupal.formatPlural = function (count, singular, plural, args, options) { args = args || {}; args['@count'] = count; + + var pluralDelimiter = Drupal.locale.pluralDelimiter; + // Determine the index of the plural form. var index = Drupal.locale.pluralFormula ? Drupal.locale.pluralFormula(args['@count']) : ((args['@count'] === 1) ? 0 : 1); + var translations = Drupal + .t(singular + pluralDelimiter + plural, args, options) + .split(pluralDelimiter); - if (index === 0) { - return Drupal.t(singular, args, options); - } - else if (index === 1) { - return Drupal.t(plural, args, options); - } - else { - args['@count[' + index + ']'] = args['@count']; - delete args['@count']; - return Drupal.t(plural.replace('@count', '@count[' + index + ']'), args, options); - } + return translations[index]; }; /** diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index a23ad91..c28cafc 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -621,7 +621,7 @@ function locale_js_translate(array $files = array()) { } // Add the translation JavaScript file to the page. - $locale_javascripts = \Drupal::state()->get('translation.javascript') ?: array(); + $locale_javascripts = \Drupal::state()->get('locale.translation.javascript') ?: array(); $translation_file = NULL; if (!empty($files) && !empty($locale_javascripts[$language_interface->id])) { // Add the translation JavaScript file to the page. @@ -1145,6 +1145,18 @@ function _locale_refresh_configuration(array $langcodes, array $lids) { } /** + * Remove the quotes and string concatenations from the string. + * + * @param string $string + * + * @return string + * Remove leading and trailing quotes. + */ +function _locale_strip_quotes($string) { + return implode('', preg_split('~(? $string) { $matches[] = array( - 'string' => $string, + 'source' => _locale_strip_quotes($string), 'context' => $t_matches[2][$key], ); } @@ -1226,35 +1238,20 @@ function _locale_parse_js_file($filepath) { // Add string from Drupal.formatPlural(). foreach ($plural_matches[1] as $key => $string) { $matches[] = array( - 'string' => $string, + 'source' => _locale_strip_quotes($string) . LOCALE_PLURAL_DELIMITER . _locale_strip_quotes($plural_matches[2][$key]), 'context' => $plural_matches[3][$key], ); - - // If there is also a plural version of this string, add it to the strings array. - if (isset($plural_matches[2][$key])) { - $matches[] = array( - 'string' => $plural_matches[2][$key], - 'context' => $plural_matches[3][$key], - ); - } } // Loop through all matches and process them. foreach ($matches as $match) { - - // Remove the quotes and string concatenations from the string and context. - $string = implode('', preg_split('~(?findString(array('source' => $string, 'context' => $context)); + $source = \Drupal::service('locale.storage')->findString($match); if (!$source) { // We don't have the source string yet, thus we insert it into the database. - $source = \Drupal::service('locale.storage')->createString(array( - 'source' => $string, - 'context' => $context, - )); + $source = \Drupal::service('locale.storage')->createString($match); } + // Besides adding the location this will tag it for current version. $source->addLocation('javascript', $filepath); $source->save(); @@ -1299,6 +1296,9 @@ function _locale_invalidate_js($langcode = NULL) { * * @param $langcode * The language, the translation file should be (re)created for. + * + * @return bool + * Returns TRUE if translation file is exists FALSE otherwise. */ function _locale_rebuild_js($langcode = NULL) { $config = \Drupal::config('locale.settings'); @@ -1327,14 +1327,18 @@ function _locale_rebuild_js($langcode = NULL) { $data_hash = NULL; $data = $status = ''; if (!empty($translations)) { + $data = array( + 'pluralDelimiter: ' . Drupal\Component\Utility\Json::encode(LOCALE_PLURAL_DELIMITER), + ); - $data = "Drupal.locale = { "; $locale_plurals = \Drupal::state()->get('locale.translation.plurals') ?: array(); - if (!empty($locale_plurals[$language->id])) { - $data .= "'pluralFormula': function (\$n) { return Number({$locale_plurals[$language->id]['formula']}); }, "; + if (!empty($locale_plurals[$language->id]['formula'])) { + $data[] = "pluralFormula: function (\$n) { return Number({$locale_plurals[$language->id]['formula']}); }"; } - $data .= "'strings': " . drupal_json_encode($translations) . " };"; + $data[] = 'strings: ' . Drupal\Component\Utility\Json::encode($translations); + + $data = 'Drupal.locale = { ' . implode(', ', $data) . ' };'; $data_hash = Crypt::hashBase64($data); }