Make the Drupal 7 language switcher work with multi-lingual CiviCRM

Update: trying to get this into CiviCRM core, see: http://forum.civicrm.org/index.php/topic,30649.0.html

The theme() function in Drupal 7 offers the possibility to specifiy a "context". This means that modules who used to call :

theme('list', $stuff);

Can now do:

theme('list__mystuff', $stuff);

Which allows themers to override the theme function for that specific case.

In my use case, I want a language switcher that supports multi-lingual CiviCRM forms. The language switcher provided by the default locale block will drop any arguments in the URL, which means that pages such as:

/en/civicrm/contribute/transact?reset=1&action=preview&id=3&lcMessages=en_US

Would be transformed to:

/fr/civicrm/contribute/transact

Therefore causing CiviCRM to output an error, since the page ID was not provided in the request.

I'm not sure if this is the cleanest solution, but it works for me:

/**
 * Implements hook_links__locale_block()
 * make the language switcher work with civicrm
 * adapt and insert into your theme's template.php
 */
function yourthemename_links__locale_block($variables) {
  if (arg(0) == 'civicrm') {
    foreach ($variables['links'] as $lang => $attr) {
      $query = $_REQUEST;
      unset($query['IDS_request_uri']);
      unset($query['IDS_user_agent']);
      if ($lang == 'fr') {
        $query['lcMessages'] = 'fr_CA';
      }
      else {
        $query['lcMessages'] = 'en_US';
      }
      $variables['links'][$lang]['query'] = $query;
    }
  }
  return theme('links', $variables);
}

You can add the above code in your theme's template.php. Do not forget to flush the Drupal cache afterwards.