Module: LostInTranslation

Included in:
Lit
Defined in:
lib/lost_in_translation.rb,
lib/lost_in_translation/hash.rb,
lib/lost_in_translation/railtie.rb,
lib/lost_in_translation/version.rb,
lib/lost_in_translation/z_recent.rb,
lib/lost_in_translation/z_cleanup.rb,
lib/lost_in_translation/difference.rb,
lib/lost_in_translation/z_interactive.rb,
lib/lost_in_translation/file_functions.rb,
lib/lost_in_translation/user_interface.rb,
lib/lost_in_translation/z_full_automatic.rb,
lib/lost_in_translation/z_half_automatic.rb

Defined Under Namespace

Classes: Railtie

Constant Summary collapse

VERSION =
'0.2.16'

Class Method Summary collapse

Class Method Details

.ask_for_file(master) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/lost_in_translation/user_interface.rb', line 7

def self.ask_for_file(master)
  text = master ? "# Master (e.g. 'en'): " : "# Slave: (e.g. 'de'): "
  file = {}
  file[:lang] = [(print text), Readline.readline()][1]
  file[:path] = defined?(Rails) ? "#{Rails.root}/config/locales/#{file[:lang]}.yml" : ask_for_path
  unless File.exist?(file[:path])
    log "File #{file[:path]} not found!"
    file[:path] = ask_for_path
  end
  file[:app_name] = Rails&.application&.class&.parent_name
  file
end

.ask_for_permission(lang1, lang2, app_name, count) ⇒ Object



20
21
22
23
24
25
26
27
28
29
# File 'lib/lost_in_translation/user_interface.rb', line 20

def self.ask_for_permission(lang1, lang2, app_name, count)
  log
  log 'Comparing Locales'
  log "Application: #{app_name}" unless app_name.nil?
  log "Master Locale: #{lang1}.yml"
  log "Slave Locale: #{lang2}.yml"
  log "Difference: #{count} Entries"
  a = [(print "# Wanna do it? [Y/n]: "), Readline.readline()][1]
  a == 'y' || a == 'Y' || a == ''
end

.ask_for_sorting(lang, app_name) ⇒ Object



31
32
33
34
35
36
37
38
# File 'lib/lost_in_translation/user_interface.rb', line 31

def self.ask_for_sorting(lang, app_name)
  log
  log "Application: #{app_name}"
  log "Do you want the #{lang}.yml to be sorted?"
  log 'Alphabetically & Recursive (ASC)'
  a = [(print "# [y/N]: "), Readline.readline()][1]
  a == 'y' || a == 'Y'
end

.ask_for_translation(value, new_structure, lang1, lang2, diff_count, diff_counter) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/lost_in_translation/user_interface.rb', line 40

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

.cleanupObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/lost_in_translation/z_cleanup.rb', line 5

def self.cleanup
  system 'clear'
  log
  log 'What I18n-yaml files do you want to compare?'
  log '!!! WARNING!!! This deletes the differences!!! Make a BACKUP!!! !!!'
  @master = ask_for_file(true) # lang path app_name
  @slave = ask_for_file(false)
  paths = tmp_paths

  raise 'Invalid Filepaths' unless File.exist?(@master[:path]) && File.exist?(@slave[:path])

  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])

  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
end

.define_snippetsObject



23
24
25
26
27
28
29
30
31
# File 'lib/lost_in_translation/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

.diff(root, compared, lang1, lang2, structure = [], new_array = [], options = {}) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/lost_in_translation/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

.full_automaticObject



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/lost_in_translation/z_full_automatic.rb', line 2

def self.full_automatic
  if defined? Rails
    lang2, lang1 = LostInTranslation.ask_for_languages
    path1 = "#{Rails.root}/config/locales/#{lang1}.yml"
    path2 = "#{Rails.root}/config/locales/#{lang2}.yml"
  else
    path2, path1 = LostInTranslation.ask_for_paths

    lang1 = LostInTranslation.get_locale(path1)
    lang2 = LostInTranslation.get_locale(path2)
  end

  abort('NOPE') unless File.exist?(path1) && File.exist?(path2)

  first = YAML.load_file(path1)
  second = YAML.load_file(path2)

  new_strings_array = LostInTranslation.clean(first[lang1], second[lang2], [lang2])

  first = {}
  new_strings_array.each do |string|
    string = string.split('---').map { |x| x == lang2 ? lang1 : x }.join('---')
    result = LostInTranslation.string_to_hash(string)
    LostInTranslation.merge_hash(result, first)
  end

  File.open(path1, 'w') { |file| file.write(first.to_yaml) }
end

.get_locale(path) ⇒ Object



38
39
40
# File 'lib/lost_in_translation/difference.rb', line 38

def self.get_locale(path)
  path.split('/').last.split('.').first unless path.empty?
end

.half_automaticObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/lost_in_translation/z_half_automatic.rb', line 5

def self.half_automatic
  if defined? Rails
    lang2, lang1 = LostInTranslation.ask_for_languages
    path1 = "#{Rails.root}/config/locales/#{lang1}.yml"
    path2 = "#{Rails.root}/config/locales/#{lang2}.yml"
  else
    path2, path1 = LostInTranslation.ask_for_paths

    lang1 = LostInTranslation.get_locale(path1)
    lang2 = LostInTranslation.get_locale(path2)
  end

  abort('NOPE') unless File.exist?(path1) && File.exist?(path2)

  first = YAML.load_file(path1)
  second = YAML.load_file(path2)

  new_strings_array = LostInTranslation.clean(first[lang1], second[lang2], [lang2])

  first = {}
  new_strings_array.each do |string|
    string = string.split('---').map { |x| x == lang2 ? lang1 : x }.join('---')
    result = LostInTranslation.string_to_hash(string)
    LostInTranslation.merge_hash(result, first)
  end

  File.open(path1, 'w') { |file| file.write(first.to_yaml) }
end

.interactiveObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/lost_in_translation/z_interactive.rb', line 5

def self.interactive
  system 'clear'
  log
  log 'What I18n-yaml files do you want to compare?'
  @master = ask_for_file(true) # lang path app_name
  @slave = ask_for_file(false)
  raise 'Invalid Filepaths' unless File.exist?(@master[:path]) && File.exist?(@slave[:path])

  paths = tmp_paths

  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')

  unless ask_for_permission(@master[:lang], @slave[:lang], @master[:app_name], count)
    abort('Well, in that case, forget it!')
  end

  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

  sorted = false

  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)) }
    sorted = true
  end
  slave_file = sort_hash(slave_file) if ask_for_sorting(@slave[:lang], @slave[:app_name])
  File.open(paths[:slave], 'w') { |file| file.write(slave_file.to_yaml(line_width: -1)) }

  postpare_paths([paths[:master], paths[:slave]])

  FileUtils.cp(paths[:master], @master[:path]) if sorted
  FileUtils.cp(paths[:slave], @slave[:path])
  reset_tmp_files
end

.log(text = '') ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/lost_in_translation/user_interface.rb', line 58

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) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/lost_in_translation/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 = []) ⇒ Object



17
18
19
20
21
# File 'lib/lost_in_translation/file_functions.rb', line 17

def self.postpare_paths(paths = [])
  paths.each do |p|
    prepare_yaml(p, true)
  end
end

.prepare_for_edit(options = {}) ⇒ Object



5
6
7
8
9
# File 'lib/lost_in_translation/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 = []) ⇒ Object



11
12
13
14
15
# File 'lib/lost_in_translation/file_functions.rb', line 11

def self.prepare_paths(paths = [])
  paths.each do |p|
    prepare_yaml(p, false)
  end
end

.recentObject



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/lost_in_translation/z_recent.rb', line 4

def self.recent
  system 'clear'
  log
  log 'What I18n-yaml files do you want to compare?'
  @master = ask_for_file(true) # lang path app_name
  @slave = ask_for_file(false)
  paths = tmp_paths

  raise 'Invalid Filepaths' unless File.exist?(@master[:path]) && File.exist?(@slave[:path])

  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)

  abort('Well, in that case, forget it!') unless ask_for_permission(@master[:lang], @slave[:lang], @master[:app_name], count)

  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

  sorted = false

  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)) }
    sorted = true
  end

  slave_file = sort_hash(slave_file) if ask_for_sorting(@slave[:lang], @slave[:app_name])
  File.open(paths[:slave], 'w') { |file| file.write(slave_file.to_yaml(line_width: -1)) }

  postpare_paths([paths[:master], paths[:slave]])

  FileUtils.cp(paths[:master], @master[:path]) if sorted
  FileUtils.cp(paths[:slave], @slave[:path])
  reset_tmp_files
end

.reset_tmp_filesObject



33
34
35
36
37
38
# File 'lib/lost_in_translation/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

.rootObject



17
18
19
# File 'lib/lost_in_translation.rb', line 17

def self.root
  File.dirname __dir__
end

.sort_hash(object) ⇒ Object



24
25
26
27
28
29
30
# File 'lib/lost_in_translation/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

.string_to_hash(string) ⇒ Object



5
6
7
8
9
10
# File 'lib/lost_in_translation/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

.tmp_pathsObject



21
22
23
24
25
26
27
# File 'lib/lost_in_translation.rb', line 21

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) ⇒ Object



33
34
35
36
# File 'lib/lost_in_translation/difference.rb', line 33

def self.value_missing(slave_file, structure)
  return true if slave_file.blank?
  slave_file.dig(*structure).blank?
end