module LostInTranslation
Public Class Methods
ask_for_file(master, namespace = '')
click to toggle source
# File lib/lit/user_interface.rb, line 7 def self.ask_for_file(master, namespace = '') text = master ? "# Master-Locale (e.g. 'en'): " : "# Slave-Locale (e.g. 'de'): " file = {} file[:lang] = [(print text), Readline.readline()][1] file[:filename] = namespace.blank? ? file[:lang] : "#{namespace}.#{file[:lang]}" file[:path] = defined?(Rails) ? "#{Rails.root}/config/locales/#{file[:filename]}.yml" : ask_for_path if !File.exist?(file[:path]) && master log "File #{file[:path]} not found!" file[:path] = ask_for_path elsif !File.exist?(file[:path]) && !master log "File #{file[:filename]} not found! It will be created!" File.open(file[:path], 'w') { |f| f.write({ file[:lang] => {} }.to_yaml(line_width: -1)) } end file[:app_name] = Rails&.application&.class&.parent_name file end
ask_for_locales_path()
click to toggle source
# File lib/lit/user_interface.rb, line 24 def self.ask_for_locales_path return "#{Rails.root}/config/locales" if defined?(Rails) log log 'Please type in the absolute path your locales-folder?' log 'e.g. /home/youruser/Documents/your-awesome-app/config/locales' path = [(print '# '), Readline.readline()][1] path end
ask_for_permission(master, count, slave = nil)
click to toggle source
# File lib/lit/user_interface.rb, line 33 def self.ask_for_permission(master, count, slave = nil) log log 'Comparing Locales' log "Application: #{master[:app_name]}" if master[:app_name] log "Master Locale: #{master[:filename]}.yml" if master log "Slave Locale: #{slave[:filename]}.yml" if slave log "Difference: #{count} Entries" a = [(print "# Wanna do it? [Y/n]: "), Readline.readline()][1] a == 'y' || a == 'Y' || a == '' end
ask_for_sorting(file, app_name)
click to toggle source
# File lib/lit/user_interface.rb, line 67 def self.ask_for_sorting(file, app_name) log log "Application: #{app_name}" unless app_name.blank? log "Do you want the #{file}.yml to be sorted?" log 'Alphabetically & Recursive (ASC)' a = [(print "# [Y/n]: "), Readline.readline()][1] a == 'y' || a == 'Y' || a == '' end
ask_for_split(file, count)
click to toggle source
# File lib/lit/user_interface.rb, line 59 def self.ask_for_split(file, count) log log "Splitting File #{file}.yml" log "File-Count: #{count} new files will be create!" a = [(print "# Wanna do it? [Y/n]: "), Readline.readline()][1] a == 'y' || a == 'Y' || a == '' end
ask_for_task(tasks)
click to toggle source
# File lib/lit/user_interface.rb, line 44 def self.ask_for_task(tasks) log log 'Welcome, stranger!' log 'Are you lost in translation, too?' log 'Then I will be glad to help you one of the following tasks!' tasks.each_with_index do |task, i| log "#{i + 1} => #{task[:text]}" end log 'Soo ... what can I do for you? (Type in the Number)' id = [(print 'Task No.: '), Readline.readline()][1] tasks[(id.to_i - 1)] rescue puts "Cannot find task with id #{id}" end
ask_for_translation(value, new_structure, lang1, lang2, diff_count, diff_counter)
click to toggle source
# File lib/lit/user_interface.rb, line 76 def self.ask_for_translation(value, new_structure, lang1, lang2, diff_count, diff_counter) system 'clear' log log "#{diff_counter} / #{diff_count}" new_s = new_structure.join('---') log "#{new_s} is missing" snippets = LostInTranslation.define_snippets.reverse snippets.each do |snippet| value = value.gsub(snippet.second, snippet.first) end puts "# In #{lang1.upcase}: #{value}" new_val = [(print "# In #{lang2.upcase}: "), Readline.readline()][1] new_val = (new_s + '---' + new_val) unless new_val.blank? new_val end
breakout()
click to toggle source
# File lib/lost_in_translation.rb, line 43 def self.breakout raise "Well in that case, forget it!" end
compare()
click to toggle source
# File lib/tasks/compare.rb, line 4 def self.compare @master, @slave, paths = init prepare_for_edit(master: @master[:path], slave: @slave[:path]) prepare_paths([paths[:master], paths[:slave]]) master_file = YAML.load_file(paths[:master]) slave_file = YAML.load_file(paths[:slave]) count = diff(master_file[@master[:lang]], slave_file[@slave[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], mode: 'count') breakout unless ask_for_permission(@master, count, @slave) new_strings_array = diff(master_file[@master[:lang]], slave_file[@slave[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], diff_count: count, mode: 'replace') new_strings_array.each do |string| result = string_to_hash(string) merge_hash(result, slave_file) end File.open(paths[:slave], 'w') { |file| file.write(slave_file.to_yaml(line_width: -1)) } postpare_paths([paths[:slave]]) FileUtils.cp(paths[:slave], @slave[:path]) reset_tmp_files log 'Done' log end
count()
click to toggle source
# File lib/tasks/count.rb, line 4 def self.count @master, @slave, paths = init prepare_for_edit(master: @master[:path], slave: @slave[:path]) prepare_paths([paths[:master], paths[:slave]]) master_file = YAML.load_file(paths[:master]) slave_file = YAML.load_file(paths[:slave]) count = diff(master_file[@master[:lang]], slave_file[@slave[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], mode: 'count') count2 = diff(slave_file[@slave[:lang]], master_file[@master[:lang]], @slave[:lang], @master[:lang], [@master[:lang]], [], mode: 'count') reset_tmp_files log log 'Differences between Locales' log "#{@master[:filename]}.yml => #{@slave[:filename]}.yml = #{count}" log "#{@slave[:filename]}.yml => #{@master[:filename]}.yml = #{count2}" log 'Done' log end
define_snippets()
click to toggle source
# File lib/lit/file_functions.rb, line 23 def self.define_snippets snippets = [] snippets << ['<<', 'a_greater_than_sign'] snippets << ['*', 'an_asterik_sign'] snippets << ['!', 'a_bang_sign'] snippets << ['%', 'a_percentage_sign'] snippets << ['a_bang_sign \'', '\'a_bang_sign'] snippets end
delete_missing()
click to toggle source
# File lib/tasks/delete_missing.rb, line 4 def self.delete_missing tbd @master, @slave, paths = init prepare_for_edit(master: @master[:path], slave: @slave[:path]) prepare_paths([paths[:master], paths[:slave]]) master_file = YAML.load_file(paths[:master]) slave_file = YAML.load_file(paths[:slave]) breakout unless ask_for_permission(@master, count, @slave) new_strings_array = diff(master_file[@master[:lang]], slave_file[@slave[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], mode: 'clean') master_file = {} new_strings_array.each do |string| string = string.split('---').map { |x| x == @slave[:lang] ? @master[:lang] : x }.join('---') result = string_to_hash(string) merge_hash(result, master_file) end File.open(@master[:path], 'w') { |file| file.write(master_file.to_yaml) } postpare_paths([@master[:path], @slave[:path]]) reset_tmp_files log 'Done' log end
diff(root, compared, lang1, lang2, structure = [], new_array = [], options = {})
click to toggle source
# File lib/lit/difference.rb, line 5 def self.diff(root, compared, lang1, lang2, structure = [], new_array = [], options = {}) @slave_file = options[:slave_file] || '' @mode = options[:mode] || 'count' # replace, clean, count @diff_count = options[:diff_count] || 0 @diff_counter = options[:diff_counter] || 0 root.each_pair do |key, value| next_root = root[key] next_compared = compared.nil? ? nil : compared[key] new_structure = structure.dup << key if value.is_a?(String) && (compared.nil? || compared[key].nil?) if value_missing(@slave_file, new_structure) @diff_counter += 1 if @mode == 'replace' new_val = ask_for_translation(value, new_structure, lang1, lang2, @diff_count, @diff_counter) new_array << new_val unless new_val.blank? elsif @mode == 'clean' new_array << "#{new_structure.join('---')}---#{value}" end end end if next_root.is_a? Hash diff(next_root, next_compared, lang1, lang2, new_structure, new_array, diff_counter: @diff_counter, diff_count: @diff_count, mode: @mode, slave_file: @slave_file) end end @mode == 'count' ? @diff_counter : new_array end
fully_automatic()
click to toggle source
# File lib/tasks/fully_automatic.rb, line 4 def self.fully_automatic tbd @master, @slave, paths = init prepare_for_edit(master: @master[:path], slave: @slave[:path]) prepare_paths([paths[:master], paths[:slave]]) master_file = YAML.load_file(paths[:master]) slave_file = YAML.load_file(paths[:slave]) count = diff(master_file[@master[:lang]], slave_file[@slave[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], mode: 'count') breakout unless ask_for_permission(@master, count, @slave) new_strings_array = diff(master_file[@master[:lang]], slave_file[@slave[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], diff_count: count, mode: 'replace') new_strings_array.each do |string| result = string_to_hash(string) merge_hash(result, slave_file) end File.open(paths[:slave], 'w') { |file| file.write(slave_file.to_yaml(line_width: -1)) } postpare_paths([paths[:slave]]) FileUtils.cp(paths[:slave], @slave[:path]) reset_tmp_files end
get_locale(path)
click to toggle source
# File lib/lit/difference.rb, line 38 def self.get_locale(path) path.split('/').last.split('.').first unless path.empty? end
half_automatic()
click to toggle source
# File lib/tasks/half_automatic.rb, line 4 def self.half_automatic tbd @master, @slave, paths = init prepare_for_edit(master: @master[:path], slave: @slave[:path]) prepare_paths([paths[:master], paths[:slave]]) master_file = YAML.load_file(paths[:master]) slave_file = YAML.load_file(paths[:slave]) count = diff(master_file[@master[:lang]], slave_file[@slave[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], mode: 'count') breakout unless ask_for_permission(@master, count, @slave) new_strings_array = diff(master_file[@master[:lang]], slave_file[@slave[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], diff_count: count, mode: 'replace') new_strings_array.each do |string| result = string_to_hash(string) merge_hash(result, slave_file) end File.open(paths[:slave], 'w') { |file| file.write(slave_file.to_yaml(line_width: -1)) } postpare_paths([paths[:slave]]) FileUtils.cp(paths[:slave], @slave[:path]) reset_tmp_files end
init(with_slave = true)
click to toggle source
# File lib/lost_in_translation.rb, line 32 def self.init(with_slave = true) system 'clear' log log 'What I18n-yaml files do you want to compare?' namespace = [(print "# Namespace? ('namespace' for 'namespace.en.yml'): "), Readline.readline()][1] master = ask_for_file(true, namespace) # lang path app_name slave = with_slave ? ask_for_file(false, namespace) : {} invalid_filepath if !File.exist?(master[:path]) && (!File.exist?(slave[:path]) && with_slave) [master, slave, tmp_paths] end
invalid_filepath()
click to toggle source
# File lib/lost_in_translation.rb, line 47 def self.invalid_filepath raise "One on the filepaths are invalid!" end
joke()
click to toggle source
# File lib/tasks/start.rb, line 30 def self.joke system 'clear' log log 'A: Knock, Knock!' log 'B: Who is there?' log 'A: Ya.' log 'B: Ya who?' log 'A: Oh, I prefer google.' log end
list_files()
click to toggle source
# File lib/tasks/start.rb, line 48 def self.list_files system 'clear' path = ask_for_locales_path files = Dir["#{path}/**/*.yml"] puts "No Files found in #{path}" if files.empty? files&.sort&.each do |file| puts file.split('/').last end start end
log(text = '')
click to toggle source
# File lib/lit/user_interface.rb, line 94 def self.log(text = '') max_length = 80 outside = 4 puts '#' * max_length if text.blank? arr = text.scan(/.{1,#{max_length - outside}}/) arr.each do |str| fill_length = max_length - str.length - outside fill = ' ' * fill_length puts '# ' + str + fill + ' #' end end
merge_hash(merge_from, merge_to)
click to toggle source
# File lib/lit/hash.rb, line 12 def self.merge_hash(merge_from, merge_to) return if merge_from.is_a?(String) || merge_to.is_a?(String) merged_hash = merge_to first_key = merge_from.keys.first merged_hash[first_key] = if merge_to.key?(first_key) merge_hash(merge_from[first_key], merge_to[first_key]) else merge_from[first_key] end merged_hash end
postpare_paths(paths = [])
click to toggle source
# File lib/lit/file_functions.rb, line 17 def self.postpare_paths(paths = []) paths.each do |p| prepare_yaml(p, true) end end
prepare_for_edit(options = {})
click to toggle source
# File lib/lit/file_functions.rb, line 5 def self.prepare_for_edit(options = {}) paths = tmp_paths FileUtils.cp(options[:master], paths[:master]) if options[:master] FileUtils.cp(options[:slave], paths[:slave]) if options[:slave] end
prepare_paths(paths = [])
click to toggle source
# File lib/lit/file_functions.rb, line 11 def self.prepare_paths(paths = []) paths.each do |p| prepare_yaml(p, false) end end
quit()
click to toggle source
# File lib/tasks/start.rb, line 41 def self.quit system 'clear' log log 'Thank you and goodbye!' log end
recent()
click to toggle source
# File lib/tasks/recent.rb, line 4 def self.recent @master, @slave, paths = init FileUtils.cp(@master[:path], paths[:copy]) `git checkout "#{@master[:path]}"` prepare_for_edit(master: @master[:path], slave: @slave[:path]) FileUtils.cp(paths[:copy], @master[:path]) prepare_paths([paths[:master], paths[:slave], paths[:copy]]) master_file = YAML.load_file(paths[:master]) master_copy_file = YAML.load_file(paths[:copy]) slave_file = YAML.load_file(paths[:slave]) count = diff(master_copy_file[@master[:lang]], master_file[@master[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], mode: 'count', slave_file: slave_file) breakout unless ask_for_permission(@master, count, @slave) new_strings_array = diff(master_copy_file[@master[:lang]], master_file[@master[:lang]], @master[:lang], @slave[:lang], [@slave[:lang]], [], mode: 'replace', diff_counter: 0, diff_count: count, slave_file: slave_file) new_strings_array.each do |string| result = string_to_hash(string) merge_hash(result, slave_file) end File.open(paths[:slave], 'w') { |file| file.write(slave_file.to_yaml(line_width: -1)) } postpare_paths([paths[:slave]]) FileUtils.cp(paths[:slave], @slave[:path]) reset_tmp_files log 'Done' log end
reset_tmp_files()
click to toggle source
# File lib/lit/file_functions.rb, line 33 def self.reset_tmp_files paths = tmp_paths paths.each_value do |path| File.open(path, 'w') { |file| file.write('') } end end
root()
click to toggle source
# File lib/lost_in_translation.rb, line 20 def self.root File.dirname __dir__ end
sort_file()
click to toggle source
# File lib/tasks/sort_file.rb, line 4 def self.sort_file @master, @slave, paths = init(false) prepare_for_edit(master: @master[:path], slave: @slave[:path]) prepare_paths([paths[:master]]) master_file = YAML.load_file(paths[:master]) if ask_for_sorting(@master[:lang], @master[:app_name]) master_file = sort_hash(master_file) File.open(paths[:master], 'w') { |file| file.write(master_file.to_yaml(line_width: -1)) } end postpare_paths([paths[:master]]) FileUtils.cp(paths[:master], @master[:path]) reset_tmp_files log 'Done' log end
sort_hash(object)
click to toggle source
# File lib/lit/hash.rb, line 24 def self.sort_hash(object) return object unless object.is_a?(Hash) hash = {} object.each { |k, v| hash[k] = sort_hash(v) } sorted = hash.sort { |a, b| a[0].to_s <=> b[0].to_s } hash.class[sorted] end
split_file()
click to toggle source
# File lib/tasks/split_file.rb, line 4 def self.split_file @master, @slave, paths = init(false) prepare_for_edit(master: @master[:path]) prepare_paths([paths[:master]]) master_file = YAML.load_file(paths[:master])[@master[:lang]] count = master_file.select { |_k, v| v.is_a?(Hash) }.size new_hash = {} if ask_for_split(@master[:lang], count) master_file.each_pair do |key, value| next unless value.is_a?(Hash) new_hash[@master[:lang]] = { key => value } File.open(paths[:slave], 'w') { |file| file.write(new_hash.to_yaml(line_width: -1)) } postpare_paths([paths[:slave]]) root_path = @master[:path].split('/').reverse.drop(1).reverse.join('/') filename = @master[:path].split('/').last FileUtils.cp(paths[:slave], "#{root_path}/#{key}.#{filename}") master_file.delete(key) end new_hash[@master[:lang]] = master_file File.open(paths[:master], 'w') { |file| file.write(new_hash.to_yaml(line_width: -1)) } postpare_paths([paths[:master]]) FileUtils.cp(paths[:master], @master[:path]) end reset_tmp_files log 'Done' log end
start()
click to toggle source
# File lib/tasks/start.rb, line 4 def self.start tasks = [ { text: 'Compare & Translate two I18n-Locale-Files', method: :start_compare }, { text: 'Count Differences of 2 I18n-Locale-Files', method: :count }, { text: 'Sort an I18n-Locale-File Alphabetically & Recursive (ASC)', method: :sort_file }, { text: 'Split an I18n-Locale-File into multiple namespaced Files (1. Level)', method: :split_file }, { text: 'Show a list of available I18n-Locale-Files', method: :list_files }, { text: 'Tell me joke', method: :joke }, { text: 'Quit', method: :quit } ] task = ask_for_task(tasks) LostInTranslation.send(task[:method]) end
start_compare()
click to toggle source
# File lib/tasks/start.rb, line 18 def self.start_compare tasks = [ { text: 'Compare everything', method: :compare }, { text: 'Just compare the recent changes (since last git commit)', method: :recent }, { text: 'Automatic translation via API', method: :fully_automatic }, { text: 'Translation suggentions from API', method: :half_automatic }, { text: 'Compare and delete the differences', method: :delete_missing }, ] task = ask_for_task(tasks) LostInTranslation.send(task[:method]) end
string_to_hash(string)
click to toggle source
# File lib/lit/hash.rb, line 5 def self.string_to_hash(string) array = string.split('---') value = array.pop arr = array.reverse arr[1..-1].inject(arr[0] => value) { |memo, i| { i => memo } } end
tbd()
click to toggle source
# File lib/lost_in_translation.rb, line 51 def self.tbd raise "This feature is not yet implemented! Please take another!" end
tmp_paths()
click to toggle source
# File lib/lost_in_translation.rb, line 24 def self.tmp_paths tmp_paths = {} tmp_paths[:copy] = "#{root}/tmp/tmp_master_copy.yml" tmp_paths[:master] = "#{root}/tmp/tmp_master.yml" tmp_paths[:slave] = "#{root}/tmp/tmp_slave.yml" tmp_paths end
value_missing(slave_file, structure)
click to toggle source
# File lib/lit/difference.rb, line 33 def self.value_missing(slave_file, structure) return true if slave_file.blank? slave_file.dig(*structure).blank? end
Private Class Methods
add_single_quotes(text)
click to toggle source
# File lib/lit/file_functions.rb, line 82 def self.add_single_quotes(text) tmp = '' text.each_line do |line| tmp += edit_line(line) end tmp end
ask_for_path()
click to toggle source
# File lib/lit/user_interface.rb, line 108 def self.ask_for_path log log 'Please type in the absolute path your locale?' log 'e.g. /home/youruser/Documents/your-awesome-app/config/locales/de.yml' path = [(print '# '), Readline.readline()][1] path end
edit_line(line)
click to toggle source
# File lib/lit/file_functions.rb, line 90 def self.edit_line(line) return line if line.match(/: .*%.*$/).blank? arr = line.split(': ', 2) return line if arr[1].blank? arr[1] = arr[1].gsub("\'", '') arr[1] = arr[1].gsub("\"", '') arr[1] = "'" + arr[1] unless arr[1].start_with?("\'") || arr[1].start_with?("\"") arr[1] = arr[1].squish + "'\n" unless arr[1].squish.end_with?("\'") || arr[1].squish.end_with?("\"") arr[1] = arr[1].gsub("\'! ", "! \'") return arr.join(': ') end
postpare(variables, text)
click to toggle source
# File lib/lit/file_functions.rb, line 56 def self.postpare(variables, text) variables = text.scan(/varyberryterry.*/) variables.each do |var| new_var = var.delete(':') new_var = new_var.gsub('varyberryterry', ': &') text = text.gsub(var, new_var) end text = add_single_quotes(text) text = text.gsub(': !,', ": ! ','") text = text.gsub('\'!', '! \'') text = text.gsub(/---\n/, '') text = text.gsub('!…', "! '…'") text = text.gsub('!:distance_in_words', "! ':distance_in_words'") text end
prepare(variables, text)
click to toggle source
# File lib/lit/file_functions.rb, line 72 def self.prepare(variables, text) variables = text.scan(/: &.*/) variables.each do |var| new_var = var.gsub(': &', 'varyberryterry') new_var += ':' text = text.gsub(var, new_var) end text end
prepare_yaml(path, post)
click to toggle source
# File lib/lit/file_functions.rb, line 42 def self.prepare_yaml(path, post) text = File.read(path) snippets = define_snippets snippets = snippets.reverse if post snippets.each do |snippet| snippet = snippet.reverse if post text = text.gsub(snippet.first, snippet.second) end text = post ? postpare(snippets, text) : prepare(snippets, text) File.open(path, 'w') { |file| file.puts text } end