Here is a variable translation support implementation with textgroups. The system module defines the 'variable' textgroup and any module defining variables can provide a list of callback functions and variable names whose forms are defined in the corresponding callback function. This surely works for the simple settings forms in system module.

Slight usability problem in patch:
- The search result overview page shows the values serialized, as the 'original' value in the editing form. The patch would be a lot simpler if we would add a 'serialized' column as in cache table, so we know when to deserialize automatically. That could work here too. True, we cannot provide an overview string value of serialized arrays, objects, etc. We could deserialize the string to display, but print some dummy value there for other types of (more complicated) serialized values. I don't think this is a serious problem.

Missing from the patch:
- Modification of conf_init() to fetch the translated variable values from the locale table.
- Modification to variable_get() to allow for passing of a language.

Possibilities:
- A slight modification of the locale editing form to include the textgroup and location used should allow for infinite customization possibilities with form_alter(), but this is not included in this patch.

Note that this patch 'competes' against the approach proposed by Jose, which provides a possibly cleaner user interface, but build the form controls into the settings forms and bypasses textgroups. The code for that is available in the i18n repository. I believe both approaches have weaknesses and strengths, so my proof-of-concept implementation is here to debate.

Comments

jose reyero’s picture

subscribe

gábor hojtsy’s picture

Title: A variable translation support implementation with textgroups » Site settings translation with textgroups
Project: Internationalization improvements for Drupal 6.x-dev » Drupal core
Version: » 6.x-dev
Component: Code » language system
Assigned: Unassigned » gábor hojtsy
StatusFileSize
new14.22 KB

Here is a greatly revised patch:

- the locale translation editing form is "powered up" with some identifiers for easy form altering
- modules defining text groups can go in and provide their custom UI for string translation based on the text group and location
- system module defines the 'site settings' text group and provides custom form fields for editing the site settings via form_alter

Some notes:

- If you did not save a settings screen before, or if you 'reset to defaults', you don't get those particular variables for localization. Reorganized variable default values could help here, but regardless of my call to arms on the dev list, and this nice issue: http://drupal.org/node/145164, noone took the helm yet unfortunately.
- Settings page developers should be careful to variable_get() their settings with the default value (pass NULL as language), so the admin pages always show and edit the default values, and translations are on the translations page.
- This implementation only works with form elements which are easy to pull out from their functions. More complex form elements might need some refactoring. Let's collect a list of settings to offer for translation in Drupal 6!
- This implementation works with string or numeric values, which can be saved as strings. Arrays and objects cannot be saved as strings in the locales tables, but as discussed with Dries, it is unlikely that you would like to offer such values for localization (but see below!).

Extensibility:

- $conf[$langcode] is also used to collect settings translations from out of the locale system, so it is possible to localize any settings, whether they are strings, numbers, arrays or objects.

Patch against Drupal 6.x-dev attached. To understand what happens, I have uploaded a short video to demonstrate the functionality. Although I did not underline the custom form editing widgets in the video, you will be able to notice them on the interface. VIDEO HERE: http://hojtsy.hu/drop/DrupalSettings.mpeg

gábor hojtsy’s picture

StatusFileSize
new14.22 KB

Here is a greatly revised patch:

- the locale translation editing form is "powered up" with some identifiers for easy form altering
- modules defining text groups can go in and provide their custom UI for string translation based on the text group and location
- system module defines the 'site settings' text group and provides custom form fields for editing the site settings via form_alter

Some notes:

- If you did not save a settings screen before, or if you 'reset to defaults', you don't get those particular variables for localization. Reorganized variable default values could help here, but regardless of my call to arms on the dev list, and this nice issue: http://drupal.org/node/145164, noone took the helm yet unfortunately.
- Settings page developers should be careful to variable_get() their settings with the default value (pass NULL as language), so the admin pages always show and edit the default values, and translations are on the translations page.
- This implementation only works with form elements which are easy to pull out from their functions. More complex form elements might need some refactoring. Let's collect a list of settings to offer for translation in Drupal 6!
- This implementation works with string or numeric values, which can be saved as strings. Arrays and objects cannot be saved as strings in the locales tables, but as discussed with Dries, it is unlikely that you would like to offer such values for localization (but see below!).

