Created
September 27, 2009 19:45
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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