Skip to content

Instantly share code, notes, and snippets.

@phillipoertel
Created September 27, 2009 19:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phillipoertel/194964 to your computer and use it in GitHub Desktop.
Save phillipoertel/194964 to your computer and use it in GitHub Desktop.
A bunch of files to migrate translation data from Globalize 1 (yuck) to use it with Globalize 2 (looks promising, much cleaner and simpler)
#
# A bunch of files to migrate translation data from Globalize 1 (yuck)
# to use it with Globalize 2 (looks promising, much cleaner and simpler)
#
# I'll generalize, convert this into a plugin and document this
# if there's enough interest.
#
========== lib/tasks/globalize_migrator.rake
require File.join(File.dirname(__FILE__), '../../config/environment')
namespace :globalize do
namespace :migrate do
desc "Migrate model translations from Globalize 1 tables to 2"
task :models do
GlobalizeModelMigrator.new.run
end
desc "Migrate view translations from Globalize 1 tables to 2"
task :views do
GlobalizeViewMigrator.new.run
end
desc "Generate Globalize 1 table dropping migrations"
task :generate_drop_tables do
%w(globalize_countries globalize_languages globalize_translations).each do |table_name|
migration_name = "drop_table_#{table_name}"
sh "script/generate migration #{migration_name}"
migration_file = Dir.glob(File.join(Rails.root, "db/migrate/*#{migration_name}.rb"))[0]
content = File.read(migration_file)
File.open(migration_file, 'w') do |file|
content = content.gsub('def self.up', "def self.up\n drop_table :#{table_name}")
content = content.gsub('def self.down', "def self.down\n raise IrreversibleMigration")
file.write(content)
end
end
end
end
end
========== lib/globalize_model_migrator.rb
class GlobalizeModelMigrator
class GlobalizeTranslation < ActiveRecord::Base
end
# model for all globalize 1 translations
class ModelTranslation < GlobalizeTranslation
end
# models for globalize 2 translations
class FolderTranslation < ActiveRecord::Base
end
class PageTranslation < ActiveRecord::Base
end
def initialize(base_locale = 'de-DE')
# the locale in which the text of the regular active record tables are in
@base_locale = base_locale
end
def run
ModelTranslation.destroy(7531) rescue nil # remove some leftover crap
globalized_classes.each do |model_class|
# access translation AR for current model
g2_translation_class = "GlobalizeModelMigrator::#{model_class}Translation".constantize
g2_translation_class.destroy_all
migrate_translations_for_model(model_class, g2_translation_class)
migrate_base_table_attributes_to_translation_table(model_class, g2_translation_class)
end
end
private
def globalized_classes
[Folder, Page]
end
# loop over all records of this model and convert translations
def migrate_translations_for_model(model_class, g2_translation_class)
model_class.all.each do |record|
attributes = translated_attributes_for_record(record)
attributes.merge!({
:"#{record.class.table_name.singularize}_id" => record.id,
# hard-coded to avoid lookup of id. currently works for me since we only have en lang trans.
:locale => 'en-US'
})
g2_translation_class.create!(attributes)
end
end
#
# Finds all translated attributes for a record and returns them
# in a hash. Example: { :name => 'house', :description => 'a place where people live' }
#
def translated_attributes_for_record(record)
translations = ModelTranslation.find_all_by_table_name_and_item_id(record.class.table_name, record.id)
translations.inject({}) do |attributes, translation|
attributes[translation.facet] = translation.text
attributes
end
end
def migrate_base_table_attributes_to_translation_table(model_class, g2_translation_class)
model_class.all.each do |record|
attributes = select_translated_attributes(record)
attributes.merge!({
:"#{record.class.table_name.singularize}_id" => record.id,
:locale => @base_locale
})
g2_translation_class.create!(attributes)
end
end
def select_translated_attributes(record)
translated_attributes = record.globalize_options[:translated_attributes]
selected = record.attributes.select { |key, value| translated_attributes.include?(key.to_sym) }
Hash[selected] # the damn select returns an array. Fixed in Ruby 1.9 ...
end
end
========== lib/globalize_view_migrator.rb
class GlobalizeViewMigrator
class GlobalizeTranslation < ActiveRecord::Base
end
class GlobalizeLanguage < ActiveRecord::Base
end
# model for all globalize 1 translations
class ViewTranslation < GlobalizeTranslation
end
BASE_LOCALE = 'de-DE'
LOCALE_ID_FOR_EN_US = 1819
def run
migrate_base_language
migrate_non_base_languages
end
private
# the translations for the base language are not stored in the DB in globalize 1,
# instead the keys from the translation calls are used.
# in globalize 2, the translations are pulled from a locale file.
# so we need to generate the locale file from the keys in the files
def migrate_base_language
base_language_keys = view_translations_in_filesystem
translations = base_language_keys.inject({}) do |translations, key|
translations[key] = key
translations
end
write_translations_to_locale_file(translations, BASE_LOCALE)
end
# fetch translations from globalize 1 table and create the corresponding
# locale files for globalize 2
def migrate_non_base_languages
%w(en-US).each do |locale|
glo_language = GlobalizeLanguage.find_by_rfc_3066(locale)
translations = parse_and_load_g1_translations(glo_language.id)
write_translations_to_locale_file(translations, locale)
end
end
def parse_and_load_g1_translations(locale_id)
translations = {}
view_translations_in_filesystem.each do |key|
record = ViewTranslation.find_by_tr_key_and_language_id(key, locale_id)
translations[key] = record.text
end
translations
end
def view_translations_in_filesystem
@translation_keys ||= begin
keys = []
Dir.glob(File.join(Rails.root, 'app/**/*.*')).each do |file|
content = File.read(file)
# example: from _('translate me') the string 'translate me' is extracted
regex = /_\(('|")(.+?)('|")\)/
keys = keys + content.scan(regex).map { |matches| matches[1] }
end
@translation_keys = keys
end
end
def write_translations_to_locale_file(translations, locale)
locale_dir = create_locale_dir(locale)
locale_file = File.join(locale_dir, "views.yml")
File.open(locale_file, 'w') do |file|
# the translation files contain the locale as first level key; add it.
translations = {
locale => symbolize_keys(translations)
}
file.write(translations.to_yaml)
end
end
def create_locale_dir(locale)
locale_dir = File.join(Rails.root, 'lib/locales', locale)
unless File.exist?(locale_dir)
FileUtils.mkdir_p(locale_dir)
end
locale_dir
end
def symbolize_keys(hash)
symbolized = hash.map { |k, v| [k.to_sym, v] }
Hash[symbolized]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment