14

I have a little helper function for my hook_schema:

function _bbcmap_schema_asr_field($description) {
  return array(
    'type' => 'int',
    'unsigned' => TRUE,
    'size' => 'small', // Up to ~66k with MySQL (equivalent up to ~660.00 adjusted)
    'not null' => FALSE,
    'description' => t($description),
  );
}

And then I can use it something like:

/**
 * Implements hook_schema().
 */
function bbcmap_schema() {
  $schema['la_data'] = array(
    'fields' => array(
      ...
      'mort_asr_male' =>    _bbcmap_schema_asr_field('The age standardised mortality amongst men (fixed point with scale factor 1/100)'),
      'mort_asr_female' =>  _bbcmap_schema_asr_field('The age standardised mortality amongst women (fixed point with scale factor 1/100)'),
      'incid_asr_male' =>   _bbcmap_schema_asr_field('The age standardised incidence amongst men (fixed point with scale factor 1/100)'),
      'incid_asr_female' => _bbcmap_schema_asr_field('The age standardised incidence amongst women (fixed point with scale factor 1/100)'),
      ...
    ),
  );
}

I know that the guideline is not to pass variables through t() but this seems very similar to how the menu system passes the callback's title through t() (by default). Any comments on this being good or bad style?

17

The first argument of t() needs to be a literal string, which excludes:

  • variables, even the parameters of a function: t($description)
  • a concatenation of strings: t('If you want to add a link, click on' . '<a href="http://example.com">this link</a>.')
  • the value returned from a function:t(get_menu_description())
  • a constant: t(MYMODULE_MY_WIDGET_TITLE), t(MyClass::WIDGET_TITLE)

The reason is that, apart few specific hooks (e.g. hook_menu(), hook_perm(), hook_permission()), the string to translate are found from a script that scan the code of a module, looking for code such as t('This is an example.'); when it finds a value that depends from runtime, such as the value of a variable, the script is not able to understand which is the string that needs to be translated, as a variable could contain a different value each times the code gets executed. In fact, http://localize.drupal.org reports a warning similar to the following one, in the case the argument for t() is not a literal string:

The first parameter to t() should be a literal string. There should be no variables, concatenation, constants or other non-literal strings there. At t($filter['name']) in customfilter/customfilter.module on line 30.

If you are passing a dynamic value to t(), the script that extracts the strings to translate will not extract any value, in that case; the effect is the argument passed to t() will not be translated, which has the same effect of not using t() and using the dynamic output directly in the user interface. The only case for which the string will be translated is when the dynamic string is equal to the literal string a function passes to t(). Suppose, for example, that you have a library not thought for Drupal, which contains a function returning the name of the current month. With the following code, the value returned from that function would be translated.

function mymodule_calendar_page_title() {
  return t(Calendar::getCurrentMonth());
}

function mymodule_calendar_translations() {
  $translations = array(
    t('January'),
    t('February'),
    t('March'),
    t('April'),
    t('May'),
    t('June'),
    t('July'),
    t('August'),
    t('September'),
    t('October'),
    t('November'),
    t('December'),
  );
}

mymodule_calendar_translations() doesn't need to be called, nor to return any value. When the code of the module will be parsed, the call to t() will be found from the code that looks for literal strings passed to t().

Translating the description given for a database table and its fields is then not something that you should do, as none of the Drupal core modules do that; for example, node_schema() contains the following code:

function node_schema() {
  $schema['node'] = array(
    'description' => 'The base table for nodes.', 
    'fields' => array(
      'nid' => array(
        'description' => 'The primary identifier for a node.', 
        'type' => 'serial', 
        'unsigned' => TRUE, 
        'not null' => TRUE,
      ), 
      'vid' => array(
        'description' => 'The current {node_revision}.vid version identifier.', 
        'type' => 'int', 
        'unsigned' => TRUE, 
        'not null' => TRUE, 
        'default' => 0,
      ), 
      // …
    );
    // …
  );

  // …

  return $schema;
}

The report that caused the removal of the calls to t() from any Drupal core implementations of hook_schema() is Remove t() from all schema descriptions, which has been open by webchick (Drupal 7 co-maintainer).

In Szeged, we had a big long discussion about t() around the schema descriptions and it was the consensus of everyone at the table (who included Dries) that t()s should be removed from these descriptions. They mess up things because t() isn't available that early, and people discussed that no one is going to take the time to translate technical descriptions of stuff, and it doesn't really make sense since we also don't translate code comments, for example.

The article about converting a Drupal 6 module to Drupal 7, has a dedicated paragraph: Schema descriptions are no longer translated.

2

They are invariable strings, so it's good to pass them through t(). There are some overhaul of t() system for things like this, but I'm not sure it will happen in D8.

Currently, it is only bad if you pass something like t($count . ' books') where $count can take any value, as it will generate too many string for the translation.

-1

It is, however, possible to use t() around a variable, and for it to work. I have done it with $title in page.tpl.php.

EDIT: Perhaps the strings don't get translated, but they can be used for string overrides.

  • 1
    See kiamlaluno's answer for why that's a bad idea. – Andy Feb 20 '14 at 9:03
  • kiamlaluno's answer seems to be saying that the string won't be translated. But another use for t() is to enable string overrides. I can confirm that that does work with variables. – naomi Feb 21 '14 at 9:46
  • 1
    @naomi Yes it will work. But if you have translations enabled, all of the titles passed thro t() will end up in the translation strings list. You shouldn't use string overrides to change node titles IMO. Create a field, and change node title to the field's value in a hook_preprocess_node or page. (You can also use hook_node_load or any related hook too) – AyeshK Feb 21 '14 at 10:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.