class Xlocalize::Executor

Public Instance Methods

download(wti, locales) click to toggle source
# File lib/xlocalize/executor.rb, line 130
def download(wti, locales)
  begin
    locales.each do |locale|
      translations = wti.pull(locale)
      
      out_list_of_translations_of_locale(wti, locale, translations).each do |out|
        File.open(out["path"], "w") do |file|
          file.write(out["content"])
          puts "Done saving #{out['path']}.".green
        end
      end
    end
  rescue => err
    puts err.to_s.red
  end
end
export_master(wti, project, targets, excl_prefix, master_lang, exclude_units=[], no_cryptic) click to toggle source
# File lib/xlocalize/executor.rb, line 25
def export_master(wti, project, targets, excl_prefix, master_lang, exclude_units=[], no_cryptic)
  master_file_name = locale_file_name(master_lang)

  File.delete(master_file_name) if File.exist?(master_file_name)

  if Helper.xcode_at_least?(9)
    Kernel.system "xcodebuild -exportLocalizations -localizationPath ./ -project #{project}"
  else
    # hacky way to finish xcodebuild -exportLocalizations script, because
    # since Xcode7.3 & OS X Sierra script hangs even though it produces
    # xliff output
    # http://www.openradar.me/25857436
    Kernel.system "xcodebuild -exportLocalizations -localizationPath ./ -project #{project} & sleep 0"
    while !File.exist?(master_file_name) do
      sleep(1)
    end        
  end

  purelyze(master_lang, targets, excl_prefix, project, filer_ui_duplicates=Helper.xcode_at_least?(9.3), exclude_units)
  if no_cryptic then
    config_fname = '.xlocalize.yml'
    config = (YAML.load_file(config_fname) if File.file?(config_fname)) || {}
    allow_cryptic = config['allow_cryptic'] || {}
    
    doc = Nokogiri::XML(File.open(locale_file_name(master_lang)))
    cryptic_trans_units = doc.cryptic_trans_units(allow_cryptic)
    if !cryptic_trans_units.empty? then
      err_msg = "Found cryptic translation units\n"
      err_msg += cryptic_trans_units.map { |fname, units| "#{fname}" + "\n " + units.join("\n ") }.join("\n")
      raise err_msg
    end
  end

  if wti then
    original_doc = Nokogiri::XML(wti.pull(master_lang)['xliff'])
    Nokogiri::XML(File.open(master_file_name)).merge_on_top_of(original_doc)
    File.write(master_file_name, original_doc.to_xml)
  end
  push_master_file(wti, master_lang, master_file_name) if !wti.nil?
end
import(locales, allows_missing_files=false) click to toggle source
# File lib/xlocalize/executor.rb, line 231
def import(locales, allows_missing_files=false)
  puts 'Importing translations' if $VERBOSE
  locales.each do |locale|
    import_xliff("#{locale}.xliff")
    import_plurals_if_needed(locale)
    puts "Done #{locale}".green if $VERBOSE
  end
end
import_plurals_if_needed(locale) click to toggle source
# File lib/xlocalize/executor.rb, line 191
def import_plurals_if_needed(locale)
  plurals_fname = "#{locale}_plurals.yaml"
  return if !File.exist?(plurals_fname)
  puts "Importing translations from #{plurals_fname}" if $VERBOSE
  plurals_yml = YAML.load_file(plurals_fname)
  plurals_yml[locale].each do |original_fname, trans_units|
    content = ''
    content << '<?xml version="1.0" encoding="UTF-8"?>' + "\n"
    content << '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' + "\n"
    content << '<plist version="1.0">' + "\n"

    fname = localized_filename(original_fname, locale)
    content << "<dict>\n"
    trans_units.each do |key, element|
      content << "\t<key>#{key}</key>\n"
      content << "\t<dict>\n"

      content << "\t\t<key>NSStringLocalizedFormatKey</key>\n"
      content << "\t\t<string>%\#@value@</string>\n"
      content << "\t\t<key>value</key>\n"
      content << "\t\t<dict>\n"
      element.each do |k, v|
        content << "\t\t\t<key>#{k}</key>\n"
        content << "\t\t\t<string>#{v}</string>\n"
      end
      content << "\t\t\t<key>NSStringFormatSpecTypeKey</key>\n"
      content << "\t\t\t<string>NSStringPluralRuleType</string>\n"
      content << "\t\t\t<key>NSStringFormatValueTypeKey</key>\n"
      content << "\t\t\t<string>d</string>\n"
      content << "\t\t</dict>\n"

      content << "\t</dict>\n"
    end
    content << "</dict>\n"
    content << "</plist>\n"

    File.open(fname, 'w') { |f| f.write content }
  end
