Drupal Internationalization (i18n) and hreflang for Multilingual SEO

January 27, 2015

Often multilingual sites will use URLs contructed with non-compliant country region codes. When using Drupal and i18n / Internationalization, this can be a problem since i18n_hreflang relies on the language codes as set (manually) within Drupal by the webmaster. In such situations it could be preferable to resolve this with code rather than changing the URL pattern.

I just stumbled across this handy tool for generating IANA-compliant hreflang attribute tags;

hreflang Tags Generator Tool

This is useful on multilingual sites that maintain hreflang tags for associating translations with each other. For example, a page might have the following translations:

<link href=”/pe/productos/cereales” hreflang=”es-pe” rel=”alternate” />
<link href=”/bo/productos/cereales” hreflang=”es-bo” rel=”alternate” />

Also handy:

Language Subtag Lookup

IANA Language Subtag Registry

There may be cases where a site has regional sub-sections or country-specific sub-sections using a non-IANA-compliant code, for example http://www.somesite.com/cz. Well, IANA wants this to be cs-cz, but you probably wouldn’t want your URL to be http://www.somesite.com/cs-cz. And if you’re using a CMS like Drupal (perhaps with the Internationalization module’s i18n_hreflang submodule), it would automatically spit out the tag as:

<link href="/cz/somepath/etc/etc" hreflang="cz" rel="alternate" />

.. and that would make IANA sad, and would cause the HTML to not validate in W3C’s Validator.

Using the i18n_hreflang submodule (in the i18n_contrib module, actually), you could override this on a case-by-case basis within the “18n_hreflang_init() ” function in i18n_hreflang.module. Right after:

foreach($translations as $lang => $translation) {


switch ($lang){
  case "pe":
    $lang = 'es-pe';
  case 'bo':
    $lang = 'es-bo';
  case 'cz':
    $lang = 'cs-cz';
  //etc etc

That overrides the <link> and its hreflang attribute for just a few languages. I did try using a hook in a custom module but could not get it working, so this ended up being a patch of i18n_hreflang.module instead.

There is another module worth mentioning: Alternate hreflang. We have not used this, but it could achieve similar ends, but may also require some similar custom patching to fully validate.

I’m not going to provide a patch file for this since the particular code will need to be customized per site on a case-by-case basis anyway.