Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
javascript
Priority:
Major
Category:
Bug report
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
26 Jan 2014 at 20:48 UTC
Updated:
15 Dec 2018 at 19:32 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
sweetchuckComment #2
sweetchuckComment #3
sweetchuckComment #4
nod_Drupal.stringReplace = function (str, args, keys) {instead ofDrupal.stringReplace = function(str, args, keys) {(the space before the function opening parenthesis).!Array.isArray(keys)instead ofkeys instanceof Array !== trueinstead of
Drupal.pluralDelimiter,Drupal.PLURAL_DELIMITERto make sure people don't mess around with it. Or better yet, add the value to drupalSettings from the PHP so that it can use the PHP constant directly.Drupal.locale.pluralFormulais used a bunch of times inDrupal.formatPlural, could you put that in a variable?Haven't looked into the logic too much, to late for that on my end :)
Comment #5
sweetchuckThe "pluralFormula" is not parsed.
Cannot use 'in' operator to search for '1' in (($n==1)?(0):((((($n%10)>=2)&&(($n%10)<=4))&&((($n%100)<10)||(($n%100)>=20)))?(1):2))
Comment #6
nod_What I meant was:
Comment #7
nod_Umm looks like this patch needs the other one to work properly too. Sounds like you'd want to put the changes here in the other patch no? and solve everything in one patch?
Comment #8
sweetchuckAt the beginning I started to work on the "eval" issue, but I ran into more and more problems.
I fixed them together with Goba, but a I made some mistake when I split the modifications to two separate patch.
Comment #9
sweetchuckWe use the Drupal.pluralDelimiter only together with Drupal.locale.pluralFormula, which is come from the <langcode>_<hash>.js file. So we can also put the pluralDelimiter character into the same file. Like you suggest.
Comment #10
sweetchuckStill does not works, but a little bit better.
(I go to sleep)
Comment #13
gábor hojtsy@nod: Yeah there are *numerous* problems with JS translation in Drupal core right now, the primary thing is it does not work at all since the JS translation file is *never* added to the page. That is kind of a bid deal :D So lumping this in with removing eval() may be a mistake. Therefore the separate issue.
The fix here should:
1. Add the JS to the page properly. That is a one line fix, the state name is wrong :)
2. Parse the JS file properly for singular/plural string pairs, and save them as one string like the .po parser / format_plural backend.
3. Update the logic in Drupal.formatPlural() to use the single concatenated string lookup to find translations and split for the right index.
This patch is not meant to change looking up the index. It fixes all bugs that exist in Drupal core *already* so the eval() removal issue can work off of a working state and get to a different working state instead of starting with a totally bugos state :)
Updated issue summary with further details.
Comment #14
gábor hojtsyRetitling for the scope too :)
Comment #15
gábor hojtsyComment #16
webchickNot being able to translate something at all sounds critical.
Comment #17
sweetchuckThe Drupal.formatPlural() works on the client side.
Now I am starting to test it with missing translations. (with partially translated strings)
Comment #18
nod_Nothing to complain about on the JS side :) Thanks!
Comment #19
sweetchuckThanks :-)
But there are still several problems.
I use the Polish languge to testing, because it have 7 different plural formula.
The problem is that if the translation is missing then
\Drupal::translation()->formatPlural()returns an empty string instead of the original English string.The JS
Drupal.formatPlural()works on the same wrong way. :-(Example:
- If the singular is translated and one of the plural version is translated then formatPlural() returns an empty string when @count points to an untranslated index. (fail)
- If the singular is not translated, but one of the plural version is translated then formatPlural() returns an empty string when @count points to an untranslated index or @count = 1. (fail)
- Only works well if everything is translated or everything is not translated.
Comment #20
wim leersTypehints missing.
Incomplete parameter docs. Silly, I know, but it's the standard…
Two invocations on the same class; let's
usethat class so that you don't need to specify the fully qualified class name twice.Comment #21
gábor hojtsy@Sweetchuck: is it realistic to support partial translations? Not sure how we could avoid that though. Eg. we should validate the submission of plural translations in form submission / .po import? Anyway, sounds like that is not part of this issue anymore (and not JS dependent), so should be its own issue :)
Comment #22
sweetchuckI am in a trouble with the
\Drupal\Core\StringTranslation\TranslationManager::formatPlural()The problem is that any index can contain an empty string in the $translated_array.
And if so - have to use the original $singular or $plural strings?
In other words:
If $translated_array[$index] is empty and the $options['langcode'] is not 'en' then call the $this->translate() again with different arguments?
Comment #23
sweetchuck@Gábor Hojtsy - Yes. You can submit the "User interface translation" form even if one of the translation is missing (singular or any plural).
Comment #24
gábor hojtsy@Sweetchuck: Once again I don't think this should be in the scope for this patch. Don't consider that scenario in the test. This is not related to the JS problems.
Comment #25
sweetchuckComment #26
sweetchuckWhen I run the tests of the locale module I get the same result as the patch in #3 comment.
JAVASCRIPT TRANSLATION
Tests parsing js files for translatable strings
21 passes, 45 fails, and 0 exceptions
Comment #27
nod_This is a reroll because the indentation standard changed for JavaScript files. No need for commit credit because of this reroll.
Comment #28
gábor hojtsyLet's get testbot results :)
Comment #30
gábor hojtsyPart of the fails seems to be due to the singular/plural strings asserted as separate source strings found. That is obviously not good anymore, should be fixed. There are some other (string context) related fails, which I'm a bit puzzled about. We are not supposed to modify the preg pattern to find strings here :)
Comment #31
sweetchuckComment #32
sweetchuckI think the D7 is also affected by the problem of the JS String.replace(), that is only the first occurrence get replaced.
Drupal.t("Lorem ipsum @foo sid amet @foo", { "@foo": "bar" }, {});Comment #33
sweetchuckThere are no test cases for the string concatenations where the quotation marks are mixed. Like this:
Drupal.t("Double" + 'simple')Comment #34
gábor hojtsyGreat job, mostly English languages fixes needed.
I would refrain from doing any more expansions of scope of this patch. IMHO its totally fine to fix the following and get this in. Its a critical bugfix after all, we don't need to fix all kinds of side things while we are at it :)
Don't do the newline after the first sentence, just continue with the second. Also the second line was longer than 80 chars, but this will resolve itself with the above tip :)
Merge onto 1 line.
Maybe document right above the pop() that
// Take next longest one from the end.
or something along those lines. The other comment makes it look like the short ones will be processed first, while that is not true :)
Removes
optionally concatenated, no?
String with leading and trailing quotes removed.
Nice simplification :)
TRUE if translation file exists, FALSE otherwise.
Would it make sense to use the Json library to generate the whole file (from an array) instead of doing parts of it with Json and parts of it manually?
Comment #35
sweetchuck@Gábor Hojtsy "... Would it make sense to use the Json library to generate the whole file (from an array) instead of doing parts of it with Json and parts of it manually? ..."
The "pluralFormula" is a function, so we can't use the json_encode() directly on the $data. The "eval" patch will optimize this.
Comment #36
gábor hojtsy@Sweetchuck: that makes sense :) Looking forward to the updates for the rest of the points.
Comment #37
sweetchuckComment #38
sweetchuckComment #39
gábor hojtsyThanks for fixing those. Fixes look good, now JS translations work again :)
Comment #40
catchCommitted/pushed to 8.x, thanks!
Comment #41
gábor hojtsyWoot, thanks!
Comment #42
sweetchuck@nod_ In the comment #4 you suggest :
"I'd be tempted to call Drupal.pluralDelimiter, Drupal.PLURAL_DELIMITER to make sure people don't mess around with it. Or better yet, add the value to drupalSettings from the PHP so that it can use the PHP constant directly."
The problem is that we need the LOCAL_PLURAL_DELIMITER in order to Drupal.t() and Drupal.formatPlural() to works well even if the current language is English, but the
files/languages/<lang_code>_<hash>.jsfile is only generated for the non-english languages.Can we add the delimiter charachter to the base settings?
Comment #43
nod_I understood wrong how the whole thing was working.
Can you add the delimiter toDrupal.local.localPluralDelimiterwhen the file gets generated? Would that work?Ok too dirstracted now, I'll have a look later.
Comment #44
gábor hojtsy@Sweetchuck: IMHO add it to the base settings or just hardcode the same value in drupal.js as well. I don't think its a big issue to have the same char defined at two places, the logic for the plurals, etc. is redefined in PHP and JS anyway.
Comment #45
andrejsmuzikovs commentedI believe that Drupal.stringReplace, which was commited in, doesn't properly replace all the placeholders. Noticed this when "edit" module wasn't loading WYSIWYG by clicking quick-edit. Can quickly reproduce this by running
Drupal.stringReplace("/x/!aa/!b", {"!aa":1, "!b":2}, null);.Expected result: "/x/1/2"
Actual result: "/x/1/!b"
I wasn't sure if I should open a new issue for this, it seems to be related to this one. Added a patch that is running OK locally.
/Andrejs
Comment #46
sweetchuckI can confirm the bug (described in #45) is exists and the patch is solve the problem.
@Andrejs I am not a JS expert, so can you explain me why need to clone the keys array, please?
Comment #47
catch@ andrejsmuzikovs - please open a new issue for that patch.
Comment #48
andrejsmuzikovs commented@catch Here it is https://drupal.org/node/2192809
I also explained it a bit more there.
/Andrejs
Comment #50
droplet commentedComment #51
sweetchuckDrupal.formatString() and Drupal.stringReplace() ported. (technically copied)
Comment #52
sweetchuckThe other issue was created on " July 27, 2011". Why that is marked as duplicated?
Comment #53
droplet commented@Sweetchuck,
That issue reported same bugs.
The only stuff I've seen that we can't use ES5 Array.isArray() in D7 and below. $.isArray() will does the job :)
Thanks!!
Comment #54
sweetchuckPatch for D7 with
if (!$.isArray(keys)) {Comment #55
droplet commentedComment #57
sweetchuckNow I am working on the D6 backport patch and the jQuery version is too old. There is no $.isArray()
Can I use
if (!(keys instanceof Array)) {instead?http://stackoverflow.com/questions/767486/how-do-you-check-if-a-variable...
There is another suggestion
toString.call(obj) === "[object Array]"Comment #58
droplet commentedinstanceof may failed at some case.
The another suggestion used in jQuery now.
Comment #59
sweetchuckBackport to D6
Comment #61
droplet commentedBack to RTBC, Patch #54 for D7.
Comment #62
David_Rothstein commentedHas there been any manual testing of this patch (cross-browser, etc)? The code looks good, but we need to be pretty careful with these kind of JavaScript patches that change fundamental parts of the code...
Also, is it correct that the issue title here is invalid for Drupal 7; for Drupal 7 we just are fixing #1230986: Drupal.t() placeholder replacement is wonky. and that's it?
Comment #63
mgiffordWhat's the best way to test this? With "JS translation files are never added to Drupal pages => strings in JS are never translated." it should be everywhere, right?
The summary states "The #1273968: remove eval from locale.module issue is cannot be solved without this fix.", but that's obviously not the case as it's been fixed.
Note, last patch still applies nicely.
Comment #64
gábor hojtsy@mgifford: I don't think the D8 title and the D8 dependencies of this issue apply to it now that it is on Drupal 7.
Comment #65
droplet commented@mgifford,
on D7 patch, it only need to fix the problem of #1230986: Drupal.t() placeholder replacement is wonky.. Copy the code on the summary into the browsers console. If it giving expected results, then it worked.
** as requests #62, mainly i think we have to test it on IE6,7,8. other browsers i did some tests already. (if it does not working, we should go back to D8 first)
Thanks.
Comment #66
mgiffordWhat happened to
if (args) {in Drupal.formatString? Patch no longer applies.Comment #68
droplet commented#54 still applies
Comment #69
mgiffordarg - I was looking at the D6 version in #59. Sorry.
Comment #70
xjmComment #71
sweetchuckThe patch #54 is still applicable to the latest 7.x and the patch #59 is still applicable to the latest 6.x
The original issue for 8.x was critical because the client side translation was not worked at all.
In D7 and D6 you can reproduce the bug only if you are using the same place holder twice or more in a string.
I think this bug is not critical any more.
Without the patch the code above output:
bar @fooinstead ofbar bar.My test code is:
Comment #73
David_Rothstein commentedI marked #2508812: t() function not working the same way in PHP and JS as duplicate which suggests a simpler fix (although I think it doesn't necessarily solve all the cases this patch does, i.e. everything mentioned in #1230986: Drupal.t() placeholder replacement is wonky.).
Also giving this a better title for the backport.
Comment #74
David_Rothstein commentedComment #79
joseph.olstadPasses manual testing in these browsers:
Test javascript code
before patch:

with patch 54 (79 is same as 54, just added 79 to allow testbot to run):

Comment #80
joseph.olstadComment #81
stefan.r commentedComment #83
David_Rothstein commentedThis looks very good. I did some additional testing (including some of the scenarios from #1230986: Drupal.t() placeholder replacement is wonky.) and everything seems to work. I am adding issue credit for mr.baileys (who worked on that issue) also.
Committed to 7.x - thanks!
Comment #86
sri@re commentedAlready in latest version of drupal 7 only , but drupal.t placeholder value is not shown in translate interface. please clarify.
Comment #87
electrokate commented@sri@re Did you find anything else on this? I am having the same problem with placeholders in multiple places in Drupal 8.