end
import_xliff(fname) click to toggle source
# File lib/xlocalize/executor.rb, line 171
def import_xliff(fname)
  puts "Importing translations from #{fname}" if $VERBOSE
  Nokogiri::XML(File.open(fname)).xpath("//xmlns:file").each do |node|
    tr_fname = node["original"]
    source_lang = node["source-language"]
    target_lang = node["target-language"]
    
    localized_src_fname = localized_filename(tr_fname, source_lang)
    next if !File.exist?(localized_src_fname)

    translations_hash = Apfel.parse(localized_src_fname).to_hash
    importer = Importer.new
    importer.translate_from_node(translations_hash, node)

    f_content = importer.strings_content_from_translations_hash(translations_hash)
    target_fname = localized_filename(tr_fname, target_lang)
    File.open(target_fname, 'w') { |f| f.write(f_content) }
  end
end
locale_file_name(locale) click to toggle source
# File lib/xlocalize/executor.rb, line 17
def locale_file_name(locale)
  if Helper.xcode_at_least?(10)
    return "#{locale}.xcloc/Localized Contents/#{locale}.xliff"
  else
    return "#{locale}.xliff"
  end
end
localized_filename(file_name, locale) click to toggle source
# File lib/xlocalize/executor.rb, line 147
def localized_filename(file_name, locale)
  parts = file_name.split('/')

  # WebTranslateIt uses _ for Language_Country separator e.g. pt_PT
  # but Xcode uses - e.g. pt-PT
  # Repace it to match Xcode file locations
  locale.sub!("_", "-")

  name = ""
  parts.each_with_index do |part, idx|
    name += "/" if idx > 0
    if part.end_with?(".lproj")
      name += "#{locale}.lproj"
    elsif idx+1 == parts.count
      extension = (part.split('.')[1] == 'stringsdict') ? 'stringsdict' : 'strings'
      # TODO: join all parts till the last '.'
      name += "#{part.split('.')[0]}.#{extension}"
    else
      name += part
    end
  end
  return name
end
out_list_of_translations_of_locale(wti, locale, translations) click to toggle source
# File lib/xlocalize/executor.rb, line 113
def out_list_of_translations_of_locale(wti, locale, translations)
  puts "Downloading translations for #{locale}"
  translations = wti.pull(locale)
  plurals_content = translations['plurals']

  out_list = [{
    "path" => "#{locale}.xliff",
    "content" => translations['xliff']
  }]
  out_list << {
    "path" => "#{locale}_plurals.yaml",
    "content" => plurals_content
  } if not plurals_content.nil?

  return out_list
end
plurals_file_name(locale) click to toggle source
# File lib/xlocalize/executor.rb, line 13
def plurals_file_name(locale)
  return locale_file_name(locale) << '_plurals.yml'
end
purelyze(locale, targets, excl_prefix, project, filer_ui_duplicates=false, exclude_units) click to toggle source
# File lib/xlocalize/executor.rb, line 83
def purelyze(locale, targets, excl_prefix, project, filer_ui_duplicates=false, exclude_units)
  locale_file_name = locale_file_name(locale)
  doc = Nokogiri::XML(File.open(locale_file_name))

  puts "Removing all files not matching required targets" if $VERBOSE
  doc.filter_not_target_files(targets)
  puts "Removing trans-unit's having reserverd prefix in their sources" if $VERBOSE
  doc.filter_trans_units(excl_prefix)
  puts "Filtering plurals" if $VERBOSE
  plurals = doc.filter_plurals(project)
  puts "Removing excluded translation units" if $VERBOSE
  doc.xpath("//xmlns:trans-unit").each { |unit| unit.remove if exclude_units.include?(unit['id']) }
  puts "Removing all files having no trans-unit elements after removal" if $VERBOSE
  doc.filter_empty_files
  puts "Unescaping translation units" if $VERBOSE
  doc.unescape

  if filer_ui_duplicates
    puts "Filtering duplicate xib & storyboard translation files" if $VERBOSE
    doc.filter_duplicate_storyboard_xib_files
  end
  
  puts "Writing modified XLIFF file to #{locale_file_name}" if $VERBOSE
  File.open(locale_file_name, 'w') { |f| f.write(doc.to_xml) }
  if !plurals.empty?
    puts "Writing plurals to plurals YAML file" if $VERBOSE
    File.open(plurals_file_name(locale), 'w') { |f| f.write({locale => plurals}.to_yaml) }
  end
end
push_master_file(wti, master_lang, master_file_name) click to toggle source
# File lib/xlocalize/executor.rb, line 66
def push_master_file(wti, master_lang, master_file_name)
  # Pushing master file to WebtranslateIt
  begin
    puts "Uploading master file to WebtranslateIt"
    file = File.open(master_file_name, 'r')
    plurals_path = plurals_file_name(master_lang)
    plurals_file = File.exist?(plurals_path) ? File.open(plurals_path, 'r') : nil
    wti.push_master(file, plurals_file)
    puts "Done.".green
  rescue => err
    puts err.to_s.red
  ensure
    file.close unless file.nil?
    plurals_file.close unless plurals_file.nil?
  end if !wti.nil?
end