The current Field API code contains t($instance['label']); t($instance['description']);, directly inherited from CCK. Yuck, of course, but this was recommended by i18n guys way back then.

neochief and markus_petrux figured a cleaner way to let a 3rd party i18n_* module handle those translations, which was recently committed to CCK D6 (-dev): #531662: Internationalization support

I think we should follow a similar approach in D7, and remove those insulting t() calls (CCK D6 will keep them to ensure compatibility with already deployed sites).

Not on my personal priority list, though, so any takers welcome :-)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

yched’s picture

Status: Active » Needs review
FileSize
1.85 KB

Attached patch is a direct port of the approach taken in CCK D6.

Adds a new hook_field_strings_alter() hook, which gets an array containing the field label and description.
The hook is called on each page that requests field info (let's say most pages), the altered strings do not enter the persistent 'field info' cache, only the static cache.

Taking a step back, I'm not sure this is the right approach, though:
- this needs extra care (not done in the attached patch) to ensure that field_ui lets you edit the original (english) strings, not the strings translated in the current UI language. The $instance array that gets saved must contain the untranslated strings, or the whole thing breaks.
- other properties like field settings, instance settings, widget settings or formatter settings can be user-facing strings that might want to be translatable too. This kind of calls for $field- and $instance-level alter hooks, which we tried to avoid so far. See http://drupal.org/node/493094#comment-2038902 for a few concerns around this area; bottomline is: _alter hook on stuff that can be edited and saved through the UI is tricky, and AFAIK drupal core doesn't do this.

This whole topic looks quite similar to #357529: Implement translation of customized 'translatable' views properties, but I'm not sure what's the approach taken over there.
Also note that I won't be able to work on this myself for the next 4 weeks.

Marking 'needs review' to get feedback, but the patch shouldn't be committed as is.

yched’s picture

nedjo’s picture

This looks like a good start of a generalized approach to non-field string translation in core, which would be, don't handle it in core (at least for D7), but use drupal_alter() to enable a contrib solution.

This indeed relates to #357529: Implement translation of customized 'translatable' views properties in that that patch could do the same. That is, remove from that patch everything to do with a handler and instead merely call drupal_alter() as needed. The handler could then be handled in contrib in a way that applied not just to views or fields but to any non-field string.

If we take such an approach, the drupal_alter() call should start with something like this for all translatable strings:

drupal_alter('strings', $strings, $type);

where $type is the type of object the translation is needed for. E.g. in this case:

drupal_alter('strings', $strings, 'field', $instance['field_name'], $instance['bundle']);

Translation could be only one of the possible hook_drupal_alter_strings() purposes.

plach’s picture

Great idea, although I am wondering about performance implications. We might make the call in a wrapper function which would check against the language_count conf variable to avoid the hook invocation for unilingual sites.

We might want to generalize the hook name by calling drupal_alter('translatable', $type, ...).

Edit: this might help also with translatable field settings. e.g. allowed values.

plach’s picture

The current patch implements the generalization proposed in #3/#4.

plach’s picture

the patch

plach’s picture

Status: Needs review » Needs work
FileSize
39.21 KB
38.43 KB

mmh, we probably need to find another place to apply the translation as we get the translated value also while editing the original string (see the attached screenshots).

yched’s picture

re #7: Yep, this is tricky, that's why I'm wondering how #357529: Implement translation of customized 'translatable' views properties does it.

nedjo’s picture

IN #357529: Implement translation of customized 'translatable' views properties we're setting a flag on the view object when editing:


+      // Set a flag to indicate that this view is being edited.
+      // This flag will be used e.g. to determine whether strings
+      // should be localized.
+      $view->editing = TRUE;

yched’s picture

@nedjo: thanks. Doesn't the Views patch also explicitly flag some properties as 'translatable' ? I'm wondering if we'd need that here...

nedjo’s picture

@yched: Yes, that flag is already part of Views (not introduced in the patch). Right now at least some of the values of flagged properties are passed through t(). The patch introduces support for plugins for different translation options.

For fields, yes, I guess a flag would also be good to avoid having to hard-code the translatable properties.

So far we've identified label and description as translatable. What other properties might be translatable? I guess admin-entered select options for a text field would be one.

While it's tempting to use drupal_alter(), that only really makes sense if we potentially want what drupal_alter() is designed for--more than one module making alterations. If instead what we want is a single translation handler, we'd probably need a way to register a handler.


+    drupal_alter("translate_$type", $object, $options);

If we do use drupal_alter(), probably it would be good to be able to catch all translation in a single alter hook implementation.


+    drupal_alter('translate', $properties, $type, $options);

That would mean we'd have to pass not the object itself but a stripped-down version with only the translatable properties.

If we think for a moment from the point of view of modules implementing translation, so far (in i18nstrings) we've tended to create a unique ID for strings to be translated. For example, the description for taxonomy term with tid 21 might be taxonomy-term-21-description. Using an id allows for updates and deletions of translations. So we might end up with:


+    drupal_alter('translate', $properties, $id, $options);

where $id might be (in the taxonomy term example) array('taxonomy', 'term', '21').

catch’s picture

Missed this, subscribing.

sun’s picture

huh? Why "translate_$object"? Usually, there is 1 module that takes over translation services for objects and it just needs to know how to handle the object.

Consider how many hooks i18n would have to implement to allow to translate object values...

So, drupal_alter("object_translate", $object, $type, $options) would do better.

However, not wanting to hi-jack this issue - but apparently I'm tinkering about normalizing object data (or exploding data into multiple table columns) and adding a magic query tag throughout core for some time now. Use a table as outlined in #141461-26: Object translation option #1: locale system, optimization strategies (and as implemented in Translatable module) to auto-perform a LEFT JOIN on all tagged queries to auto-load the proper data initially already. Separate issue, not existing yet.

sun’s picture

That issue now exists and even works better than I imagined: #593746: Prepare Drupal core for dynamic data translation

tomsm’s picture

subscribing...

yched’s picture

FileSize
4.11 KB

Sorry for not reporting earlier.
As promised in #593746-57: Prepare Drupal core for dynamic data translation, I started a patch to apply the new mechanism for 'translatable properties' added over there.

Well, the 1st step of moving label and description out of the serialized {field_config_instance}.data column and into their own columns is dead easy, attached patch does that.

More complex is how field_read_instance() and field_info_instance[s]() should handle the notion of 'translated' or 'non translated' instance information.
Bottomline is: the properties that show up in Field UI's forms should always be the *untranslated* ones, or the translated values will end up being saved as the primary definition.
Similarly, the following API sequence:

$instance = field_info_instance('node', 'field_foo', 'article');
$instance['some_property'] = 'foo';
field_update_instance($instance);

will have the same undesired result.

Not sure of how this can be handled in a non-ugly way. I'm also not sure I'll be actively working on this in the near future :-/

Leaving as CNW.

sun’s picture

Status: Needs work » Needs review

More complex is how field_read_instance() and field_info_instance[s]() should handle the notion of 'translated' or 'non translated' instance information.
Bottomline is: the properties that show up in Field UI's forms should always be the *untranslated* ones, or the translated values will end up being saved as the primary definition.
Similarly, the following API sequence:

This issue, we will have to tackle in a general sense, because it not only applies to field labels + descriptions.

Let's see what the bot thinks about this patch. :)

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
3 KB

Rerolled, and removed the 'translatable' query tag until this is figured out, then..

Status: Needs review » Needs work

The last submitted patch failed testing.

dagmar’s picture

Status: Needs work » Needs review

Failed: Failed to install HEAD.

mmm, test bot was working? Lets try again.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
2.98 KB

Doh, 'description' column, being of type 'text', cannot have a default value.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
4.41 KB

testCreateFieldInstance() needed to be updated accordingly.

sun’s picture

Title: Translations of field labels and descriptions » Prepare field label and description for DDT (translatable queries)
Status: Needs review » Reviewed & tested by the community

Looks nice and elegant. Thanks, yched!

webchick’s picture

Status: Reviewed & tested by the community » Needs review

Why are we changing core's DB schema around at this point in the release cycle? Shouldn't this be handled by i18n module?

The original post talks about removing some ugly dynamic t() stuff, but I see no hunks like that in this patch. Therefore, this seems like an API addition to me?

yched’s picture

Why are we changing core's DB schema around at this point in the release cycle ?

Because the idea of #593746: Prepare Drupal core for dynamic data translation was born, matured and got in within the last month. That approach requires translatable data to be in their own columns. Before that, there was no reason for those columns to be separated, so they were not.
Also, any code currently making assumptions on the structure of those tables to read or write directly in them would be seriously wrong. All the logic for handling this table is encapsulated in field_[read|create|update]() API functions, which should be used for any access to this data (well, except of course for core update functions in the future). The patch does not change this API.

The original post talks about removing some ugly dynamic t() stuff, but I see no hunks like that in this patch

We'll be able to remove those when #15-#17 is sorted out, and we can actually add the 'translatable' tag to the query that reads instances definitions.
This should be doable without an API change (probably an API addition, though, like an additional optional param in field_read_instance() and field_info_instance functions, that would be used by field UI)

nedjo’s picture

Are there other data that may be serialized into the 'data' column - e.g., attributes added by contrib modules - that require translation?

If so, simply pulling label and description into the schema as separate fields helps, but it's an incomplete solution--and one that contrib can't (easily) follow.

We're going to continue to have strings that require translation and that are stored in serialized fields. This issue came up in #357529: Implement translation of customized 'translatable' views properties (see sun's comment).

