BadrIT/translation_center

View on GitHub
lib/translation_center/translations_transfer.rb

Summary

Maintainability
A
2 hrs
Test Coverage
module TranslationCenter

  # needed for interpolated translations in I18n
  def self.get_translation_from_hash(key, hash)
    path = key.split('.')
    last_step = hash
    path.each do |step|
      break if last_step.blank? || !last_step.is_a?(Hash)
      last_step = last_step[step.to_s.to_sym]
    end
    last_step
  end

  def self.collect_keys(scope, translations)
    full_keys = []
    translations.to_a.each do |key, translations|
      new_scope = scope.dup << key
      if translations.is_a?(Hash)
        full_keys += collect_keys(new_scope, translations)
      else
        full_keys << new_scope.join('.')
      end
    end
    return full_keys
  end

  # gets the translation of a a key in certian lang and inserts it in the db
  # returns true if the translation was fonud in yaml 
  def self.yaml2db_key(locale, translation_key, translator, all_yamls)
    I18n.locale = locale
    translation = TranslationCenter::Translation.find_or_initialize_by(translation_key_id: translation_key.id, lang: locale.to_s, translator_id: translator.id)
    translation.translator_type = TranslationCenter::CONFIG['translator_type']
    
    # get the translation for this key from the yamls
    value = get_translation_from_hash(translation_key.name, all_yamls[locale])

    # if the value is not empty and is different from the existing value the update
    if value.is_a? Proc
      puts "proc removed for key #{translation_key.name}"
      translation.destroy unless translation.new_record?
    elsif !value.blank? && value != translation.value
      translation.update_attribute(:value, value)
      # accept this yaml translation
      translation.accept if TranslationCenter::CONFIG['yaml2db_translations_accepted']
      true
    end
  end

  # takes array of keys and creates/updates the keys in the db with translations in the given locales
  def self.yaml2db_keys(keys, translator, locales, all_yamls)
    # initialize stats variables
    new_keys = 0
    missing_keys = locales.inject({}) do |memo, lang|
      memo[lang] = 0
      memo
    end

    # for each key create it in the db if it doesn't exist, and add its translation to
    # the db in every locale
    keys.each do |key|
      translation_key = TranslationCenter::TranslationKey.find_or_initialize_by(name: key)
      if translation_key.new_record?
        translation_key.save
        new_keys += 1
      end

      # for each locale create/update its translation
      locales.each do |locale|
        missing_keys[locale] += 1 unless self.yaml2db_key(locale, translation_key, translator, all_yamls)
      end

    end

    puts "found new #{new_keys} key(s)"
    missing_keys.each do |locale, count|
      puts "missing #{count} translation(s) for #{locale}" if count > 0
    end
  end

  # take the yaml translations and update the db with them
  def self.yaml2db(locale=nil)

    # prepare translator by creating the translator if he doesn't exist
    translator = TranslationCenter.prepare_translator

    # if couldn't create translator then print error msg and quit
    if translator.blank?
      puts "ERROR: Unable to create default translator with #{TranslationCenter::CONFIG['identifier_type']} = #{TranslationCenter::CONFIG['yaml_translator_identifier']}"
      puts "Create this user manually and run the rake again"
      return false
    end

    # Make sure we've loaded the translations
    I18n.backend.send(:init_translations)
    puts "#{I18n.available_locales.size} #{I18n.available_locales.size == 1 ? 'locale' : 'locales'} available: #{I18n.available_locales.join(', ')}"

    # Get all keys from all locales
    all_yamls = I18n.backend.send(:translations)
    all_keys = all_yamls.collect do |check_locale, translations|
      collect_keys([], translations).sort
    end.flatten.uniq
    puts "#{all_keys.size} #{all_keys.size == 1 ? 'unique key' : 'unique keys'} found."

    locales = locale.blank? ? I18n.available_locales : [locale.to_sym]

    # create records for all keys that exist in the yaml
    yaml2db_keys(all_keys, translator, locales, all_yamls)
  end

  def self.db2yaml(locale=nil)
    locales = locale.blank? ? I18n.available_locales : [locale.to_sym]

    # for each locale build a hash for the translations and write to file
    locales.each do |locale|
      result = {}
      I18n.locale = locale
      puts "Started exporting translations in #{locale}"
      TranslationCenter::TranslationKey.translated(locale).each do |key|
        begin
          key.add_to_hash(result, locale)  
        rescue
          puts "Error writing key: #{key.name} to yaml for #{locale}"
        end
      end
      File.open("config/locales/#{locale.to_s}.yml", 'w') do |file|
        file.write({locale.to_s => result}.ya2yaml)
      end
      puts "Done exporting translations of #{locale} to #{locale.to_s}.yml"
    end 
  end

end