Problem/Motivation

The registration field formatter label is not translatable.

User story:

As a visitor viewing a site in another language, I want to see the registration link text in my language, so that I know what to do to register.

Proposed resolution

Use the String translation module (i18n_strings, part of the Internationalization project (i18n)) to make the string translatable.

Do NOT use t() to translate variables (e.g.: t($text)), especially because $text is code entered by a user. Otherwise, this opens your site up to cross-site scripting and other security problems.

Remaining tasks

  1. Write a patch that doesn't use t().
  2. Review patch and RTBC
  3. Commit patch.

User interface changes

No changes to the registration module user interface. The label entered by the user becomes available in the String Translation interface, if the appropriate modules are enabled.

API changes

No changes to the registration module API. A new i18n_string group becomes available. Two new, internal functions become available to facilitate translation. Translations of the user-entered label are stored separately by the i18n_string module.

Original report by @zterry95

While trying to translate the formatter label of the register link. we can't get it works.
I have take some time to study this problem and I think it's a bug.

Here is the patch to fix this. Tested my my local and it works; the register label can be translated now.

attachment is the patch.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

zterry95’s picture

Status: Active » Needs review
mgifford’s picture

Simple enough patch. Applies nicely to git.

mparker17’s picture

Assigned: Unassigned » mparker17
Status: Needs review » Needs work

From the documentation for the t() function:

You should never use t() to translate variables, such as calling

t($text);

, [...]. It is especially important never to call

t($user_text);

, where $user_text is some text that a user entered - doing that can lead to cross-site scripting and other security problems.

So, I'm marking this patch as "Needs work".

However, I have to fix this for a client site right now, so I'm assigning it to myself.

mparker17’s picture

Assigned: mparker17 » Unassigned
Status: Needs work » Needs review
Issue tags: +Needs issue summary update
FileSize
5.66 KB

Drupal 7 core itself doesn't provide a way to translate arbitrary strings; but the Internationalization module (i18n) has a sub-module called String translation (i18n_strings) that makes it relatively simple to bolt arbitrary string translation on to an existing module without rewriting how the module works internally. It does this by providing a function called i18n_string(), which, depending on how it's called will either register the string or retrieve the translated version (it's important that the string be registered first, so it becomes available to translate).

Note that I didn't want to add a hard dependency on the i18n_string module, so, as suggested in the documentation on using the i18n API from other modules I wrapped calls to it's eponymous function in a function_exists() call, which I further wrapped in a "private", namespaced function so the code is more readable and so it acts the way the module did before if the i18n_string module isn't installed.

***

To use the i18n_string functionality, it's recommended you create a "i18n_string group" (namespace) for strings from your module, which you do by implementing hook_i18n_string_info().

Secondly, you need a way to generate a "key" when both saving and loading the user-entered string. In this case, I generated a key in the namespace "registration" (i.e.: the machine name of this module) that consisted of the entity type (e.g.: "node"), the bundle name (i.e.: content type; e.g. "campaign"), the view mode (e.g.: "full" for the full content view), the field name, and the machine name of the setting(s) we wanted to translate ("label"). However, since the view mode is not available at formatter-view-time, I stored a chunk of the key as a formatter setting (which I called i18n_string_key).

Finally, you need to register the new string when it's saved. In this case, it was rather difficult because registration_field_formatter_settings_form() only deals with a chunk of the Manage display form, and modifying the form is not allowed (because it's not passed-by-reference) so I couldn't add a submit handler. The solution was to add a '#process' to the form-chunk. However, it turns out that, when processing the form-chunk, $form_state['submitted'] acts exactly opposite to the way I expected (i.e.: it's equal to TRUE when loading the form-chunk and FALSE when saving the form-chunk). Checking that the form was being submitted before registering the string was necessary to avoid blowing away the string's translation when a user just wants to look at the string.

mparker17’s picture

Title: formatter label can't be translated » Registration link text (field formatter label) is not translatable
Issue summary: View changes
Issue tags: -Needs issue summary update
mparker17’s picture

Issue summary: View changes
mparker17’s picture

Issue summary: View changes
csc4’s picture

Bit unclear what's happening with this - it's a big issue on multilingual sites. According to @mgifford at https://www.drupal.org/node/2234915#comment-8755545 patch does the job so is there any reason it's not committed? Should we use it?

Should it perhaps be using hook_variable_info? That would mean we could translate via the variables module - cf r4032login.variable.inc

mgifford’s picture

@csc4 I just said it applied to Git.

@mparker17 has rolled up a new patch that is ready for review. It follows a better approach for string translation.

This just needs a review. Have you tested it out yet @csc4? Even on SimplyTest.me

csc4’s picture

I've tested https://www.drupal.org/files/issues/registration-2234915-4-translate_lin... and it's working for the node, but not working in panels is that because it's not using hook_variable_info?

idebr’s picture

While this solves the issue by the OP, its scope is limited to the registration link in the field configuration. How should this fit in an effort to make other parts of Registration translatable? For example, Profile2 has a submodule to implement i18n for its custom entities: http://cgit.drupalcode.org/profile2/tree/contrib/profile2_i18n.module

Jochen Wendebaum’s picture

It would be nice to get a final solution for this issue. I will not apply the first patch to get my site up, knowing that further updates of the module will brake it again. *sigh*

caxy4’s picture

Status: Needs review » Closed (won't fix)

I understand the user story and don't disagree with the need for translation in some cases – unfortunately we don't want to make the registration module dependent on i18n as it is a minority use case and getting site translation working robustly usually means a developer is involved that would be capable of applying this patch to suite his/her needs.

Closing as "Won't fix"

mparker17’s picture

Status: Closed (won't fix) » Needs review

This doesn't add a dependency on i18n: it uses a function from i18n_string if the module is enabled, but if the module is missing, it doesn't do anything. Please review the patch and Translating user-entered strings in D7 for more details.

caxy4’s picture

Thanks for the follow up @mparker17 – I've reviewed and incorporated the patch (9b3a21c).

Let me know if it meets your needs before I close the ticket.

  • caxy4 committed 9b3a21c on 7.x-1.x authored by mparker17
    Issue #2234915 by mparker17, zterry95: Registration link text (field...
mparker17’s picture

Status: Needs review » Fixed

Looks good to me, thanks!

caxy4’s picture

Status: Fixed » Closed (fixed)

Good to hear!
Closing as fixed.