Requirements
The previous version of the site was built on Ruby on Rails in a custom content management system that allowed administrators of the site to have content types, categories, and even translations. This was all stored in a MySQL database with a simple schema that allowed for a pretty easy migration into Drupal.
The task was to re-create the entire site within Drupal, keeping the exact same content types, content, and existing design with the exception of a new homepage, new header and new footer. The new homepage design is based off of the current Grammy.com's homepage design.
Previous Homepage:
Newest Homepage:
The Recording Academy wanted to re-platform this on Drupal for a couple of reasons. The first is that since Grammy.com is on Drupal 6 and will be upgraded to Drupal 7 before the next annual awards show, we could leverage some of the work in building the Latin Grammys website with Drupal 7 for the upgrade of Grammy.com itself. The second reason was to bring the site more inline with Grammy.com in terms of capabilities in content editing, advertising, and future enhancements to the site could be leveraged from any improvements that end up being made on Grammy.com.
Migration
For the migration work on this project, we decided to create a custom drush command that could run the various migration scripts. The scripts are split out by content type: each script migrating the pertinent information for a particular content type. They are comprised of a simple function that runs bootstrapped Drupal code to take data from the old Ruby database and transform it for the new Drupal database.
You can find the code for this custom drush command, $ drush lmi
in this gist.
We then have one simple bash script that runs drush commands in succession, like so:
# Clean install using our installation profile written with profiler.
drush site-install lagra -y
drush upwd admin --password="admin"
drush fra --force -y
drush dis overlay -y
drush cc all
# Migrate taxonomy terms.
drush lmi tag
drush lmi genre
drush lmi award
# Migrate content.
drush lmi event
drush lmi nominee
drush lmi page
drush lmi photo
drush lmi podcast
drush lmi press_release
drush lmi sponsor
drush lmi video import
You may also notice that within that bash script, we are installing Drupal from scratch with a custom install profile called 'lagra'. This installation profile is using Profiler and does some simple enabling of core modules, contrib modules, custom features, and sets a few initial variables within the variables table. If you haven't looked into using Profiler on your projects, you should. It allows you to do some pretty complex operations with very simple syntax right in your profile's .info
file.
You can find the code for this custom install profile in this gist.
What this all leads to is a relatively simple and quite an efficient way to completely reinstall the entire project from scratch at any given point. All of the features of the site are in custom Features modules, and the migration scripts run automatically, so a fresh install of the project is as easy as running $ ./docroot/scripts/reset.sh
at any given time. We found this led to a very rewarding workflow during the entire duration of the project.
Translation
Another huge requirement for the site (in fact, one we underestimated) was the use of three different languages on the site: English, Spanish, and Portuguese. For this we had to add a whole slew of i18n_*
modules. Here's the list:
- Internationalization (i18n)
- Block languages (i18n_block)
- Menu translation (i18n_menu)
- Multilingual content (i18n_node)
- Path translation (i18n_path)
- String translation (i18n_string)
- Taxonomy translation (i18n_taxonomy)
- Translation sets (i18n_translation)
- Variable translation (i18n_variable)
- Views translation (i18nviews)
- I18n page views (i18n_page_views)
Challenges
The old Ruby system had a very competent system for managing translations of content. However, not all content in the system was translated, and so there were some challenges in making sure that we could switch to a different language and not have the page show up empty simply because the content was not translated for that particular views listing. The listing being empty was not ideal from a user's standpoint, nor from a content editor's standpoint. So we opted to do a little extra work in the migration scripts for the particular content types that did not have translations. We simply created the English version of the nodes, and at the same time used the same copy for the translations. This resulted in populated views for each language, and an ideal way for content editors to browse the listings and quickly know what content needed to be translated, hit an edit button, and then translate.
Another challenge we didn't account for was all of the strings that are not translated automatically. The String translation module was easy enough to use for most cases, but for the times we found it lacking, we ended up using the String Overrides module to fill in the gaps.
We also found that keeping string translations in code was problematic. We opted for using the $conf
array like so:
global $conf;
$conf['locale_custom_strings_es'][''] = array(
"You must be logged in to access this page." => "Debes estar registrado para acceder a esta página.",
);
However, this also became an issue once we decided to start using the String Overrides module because the $conf
array would simply override any translations we would put in the String Overrides UI. So, we opted to use this $conf
array method to get the values into the database initially (hitting save in the String Overrides UI) and then just remove the $conf
array. Then, we could use the UI to translate the few strings that remained.
This is still something we haven't solved, so if you have any suggestions on easily keeping string translations in code (à la Features), we would love to know about it in the comments!
Involvement
The following were involved in this project at various stages and in various roles:
In order of code contributions.
Brock Boland: Developer at Lullabot
Jerad Bitner: Senior Developer & Technical Project Organizer at Lullabot
David Burns: Senior Developer at Lullabot
Angus Mak: Developer at Lullabot
Ben Chavet: Systems Administrator at Lullabot
Bao Truong: Software/Web Developer at The Recording Academy