We currently have a huge problem with long UI texts (more than one line) in modules, well, several problems:
- Te text is not readable at all as it is mixed with php
- Translating the text is a line by line translation without context.
- Changing any bit of that texts causes it to need retranslation
- They are a huge burden for locale performance as a) they're not cached and b) the table searches use really long strings as index, which make them slow.

This patch makes a few things to fix all these issues and IMHO makes the whole text handling in Drupal much more robust and consistent:

  • Introduces hook_text(). Move big texts to module/text.inc files which will be loaded only when needed (the registry will take care of that), and proposes a much more readable format.
  • Introduces module_get_text() and drupal_get_text() functions which will finally allow us to get rid of _user_mail_text() function, which is done in this patch.
  • Allows all these texts to be overridden using variables, though not of them are editable through the UI
  • Text arguments when they don't need other parameters can be defined also in these files, right below the main text, which makes it really much more readable (The _text hook can return either a plain text or a (text, variables) array. These variables can be overridden when invoking the function though.

Other advantages:

  • Smaller code in modules, this will save a lot of lines of PHP in the main .module files, that will be loaded only when needed (not very often for big texts)
  • Any further attempt to improve localization and translatability (which is what I'm aiming at) will just need to deal with this function, making other patches *much* smaller.
  • The (long story) variables default text can be made much simpler with this, as these text variables will have their own handling and we won't need to provide defaults for them. #145164: DX: Use hook_variable_info to declare variables and defaults

The two prosed API functions look like this. The first one is to retrieve a specific module's text and the second one will work for any keyed text. I think both can make sense.

/**
 * Get module text
 * 
 * @param $module
 *   Module name
 * @param $text_id
 *   Id of the text to get, it is internal to each module.
 * @param $args
 *   An associative array of replacements to make after translation.
 * @param $langcode
 *   Optional language code to translate to a language other than what is used
 *   to display the page.
 * @return
 *   The translated string with variables replaced.
 */
function module_get_text($module, $text_id, $args = array(), $langcode = NULL) {}

/**
 * Get named text.
 * 
 * This function gets a text searching before for possible variable overrides and localization
 * 
 * If the text is found, it will be returned
 * @see drupal_replace_string()
 * 
 * @param $module
 *   Module name
 * @param $text_id
 *   Id of the text to get, it is internal to each module.
 * @param $text
 *   Default text to be used if a more suitable one is not found
 * @param $args
 *   An associative array of replacements to make after translation.
 * @param $langcode
 *   Optional language code to translate to a language other than what is used
 *   to display the page.
 * @return
 *   The translated string with variables replaced.
 */
function drupal_get_text($text_id, $text, $args = array(), $langcode = NULL) {}

Notes:
- The locale module part is just an example of how this could work to localize texts, not really working yet.
- The text.inc file format is just a vague idea, for texts to be readable, I know it's not up to current standards, but also I don't think current code standards will help with readability here. Ideas and help wanted!!

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Jose Reyero’s picture

FileSize
3.87 KB

I forgot this, just in case someone wants to see how the text.inc files may look like. I've just done two for now with a few sample strings for node and user modules

Jose Reyero’s picture

Issue tags: +i18n sprint
Jose Reyero’s picture

Status: Active » Needs review
Damien Tournoud’s picture

They are a huge burden for locale performance as a) they're not cached and b) the table searches use really long strings as index, which make them slow.

That's not perfectly true. The lookup is actually quite fast, because it can use a partial index.

On the other hand, your solution impose to put all the texts in the same file for a given module (because you can have only one hook_text() implementation for a given module), so you are actually trading memory consumption against performance.

I'm not sure I see the difference between this solution and the previous one your suggested. Are they both useful? Or are they exclusive one from another?

Jose Reyero’s picture

@Damien

> On the other hand, your solution impose to put all the texts in the same file for a given module (because you can have only one hook_text() implementation for a given module), so you are actually trading memory consumption against performance.

Not all, only big (multiple line) ones, that file will be only loaded when needed, which if you look at such texts, they're loaded usually on only one of the module's pages

> 'm not sure I see the difference between this solution and the previous one your suggested. Are they both useful? Or are they exclusive one from another?

They're exclusive atm but this one can be easily expanded later with some localized text loading. The main point is that we can handle all these texts in the same function.

Jose Reyero’s picture

Status: Needs review » Closed (duplicate)
Jose Reyero’s picture