plach’s picture

@nedjo:

Are there other data that may be serialized into the 'data' column - e.g., attributes added by contrib modules - that require translation?

Surely List's allowed values, which really need a way to be translated.

yched’s picture

Well, there are indeed stuff in the serialized 'data' column that would benefit from being translatable.
- default value (for most fields except filefield)
- allowed values (for list fields, e.g 'Yes, No, Maybe')
- prefix, suffix (for number fields)
- foobar (for some contrib field type we don't even know about yet).

Problem is those are settings specific to some field types (or widget type, or formatter type), and thus cannot be moved to their own columns. The primary reason for a serialized column is the flexibility of the actual content of a $field or $instance structure...

So, this would need the full 'data' column to be marked translatable, and let i18n handle its 'replacement' translated serialized arrays. I don't know to what extent this is feasible on the i18n side.
It seems at least this would require marking which properties are translatable or not.

function number_field_info() {
  return array(
    'number_integer' => array(
      'label' => t('Integer'),
      'description' => t('This field stores a number in the database as an integer.'),
      'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''),
      // ...

needs to become

function number_field_info() {
  return array(
    'number_integer' => array(
      'label' => t('Integer'),
      'description' => t('This field stores a number in the database as an integer.'),
      'instance_settings' => array(
        'min' => array('default' => '', 'translatable' => FALSE),
        'max' => array('default' => '', 'translatable' => FALSE),
        'prefix' => array('default' => '', 'translatable' => TRUE),
        'suffix' => array('default' => '', 'translatable' => TRUE),
      ),
      // ...

Now *that* is an API change (although I guess we can code some BC layer so that we understand both formats, in which case it becomes an API addition...)

webchick’s picture

I should clarify that Dries and I are not necessarily opposed to API changes at this stage, if they fix critical issues. We just want to avoid them when we can, and ones that affect lots of module/theme developers need a really good excuse.

mcload’s picture

subscribing

Pasqualle’s picture

spacereactor’s picture

subscribing

spacereactor’s picture

Status: Needs review » Needs work
Issue tags: +i18n, +translatable strings, +translatable fields

The last submitted patch, field_label_translate.patch, failed testing.

plach’s picture

Version: 7.x-dev » 8.x-dev

I'm afraid this is for D8 now :(

plach’s picture

Tor Arne Thune’s picture

Some examples of not being able to translate field labels and their description (as motivation of fixing this in D8):
#1028538: Some shortcut links not translated
#1052478: 'Find content' not translated in Content shortcut bar

plach’s picture

plach’s picture

plach’s picture

Status: Needs work » Postponed

I guess we need to wait to figure out how to address object translation in general before going on with this (see the discussion going on in the issue above).

See also: http://groups.drupal.org/node/149984

mgifford’s picture

Do we know how object translation is dealt with now? If so should this still be postponed?

plach’s picture

Status: Postponed » Closed (won't fix)

This is a completely obsolete approach for D8: we are leveraging config translation now.

mgifford’s picture

Brilliant, thanks @platch. I was just trying to clean up some of the Postponed issues that seemed to get stalled!