Extensibility:

- $conf[$langcode] is also used to collect settings translations from out of the locale system, so it is possible to localize any settings, whether they are strings, numbers, arrays or objects.

Patch against Drupal 6.x-dev attached. To understand what happens, I have uploaded a short video to demonstrate the functionality. Although I did not underline the custom form editing widgets in the video, you will be able to notice them on the interface. VIDEO HERE: http://hojtsy.hu/drop/DrupalSettings.mpeg

dries’s picture

1. A couple of things -- it is a bit weird that we have to pass in NULL to variable_get(). It would be good if we could merge the -1 and NULL type. That would solve a ton of confusion. If we can't solve this in any way, at least use two defines to the difference between -1 and NULL becomes more clear.

2. I'd rename variable_language to langcode -- that's what we seem to use elsewhere.

3. "Update a variable source value for translation." what do you mean with "update"? Update the translation, update the source, mark the variable as out-of-sync. It would help to be a bit more specific about what and when things get updated.

4. The changes to variable_set() scare me a little bit. There might be modules doing a lot of variable_set()s. For example, there might be code that increments a counter, stored in the variables table, on each page load. The locale_variable_update() might add quite a bit of overhead/queries.

To summarize:
* User experience: good
* Developer experience: could be better
* Performance: might be problematic

I'll review this patch in more depth, as soon as I have some answers to these questions.

gábor hojtsy’s picture

StatusFileSize
new14.39 KB

1. Yes, the -1 and NULL are different because -1 means: use the page language, NULL means: use the default language. The default is -1 to use the page language, so variable_get() will return strings in the page language if not told otherwise. Of course we can introduce new constants there. Have good ideas? LANGUAGE_USE_DEFAULT and LANGUAGE_USE_PAGE are quite ambiquos, LANGUAGE_DEFAULT and LANGUAGE_PAGE is misleading because the constant values are just instructing the function to do something, not represent the language code themselfs.

2. Good idea!

3. Update now means that we update the source string in the locales table to let it be in sync with the variables table. It does not invalidate the translation, as we don't have tools for this ready.

4. Performance. Well, do get a list of variables for localization in locale_variable_update and iterate through them to find whether the currently variable is for localization. If it is not, we don't do anything. I don't think we can do less in variable_set(). I thought about adding the variable update call to system module's default settings submit handler, but that would only work for settings form, not when a variable is modified programatically, so the locale tables can easily get outdated.

New patch attached to fix $variable_language to $langcode and more documentation on what locale_variable_update() updates. Awaiting a good idea for the constants on variable_get() language codes.

gábor hojtsy’s picture

StatusFileSize
new14.39 KB

Updated patch to post-schema API code to avoid offsets when applying :) Otherwise the very same code.

jose reyero’s picture

I think using textgroups for variables is a good idea but *only for translatable texts*, not for any other kind of setting.

I'm working on this alternate, http://drupal.org/node/147041, that really doesn't want to be a 'competing' patch, but a different thread to explore other alternatives.

I think we should push this one and maybe think of some extension for 'localizable variables' != 'translatable variables. Also, I will try to work on http://drupal.org/node/145164 because that one, if we make it 'locale ready' can greatly help development of this one.

About this patch:
- We really don't need specific interface for translators if we use this only for text variables.
- There's some other locale query with an inner join, that causes an error when editing these texts.
- That -1 parameters to get variable defaults is not very clear. I have a 'variable_get_default' proposal in the other patch
- The variable initialization for language shouldn't be in locale module, but in language.inc, It is done before module loading.
- We need to mark these variables in the forms for the administrator to know they will be translatable through textgroups.

