Custom Form Labels in Drupal without String Overrides

,

One of the aggravating aspects of customizing built-in labels and other strings in Drupal is that it’s a simple substitution that will change all occurrences of the exact string through the entire site, regardless of context. So the quick and dirty methods work much of the time, especially for longer strings that are more likely to be unique. In the case of single-word strings, though, they often have different meanings in different contexts. For example, “View” can be a noun or a verb, and it might refer to viewing an image or a View from the views module. So sometimes you want and need to be very precise in the way you make these changes.

Let’s say that you have a field like Weight in one of your Drupal content types (for example, an e-commerce site with Ubercart will have Products and those all have a Weight field). So you want to change that on the entry form to something like Shipping Weight (product as packaged), as distinguished, for example, from Field Weight (product as used).

It’s really easy to change that using one of the many string substitution methods in Drupal. You can create a full-on translation file using the built-in Drupal Locale system, but that’s overkill if you’re building a site in English. Simpler is to use the String Overrides module, which lets you simply override any string. Simply input “Weight” in one column and “Shipping Weight” in the other and it’s done!

Simpler still, in your settings.php file, you can simply add a few overrides without the extra overhead of adding a whole module:

 $conf['locale_custom_strings_en'] = array(
   'Weight'      => 'Shipping Weight',  
 );

Same effect. Great! Just one little problem. Now if you go to a page that has some type of sorting, like for a menu item or taxonomy term, the Weight field that determines sort order in Drupal now reads “Shipping Weight” when that isn’t what it is at all. Arrgh! Drupal indiscriminately looks for any text wrapped in the t() function that matches “Weight” and replaces it, regardles of context. That’s no good!

To get some more granularity, you need to alter your form on a form-by-form basis. To do this, I created a simply module to make the form tweaks I need. I call it TD_form_tweaks because it is for the Trail Designs site. Like any module, it needs a .info file

td_form_tweaks.info

name = TD Form Tweaks
description = "Programmatically make necessary tweaks to forms on the site."
package = User interface
core = 6.x

version = "6.x-0.9"
core = "6.x"
project = "td_form_tweaks"
datestamp = "1287267734"

And then the actual functionality.

/**
* @file
* td_form_tweaks allows form modifications using the methods outlined
* in this excellent Lullabot post:
* http://www.lullabot.com/articles/modifying-forms-drupal-5-and-6
*/

/**
* Implementation of hook_form_alter().
*
* This lets you make changes to any form in the site. You can alter
* remove or add form elements. You can also alter the validation 
* and submission behavior. The name will always be modulename_form_alter.
* If this will only be used on one form, you can use the hook_FORM_ID_alter 
* function instead of the hook_form_alter.
* see http://api.drupal.org/api/function/hook_form_FORM_ID_alter/6
*/
<pre>
function td_form_tweaks_form_alter(&$form, $form_state, $form_id) {

/*
* used with devel module to determine form ID and such
*      $dpm($form);
*/

$is_product == FALSE;
$product_types = uc_product_types();

// is user creating a new product page?
if (arg(0) == 'node' && arg(1) == 'add' && in_array(arg(2), $product_types)) {
   $is_product = TRUE;
}

// is user editing an existing product page?
if (arg(0) == 'node' && arg(2) == 'edit') {
  $node = node_load(arg(1));
  if (!empty($node->type) && in_array($node->type, $product_types)) {
     $is_product = TRUE;
  }
}

// if it's a product, alter the form
if ($is_product && $form['#id'] == 'node-form') {
      if (!empty($form['base']['weight']['weight'])) {
        $form['base']['weight']['weight']['#title'] = t('Packaged Weight');
      }
  }
}

And voilà! This could easily include a switch statement and be set up to make any number of changes to any number of product types. A bit more work than a simple string override, yes, but it doesn’t propogate willy-nilly throughout the site.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>