Drupal 6: Deploying a site with language translation hostnames and resolving hard coded hostname database records

Sometimes there's no escaping hard coded hostnames being stored in your Drupal database. If you have ever setup language translations (i18n) in production, and then deployed the site to a development environment (with a different hostname), you'll know exactly what I am talking about. The first thing you'll notice in your dev site is that all your urls are linking back to the production site, and you may even have a hard time logging in.

If you query the languages table, you'll see the following:

select language, domain
from {languages}

Results:

language domain
de      http://de.ericlondon.com
en      http://www.ericlondon.com
es      http://es.ericlondon.com
fr      http://fr.ericlondon.com

At first I thought it would make sense to write a module or a hook_update_n() function to resolve this problem when deploying to another environment, but this method seemed rather clunky, repeatedly running the same revision of a module's update script. In the end, I decided to simply write a PHP script to run via Drush. The following code fetches your default language and all records in the language table, loops through them, and updates the hostname records to match your new hostname:

<?php

// ensure this script is being called from Drush ONLY
// ensure HTTP_HOST is being used
if (
  !is_array($_SERVER['argv'])
  || substr($_SERVER['argv'][0], -9) != 'drush.php'
  || substr($_SERVER['SCRIPT_FILENAME'], -9) != 'drush.php'
  || !strlen($_SERVER['HTTP_HOST'])
) {
  header('HTTP/1.1 403 Forbidden');
  die('Access Denied.');
}

$output = "";

// fetch hostname from globals
$http_host = $_SERVER['HTTP_HOST'];

// ensure http host exists
if (!$http_host || !is_string($http_host)) {
  die('Error occurred fetching http host.');
}

// set default http host
$default_http_host = 'www.' . $http_host;

// define default language
$default_language = 'en';

// define SQL to fetch default language
$sql = "
  select *
  from {languages}
  where language = '%s'
";

// execute SQL
$default_language_record = db_fetch_object(db_query($sql, $default_language));

// ensure record exists
if (!is_object($default_language_record)) {
  die('Error occurred fetching default language.');
}

// update default language record
$default_language_record->domain = 'http://' . $default_http_host;

// set new variable for "language_default"
variable_set('language_default', $default_language_record);
$output .= "Setting language_default variable to: " . $default_language_record->domain . "\n";

// fetch language records
$sql = "
  select *
  from {languages}
";
$resource = db_query($sql);
$language_records = array();
while ($row = db_fetch_object($resource)) {
  $language_records[] = $row;
}

// correct language records
foreach ($language_records as $key => $value) {

  // determine language prefix
  switch ($value->language) {
    case $default_language:
      $prefix = 'www.';
      break;
    default:
      $prefix = $value->language . '.';
      break;
  }

  $new_domain = 'http://' . $prefix . $http_host;

  $sql = "
    update {languages}
    set domain = '%s'
    where language = '%s'
  ";
  db_query($sql, $new_domain, $value->language);

  $output .= "Setting language record for language: \"" . $value->language . "\" to: " . $new_domain . "\n";

}

drupal_flush_all_caches();

$output .= "Executed: drupal_flush_all_caches()\n";

$output .= "DONE.\n";

echo $output;
?>

I dropped this script (named: fix_env.php) in the root of my Drupal site, and then executed it via Drush using the following shell command:

drush --uri=http://tdb.erl.dev scr fix_env.php

The "--uri" flag allows you to specific a hostname for multi-site environments, and the "scr" flag allows you to specify a php script to execute.

NOTE: I'm in the habit of never using sites/ericlondon.com, because it's a real PITA if you ever try to move your site into a multi-site configuration ^_^

After running the script via Drush, my hostname database records have been corrected to match my development environment:

select language, domain
from {languages}

Results:

language domain
de      http://de.tdb.erl.dev
en      http://tdb.erl.dev
es      http://es.tdb.erl.dev
fr      http://fr.tdb.erl.dev