3

I tried adding a description for the language field in a node form using hook_form_alter:

$form['language']['#description'] = t('Description');

The changes are not accepted, the language field stays as it is the description is not added. As far as i can tell this is not a problem with the hook, because changes to other fields work fine, only the language field does not change. Any ideas what i'm doing wrong.

  • Have you dumped the contents of $form to see if you are getting the correct element? – Alex Gill Oct 16 '12 at 14:43
3

Your code doesn't work because the node edit/create form sets $form['language'] using the following code. (See node_form().)

  // Basic node information.
  // These elements are just values so they are not even sent to the client.
  foreach (array('nid', 'vid', 'uid', 'created', 'type', 'language') as $key) {
    $form[$key] = array(
      '#type' => 'value', 
      '#value' => isset($node->$key) ? $node->$key : NULL,
    );
  }

It's then the Locale module that changes the form field in locale_form_node_form_alter() using the following code.

  if (isset($form['#node']->type) && locale_multilingual_node_type($form['#node']->type)) {
    $form['language'] = array(
      '#type' => 'select', 
      '#title' => t('Language'), 
      '#default_value' => (isset($form['#node']->language) ? $form['#node']->language : ''), 
      '#options' => array(LANGUAGE_NONE => t('Language neutral')) + locale_language_list('name'),
    );
  }
  // Node type without language selector: assign the default for new nodes
  elseif (!isset($form['#node']->nid)) {
    $default = language_default();
    $form['language'] = array(
      '#type' => 'value', 
      '#value' => $default->language,
    );
  }

If your module is executed before the Locale module, its changes to the language form field are not retained, as the Locale module set $form['language'] to a different array.

In order for your code to work, you need to change the weight of your module, or implement hook_module_implements_alter() to alter the order hooks are executed.

function mymodule_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'form_alter') {
    // Move mymodule_form_alter() to the end of the list. module_implements()
    // iterates through $implementations with a foreach loop which PHP iterates
    // in the order that the items were added, so to move an item to the end of
    // the array, we remove it and then add it.
    $group = $implementations['mymodule'];
    unset($implementations['mymodule']);
    $implementations['mymodule'] = $group;
  }
}

This code changes also the order in which hook_form_FORM_ID_alter(), and hook_form_BASE_FORM_ID_alter() are executed.

| improve this answer | |
1

@kiamlaluno: I don't think your approach works. Here a comment from the i18n module:

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
 function i18n_node_form_node_form_alter(&$form, $form_state) {
 $node = $form['#node'];
 /**
  * i18n has to override locale.module
  * drupal_alter() fails to order modules correctly in some cases
  * for example specific hooks like hook_form_BASE_FORM_ID_alter
  *
  * its not possbile to reorder hook_form_BASE_FORM_ID_alter with
  * hook_module_implements_alter
  *
  * @see http://drupal.org/node/765860
  */

   // call a 'private' implemenation of i18n_node_form_node_form_alter()
   $form['#after_build'][] = '_i18n_node_form_node_form_alter';
  }

I used the '#pre_render' property to solve this:

  function your_module_form_node_form_alter(&$form, &$form_state){
    $form['language']['#pre_render'][] = '_your_module_language_node_prerender';
   }

   function _your_module_language_node_prerender($element){
     // do something with $element
     return $element
   }
| improve this answer | |

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.