Language Based Stylesheet Switching in Your Theme

multilingual DrupalTheming in Drupal is the one layer that seems to have shown the most steady improvement since the introduction of phpTemplate around version 4.5. With each new release it gets easier and easier to bend Drupal to your will and have it display a pixel perfect version of your design.

In Drupal 6 we saw the introduction of powerful .info files that you can use to tell the theme system more about your specific theme. Things like its name, whether its a subtheme, what core Drupal system variables it supports, which features are configurable and which style sheets to use and load for different media.

By defining which style sheets to load in the .info file you don't need to know any PHP (or where you'd use that PHP) to include several style sheets into your site's pages. This really is a great feature. But, what if there are situations when you don't want those style sheets to show up? Or you'd rather have different style sheets load? Well, in those situations you're still going to have to get familiar with some PHP, Drupal's preprocess functions and drupal_get_css().

I recently found myself needing to switch style sheets based on language. Drupal already has some built in code to handle style sheet switching if the defined languages in your site are right to left (RTL) languages. In those cases you simply need to include style sheets with an -rtl suffix in the style sheet name (e.g. style-rtl.css). And when a RTL language is selected, Drupal will take care of loading the -rtl.css file. (For more detailed information see "Supporting "right to left" (RTL) languages" in the handbook.) But what if like me you want Drupal to load a different style sheets for each of your non RTL languages?

After my first bit of investigation, I'd actually come across a hook I'd never run into before hook_system_info_alter which allows modules to alter the .info file of any other module or theme. This would include altering the part of the theme .info file that defines what style sheets to load. But, upon reading the documentation I realized it only gets called when Drupal's caching is rebuilt or when visiting the admin/build/theme page. In other words not on every page load nor when the language is switched.

But, since this is a presentation layer job we're trying to achieve the logical place to look is the theming layer. And in the theme layer, we are specifically looking at information being loaded into a page. Actually, we are looking for a way to modify something before it is loaded into the page.tpl.php file.

Luckily Drupal 6 has Drupal pre-process functions just for this sort of thing. Since it is the 'page' we're interested in we want to make use of the themename_preprocess_page() function.

This function gets passed a $vars array by reference. This array contains the variables and their values that will be passed into the page.tpl.php file. By the time themename_preprocess_page() is called it is already populated with $vars['css'] and $vars['styles'], but you have a chance to change their values.

So if you wanted to change the style sheets based on language you could use some code similar to this.

function foo_preprocess_page(&$vars, $hook) {
  global $language;
  if ($language->language != 'en') {
    foreach ($vars['css']['all']['theme'] as $stylesheet => $value) {
      if (strstr($stylesheet, path_to_theme())) {
        $stylesheet = str_replace('.css', '-'. $language->language .'.css', $stylesheet);
      }
      $sheets[$stylesheet] = $value;
    }
    $vars['css']['all']['theme'] = $sheets;
    $vars['styles'] = drupal_get_css($vars['css']);
  }
}


In a nutshell, this code checks to see if the current language is not english (could be adjusted to test if its not the 'default' language). If not, then find the style sheets loaded by your current theme and change them to load style sheets with a language suffix. It then repopulates the $vars['css'] and $vars['styles'] with their new values.

Having this exact code run would require that you have a copy of each of your style sheets for each language that your user could switch to reside in your theme's folder. Those style sheets would have to be named in the following format orginalname-langcode.css (e.g. style-fr.css).

I suppose this concept could be expanded to write a module that would allow an administrator to select which of the theme's style sheets to replace (instead of replacing them all) and for which languages to do it. Or, you can simply adjust the logic in the above function to suit your specific needs.

As always, leave a comment if you have a question, different solution or have suggestions on improving the information provided here.

May 5th 2009 11PM
By: andre

 

Comments

worked like charm. Comment

worked like charm. Comment from Benjamin also worked great. Thanks

Posting Emailed Comment

Check if file exists and only use then

You could also check if the file for an alternate language stylesheet
exists, and only try to load it then. Not tested at all, but it seems this
could be added inside that if:

<?php
      $stylesheet_lan = str_replace('.css', '-'. $language->language
.'.css', $stylesheet);
      $stylesheet = (file_exists($stylesheet_lan)) ? $stylesheet_lan :
$stylesheet;
?>

benjamin, Agaric Design Collective

This is great

Great writeup; thanks a lot!

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options