For some of these issues, instead of mad form altering, I think the best solution would be to mark the form elements as being a variable and let the forms API handle it. It could also take care of default values.

I.e.

$form['variable_name'] = array(
  '#type' => 'textfield',
  '#variable' => 'variable_name',
 .....
);

And the form functions could take care of the default value and marking it as translatable...

gábor hojtsy’s picture

I think using textgroups for variables is a good idea but *only for translatable texts*, not for any other kind of setting.

Yes, as you have seen the discussion, a realistic target for Drupal 6 seems to be translatable texts. As I have noted this patch includes a $conf array extension, which allows anyone to add any kind of translated variables, not just text.

We really don't need specific interface for translators if we use this only for text variables.

What specific interface? You mean help text for user email tokens? I think those are important to have for a translator, so he knows what tokens she can use.

There's some other locale query with an inner join, that causes an error when editing these texts.

Maybe you can point that out?

That -1 parameters to get variable defaults is not very clear. I have a 'variable_get_default' proposal in the other patch

Good idea!

The variable initialization for language shouldn't be in locale module, but in language.inc, It is done before module loading.

Well, in this patch, translated variables are collected when the first request comes in for a variable in a language. Not necessarily in bootstrap time. It works for me this way, and it is also capable of loading many languages in the same request, getting the set of translated variables when first requested. Sure we can move the variable init code to language.inc so if some bootstrap code want a variable in a language, we can load that in before modules being loaded.

We need to mark these variables in the forms for the administrator to know they will be translatable through textgroups.

Sure.

$form['variable_name'] = array(
  '#type' => 'textfield',
  '#variable' => 'variable_name',
.....
);

And the form functions could take care of the default value and marking it as translatable...

It would be great if you could make this default value change (http://drupal.org/node/145164) happen in the remaining four days, so his would be workable.

dries’s picture

I'd like to see this patch go in and _really_ recommend that everyone helps review this patch.

I still have issues with the $langcode values (-1, NULL) so I'm looking forward to Jose's alternative solution.

gábor hojtsy’s picture

The patch at http://drupal.org/node/145164#comment-250759 (or later versions when come to light) is a prerequisite, to properly support variable defaults for translation, so we can translate variables with their default values even if their corresponding forms are not saved. It also includes an elegant looking variable_get_default().

catch’s picture

Status: Needs review » Needs work

No longer applies.

Hunk #1 succeeded at 442 (offset 19 lines).
Hunk #2 succeeded at 489 with fuzz 2 (offset 20 lines).
Hunk #3 succeeded at 506 (offset 20 lines).
Hunk #4 succeeded at 1041 (offset 19 lines).
patching file includes/locale.inc
Hunk #1 FAILED at 733.
Hunk #2 FAILED at 798.
Hunk #3 FAILED at 812.
Hunk #4 FAILED at 1793.
4 out of 4 hunks FAILED -- saving rejects to file includes/locale.inc.rej
patching file modules/locale/locale.module
Hunk #1 succeeded at 495 with fuzz 1 (offset 15 lines).
patching file modules/system/system.module
Hunk #1 FAILED at 536.
Hunk #2 FAILED at 601.
2 out of 2 hunks FAILED -- saving rejects to file modules/system/system.module.rej

gábor hojtsy’s picture

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

Moving to D7. The contrib i18n module already uses some textgroups for translating values at different places in Drupal.

gábor hojtsy’s picture

Assigned: gábor hojtsy » Unassigned
robin monks’s picture

Status: Needs work » Patch (to be ported)

Subscribing

plach’s picture

Version: 7.x-dev » 8.x-dev
Status: Patch (to be ported) » Needs work
gábor hojtsy’s picture

Status: Needs work » Closed (duplicate)

This was a total dead end. Following the Drupal 8 configuration management initiative instead since they are redoing all of the configuration backend anyway. It is going to be fixed in other ways, so not marking won't fix.