A) Because Drupal.t() loops through the placeholders in the order they are defined, placeholders that start with identical strings, for example "!price" and "!price_formatted", can cause problems.

Example

var params = {
  "!foo": "foo",
  "!bar": "bar",
  "!foobar": "banana"
}
alert(Drupal.t('!foobar', params));

the expected output is 'banana', the actual output is 'foobar' (the value of !foo + the remaining literal 'bar').

Solution

One solution could be sorting the args by descending key first, making the longer strings occur before their shorter versions so they're replaced first.

B) By default, javascript's string.replace only replaces the first occurrence of a string.

Example

var params = {
  "!foo": "foo",
  "!bar": "bar",
  "!foobar": "banana"
}
alert(Drupal.t('!foobar !foobar !foobar', params));

Expected result: "banana banana banana"
Actual result: "foobar banana !foobar"

edit: changed an error in the second example.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

plach’s picture

Component: language system » locale.module
Issue tags: +Needs backport to D7

UI translation issues belong to the Locale queue. I guess this needs backport to D7.

Anyway, the proposed solution looks sensible to me at a first sight, and it's consistent with what t() does: it uses strtr() which gives precedence to the longest keys.

mr.baileys’s picture

Updated the original bug report with an additional Drupal.t() string replacement issue.

mr.baileys’s picture

Attached patch addresses the first issue.

mr.baileys’s picture

Status: Active » Needs review
FileSize
2.03 KB

And here's an attempt to address both issues.

mr.baileys’s picture

And once more, this time without unrelated cruft in the patch. Sorry.

mr.baileys’s picture

Issue summary: View changes

Added a second, related, string-replacement issue.

mr.baileys’s picture

Issue summary: View changes

Updated issue summary.

mr.baileys’s picture

Re-rolled.

dags’s picture

nod_’s picture

tag

Can you please add a test scenario to this page http://drupal.org/node/1777342 so that we can make sure we test it and possibly add tests to testswarm to make sure we fix it and keep it fixed? :)

mr.baileys’s picture

@_nod: the only way I can think of to test this is to paste the examples in the original post in a console and run them. Is it ok to add those instructions to http://drupal.org/node/1777342? Those tests seem to be more of the click-and-verify-variety :)

nod_’s picture

Yep, you can add them, they are the easy kind of tests to port to testswarm, they won't be in there for long :)

mr.baileys’s picture

Cool, added a test-case at the bottom http://drupal.org/node/1777342

droplet’s picture

Status: Needs review » Needs work

Still doesn't looks correctly.

PHP:

$params = array(
  "!foo" => "1",
  "!bar" => "10",
  "!foobar" => "!foo"
);

var_dump(t('!foobar !foobar !foobar', $params));

// string(14) "!foo !foo !foo"

JS:

var params = {
  "!foo": "1",
  "!bar": "10",
  "!foobar": "!foo"
}
console.log(Drupal.t('!foobar !foobar !foobar', params));

// 1 1 1

see:
http://phpjs.org/functions/strtr:556
http://git.php.net/?p=php-src.git;a=blob;f=ext/standard/string.c#l2777

droplet’s picture

Issue summary: View changes

Updated issue summary.

droplet’s picture