Problem/Motivation
AccountForm::form() uses the following code.
$form_state->set('user', $account);
// The user may only change their own password without their current
// password if they logged in via a one-time login link.
if (!$form_state->get('user_pass_reset')) {
$form['account']['current_pass']['#description'] = $this->t('Required if you want to change the %mail or %pass below. <a href=":request_new_url" title="Send password reset instructions via email.">Reset your password</a>.', [
'%mail' => $form['account']['mail']['#title'],
'%pass' => $this->t('Password'),
':request_new_url' => Url::fromRoute('user.pass')->toString(),
]);
}
Required if you want to change the %mail or %pass below. is problematic to translate in languages that use more than a definite article because, without knowing which word follows the article, it is not possible to decide which article must be used.
For example, in Italian the definite articles are il, lo, gli, i, la, and le depending on the word to which the article is applied. Without knowing what word follows the article, which in this case is replaced by %mail, I cannot know which article to use.
Furthermore, in Italian I could translate email with indirizzo email, indirizzo di posta elettronica, posta elettronica, or simply use email or mail as in English. With the article, those translations would become l'indirizzo email, l'indirizzo di posta elettronica, la posta elettronica, l'email, and la mail. (In l'email, l' is an elision for la, but differently from la, l' is written without spaces before the following word.)
In Norwegian, the definite article is an enclitic which is attached to the word. For example, the translation of the house is husen, while the translation of the car is bilen.
Even supposing I would know which definite article is used, I cannot attach it to the placeholder, which would change to a different placeholder (%mailen instead of %mail).
In both the cases, the sentence can be translated if what follows the definite article is not a placeholder.
The placeholder has been used to avoid to translate again the form element title, but using a placeholder after a definite article causes more translation issues.
Proposed resolution
In 'Required if you want to change the %mail or %pass below. <a href=":request_new_url" title="Send password reset instructions via email.">Reset your password</a>.', do not use the %mail nor the %pass placeholders.
Instead, a string like 'Required if you want to change the <em>Email address</em> or the <em>Password</em> field below. <a href=":request_new_url" title="Send password reset instructions via email.">Reset your password</a>.' should be used, where
Email address and Password are the title of the form elements which requires the current password to be changed.
Original report for Drupal 7
The string
Enter your current password to change the %mail or %pass. !request_new.
on user/n/edit is very hard to translate correctly because of the placeholders %mail and %pass. You really need to control the whole sentence to translate it properly. A couple of examples: In Norwegian, you don't use a separate word like "the" to get the definite form, you add an ending to the word instead. While in German, there are three different versions of "the" depending on the word it's pointing to.
There doesn't seem to be a good reason for these placeholders. The string should be changed to:
Enter your current password to change the <em>e-mail address</em> or <em>password</em>. !request_new.
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | 973772.drupal.user-password-form-translatable.patch | 1.24 KB | joachim |
Issue fork drupal-973772
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 973772-hard-to-translate
changes, plain diff MR !9061
Comments
Comment #1
joachim commentedConfirming.
The logic in this form is pretty crusty and hard to follow:
$protected_values appears to be some magic needed for the form to work securely, but WTF is with reaching back into it to get strings for a title?
Could do with input from someone who understands how this works before I wade in and make a patch.
Comment #2
joachim commentedAlso, how are you finding this one:
form_set_error('current_pass', t("Your current password is missing or incorrect; it's required to change the %name.", array('%name' => $name)));
It's probably not clear from what you get as a translator that %name can be either 'password' or 'e-mail address' as above.
Comment #3
joachim commentedHere's a patch for the original bit.
I suspect the 'Your current password is missing or incorrect....' bit will need some work too as it has the same problem; might have to split it into two separate strings and forego the clever reuse, as by the sound of it it will fail on languages that need to alter nouns.
I think a follow-on issue is needed to clean up the confusing logic and badly-worded comments, as it took me over half an hour to understand what this form is doing.
Comment #4
EvanDonovan commented@joachim: Why are the mail and pass variables still in the t() function if they are not being used? Also, neither should be capitalized.
Once that is fixed, it should be good.
Comment #5
joachim commentedDo you mean this line? This is kinda crack, but it's used by the validation further down. I agree it needs cleaning up, but it's out of the scope of this patch.
Powered by Dreditor.
Comment #6
EvanDonovan commented@joachim: No, I mean
+ $current_pass_description = t('Enter your current password to change the <em>E-mail address</em> or <em>Password</em>. !request_new.', array('%mail' => $protected_values['mail'], '%pass' => $protected_values['pass'], '!request_new' => $request_new));The first two parameters in the t() function aren't being used anymore, so I don't think they need to be included in it (I know that they need to be set earlier). And the words with which they have been replaced need to be lowercase.
Comment #7
drupal_was_my_past commentedRe-rolling patch from #3 with EvanDonovan's suggestions. Also pulled $request_new out of t(). Moving this to 8.x because of string freeze.
Comment #8
drupal_was_my_past commentedRe-rolled after #22336: Move all core Drupal files under a /core folder to improve usability and upgrades core directory structure for Drupal 8 was changed.
Comment #10
drupal_was_my_past commentedRe-rolling #8.
Comment #11
tstoecklerYou shouldn't pull $request_new out of t(). Other languages might want to put that bit at a different place than at the end (RTL languages, for instance).
Comment #12
tstoecklerSorry, didn't want to change version.
Comment #13
drupal_was_my_past commented@tstoeckler But $request_new has already been run through t(). Doesn't running it through twice cause problems?
Comment #14
tstoecklerAs it currently stands $request_new is added to the string as a !placeholder, which aren't translated in themselves. Another form, which I would personally like even better, is to inline the link in the t() such as:
Required if you want to change the <em>e-mail address</em> or <em>password</em> below. <a href="@url" title="Request new password via e-mail.">Request new password</a>That would be a change from the current method, though.
Comment #15
drupal_was_my_past commentedBut $request_new is uses l() and t() itself, so it seems like it would run the "Request new password." string through t() first in l() and then again in another t().
Comment #16
tstoecklerNo it doesn't! t() doesn't translate %arguments, @arguments, or !arguments. That would make no sense. :)
Comment #17
drupal_was_my_past commentedOH! I see! I'm sorry I was being so dense. I'll re-roll it with the !placeholder included in the t().
Comment #18
drupal_was_my_past commentedOn second thought, I'll use your suggestion in #14. Patch forthcoming.
Comment #19
drupal_was_my_past commentedRe-rolled patch with suggestion from #14.
Comment #20
drupal_was_my_past commentedForgot to change status to needs review.
Comment #21
tstoecklerThanks for sticking with this. I'm sorry that I have to set this to "needs work" once more.
You should call url() on 'user/password'. l() does that automatically, that's why it wasn't needed before.
8 days to next Drupal core point release.
Comment #22
drupal_was_my_past commented@tstoeckler no problem. Thanks for the fix. I was struggling with that part and gave it my best shot. Patch re-rolled here.
Comment #23
tstoecklerI was about to mark this RTBC, but upon looking at it one time I stumbled on the '< em >' part. Before we were using the titles of the form elements, i.e. 'Password' and 'E-mail address' in the < em >. The patch removes that capitalization, but leaves the < em > which now doesn't really reference those form elements anymore. So should we remove the < em > as well, or re-capitalize the two (or neither)? I'm leaning towards the former, but not sure.
Also removing "string freeze" tag, as this will not go into D7 anymore.
Comment #24
kscheirer#22: user-change-password-973772-22.patch queued for re-testing.
Comment #26
mgiffordComment #35
quietone commentedI tested this on 9.2.x and the string
Enter your current password to change the %mail or %pass.does not exist in the code base nor in 8.9.x. It was replaced withYour current password is missing or incorrect; it's required to change the %name.in #2418119: REST user updates bypass tightened user account change validation in March 2015. The new string is easier to translate (looking at the Italian translation right now).Since the string still exists in D7 moving to the Drupal 7 issue queue.
Comment #36
avpadernoActually, Your current password is missing or incorrect; it's required to change the %name. is not easier to translate, not even in Italian.
In Italian, the translation of Your current password is missing or incorrect; it's required to change the email. is La tua password corrente è mancante o errata; è necessaria per modificare l'email. The translation of Your current password is missing or incorrect; it's required to change the password. is La tua password corrente è mancante o errata; è necessaria per modificare la password.
In Russian, the translation for Your current password is missing or incorrect; it's required to change the %name. Your current password is missing or incorrect; it's required to change the email. Your current password is missing or incorrect; it's required to change the password. are the following.
Also in this case, the sentence changes basing on what replaces %name.
Comment #38
quietone commentedThere is some confusion here. I was referring to the string in the issue summary. The string in the issue summary is "Enter your current password to change the %mail or %pass. !request_new." That string was changed in core 2011, #1326172: Improve wording of the "Current password" field description on the user edit form, to "Required if you want to change the %mail or %pass below". That string is still in core.
The string in #36, is different from those two. The string in #36 added in 2010 in [#8629]. So, I think that should be a separate issue.
Comment #39
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue.
While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)
Comment #40
avpadernoMy comment was a reply to comment #35, which says:
I did not check which string was actually used, but that comment said the string used in Drupal 7 was replaced from
Your current password is missing or incorrect; it's required to change the %name., which is said to be easier to translate.Comment #41
avpadernoEven Required if you want to change the %mail or %pass below has the same issue the original string has: Other languages could have more than a definite article, or could use no definite article at all.
In Italian, the definite articles are il, lo, la, gli, i, le, not considering that it is l'email, not la email, but it is la mail. Without knowing which word is used, after the article, I can just guess basing on the placeholder, with the consequence that l'mail or la email could appear, depending on my guess and what value is used for %mail.
Comment #42
avpadernoIn Norwegian seems to be even more difficult, as the translation of la signora seems to be damen, while the translation of il bambino seems to be barnet. In both the cases, the bold part in the word is the article. (The translation of signora would be dam.)
(Technically, the definite article in Norwegian is an enclitic, contrary to Italian and English where it is a proclitic.)
Comment #43
avpadernoComment #44
quietone commentedSo, I came to two different conclusions based on my git research. That doesn't help this at all!
I have updated the issue summary
@avpaderno, do you have a suggestions to fix this?
Comment #45
avpadernoComment #46
avpadernoThe solution is simple: Do not use placeholders after an article.
Comment #47
avpaderno(I forgot the link to the documentation page.)
Comment #48
avpadernoThe only time the %mail is used in a translatable string is in the core/modules/user/src/AccountForm.php file.
I would leave other cases of placeholder after an article to other issues.
Comment #50
avpadernoComment #51
smustgrave commentedCould the issue summary be updated to the standard template please.
Comment #52
avpadernoI apologize: I was not able to retrieve this issue.
Comment #53
smustgrave commentedMuch appreciated @avpaderno believe the change is good.
Comment #56
catchCommitted/pushed to 11.x and cherry-picked to 10.4.x, thanks!