Overriding language for a Drupal backend

This blog post is more than 6 years old, so the content may be out of date.

Someone in my DPC Drupal tutorial brought up the topic of multi-lingual sites, and asked how to run the backend of the site in English, when the frontend is in Dutch...

Text in Drupal should run through the t() function, which handles translation. t() checks the global $language variable to choose the target language ($language may be set from user preferences, from a path parameter, from content-negotiation...it will be set automatically).

The solution is to implement an early bootstrap hook - hook_init - to change the language.

Assuming a custom Drupal module called 'backend_language':

<?php
 
/**
 * Implementation of hook_init
 */
function backend_language_init() {
  // get our target backend language from a variable config:
  $backend_language = variable_get('backend_language', FALSE);
 
  // check if the current language is different
  if(_backend_language_is_backend() && $GLOBALS['language']->language != $backend_language) {
    // check that our desired language exists
    $languages_available = language_list();
    if(array_key_exists($backend_language, $languages_available)) {
      // override language to use our preferred language
      $GLOBALS['language'] = $languages[$backend_language];
    }
  }
}
 
/**
 * Check whether the user is vising a backend-page.
 */
function _backend_language_is_backend() {
  // use the same rules that govern the 'admin theme' setting at admin/settings/admin
  // check that the first path parameter is 'admin', or (if the "Use administration theme for content editing" checkbox is checked, if it's a node add/edit form).
  // see system.module:534
  return (arg(0) == 'admin' || (variable_get('node_admin_theme', '0') && arg(0) == 'node' && (arg(1) == 'add' || arg(2) == 'edit')));
}
 

It's a good idea to give this backend_language module a low weight in the system table: we need this to run early, before any other modules use localised text (otherwise some text will be untranslated).

If you're using the admin_menu module, you might want the admin menu to also use your preferred backend language. This is harder because you need to switch languages multiple times:

  • Start bootstrap
  • Switch to English
  • Generate admin menu
  • Switch to previously-used language
  • Continue to render page

This requires careful balancing of system weights (you could manually change the weight with an SQL query, or install the utility module to control module weights through the admin GUI):

  • backend_language module: -10
  • admin_menu: -9
  • backend_language_restore module: -8

Backend language module:

<?php
 
/**
 * Implementation of hook_init
 */
function backend_language_init() {
  // get our target backend language from a variable config:
  $backend_language = variable_get('backend_language', FALSE);
 
  // check if the current language is different
  if(_backend_language_is_backend() && $GLOBALS['language']->language != $backend_language) {
    // check that our desired language exists
    $languages_available = language_list();
    if(array_key_exists($backend_language, $languages_available)) {
      // remember the original language
      $GLOBALS['language_original'] = $GLOBALS['language'];
      // override language to use our preferred language
      $GLOBALS['language'] = $languages[$backend_language];
    }
  }
}

Backend language restore module:

<?php
 
/**
 * Implementation of hook_init
 */
function backend_language_restore_init() {
  if(isset($GLOBALS['original_language'])) {
    $GLOBALS['language'] = $GLOBALS['original_language'];
    unset($GLOBALS['original_language']);
  }
}

[edit] Oops, originally forgot to check that the user was looking at a backend page before switching languages...added now!

Comments

Thanks for sharing this idea!
There's a little typo inside backend_language_init() - $GLOBAL['.... is missing the trailing letter S.

Thanks Carsten - fixed!

Hi, Thanks for the module.
It works fine with superadmin role but i got an error when trying to remove a file with others roles..

When i click on remove, it refresh the block with the image. The button label goes back to french and the picture is always her. I have to click a second time in the button (in french) to delete the picture...

there is a missing semicolon
$GLOBALS['language_original'] = $GLOBALS['language']

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <apache>, <bash>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <php>, <python>, <ruby>. The supported tag styles are: <foo>, [foo]. PHP source code can also be enclosed in <?php ... ?> or <% ... %>.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.