summaryrefslogtreecommitdiffstats
path: root/lib/tasks/locales.rake
blob: 952f8f6de66facac5bd270fbe4d2f1eeb86dcfc6 (plain)
1
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
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
desc 'Updates and checks locales against en.yml'
task :locales do
  %w(locales:update locales:check_interpolation).collect do |task|
    Rake::Task[task].invoke
  end
end

namespace :locales do
  desc 'Updates language files based on en.yml content (only works for new top level keys).'
  task :update do
    dir = ENV['DIR'] || './config/locales'

    en_strings = YAML.load(File.read(File.join(dir,'en.yml')))['en']

    files = Dir.glob(File.join(dir,'*.{yaml,yml}'))
    files.sort.each do |file|
      puts "Updating file #{file}"
      file_strings = YAML.load(File.read(file))
      file_strings = file_strings[file_strings.keys.first]

      missing_keys = en_strings.keys - file_strings.keys
      next if missing_keys.empty?

      puts "==> Missing #{missing_keys.size} keys (#{missing_keys.join(', ')})"
      lang = File.open(file, 'a')

      missing_keys.each do |key|
        {key => en_strings[key]}.to_yaml.each_line do |line|
          next if line =~ /^---/ || line.empty?
          puts "  #{line}"
          lang << "  #{line}"
        end
      end

      lang.close
    end
  end

  desc 'Checks interpolation arguments in locals against en.yml'
  task :check_interpolation do
    dir = ENV['DIR'] || './config/locales'
    en_strings = YAML.load(File.read(File.join(dir,'en.yml')))['en']
    files = Dir.glob(File.join(dir,'*.{yaml,yml}'))
    files.sort.each do |file|
      puts "parsing #{file}..."
      file_strings = YAML.load_file(file)
      unless file_strings.is_a?(Hash)
        puts "#{file}: content is not a Hash (#{file_strings.class.name})"
        next
      end
      unless file_strings.keys.size == 1
        puts "#{file}: content has multiple keys (#{file_strings.keys.size})"
        next
      end
      file_strings = file_strings[file_strings.keys.first]

      file_strings.each do |key, string|
        next unless string.is_a?(String)
        string.scan /%\{\w+\}/ do |match|
          unless en_strings[key].nil? || en_strings[key].include?(match)
            puts "#{file}: #{key} uses #{match} not found in en.yml"
          end
        end
      end
    end
  end

  desc <<-END_DESC
Removes a translation string from all locale file (only works for top-level childless non-multiline keys, probably doesn\'t work on windows).

Options:
  key=key_1,key_2    Comma-separated list of keys to delete
  skip=en,de         Comma-separated list of locale files to ignore (filename without extension)
END_DESC

  task :remove_key do
    dir = ENV['DIR'] || './config/locales'
    files = Dir.glob(File.join(dir,'*.yml'))
    skips = ENV['skip'] ? Regexp.union(ENV['skip'].split(',')) : nil
    deletes = ENV['key'] ? Regexp.union(ENV['key'].split(',')) : nil
    # Ignore multiline keys (begin with | or >) and keys with children (nothing meaningful after :)
    delete_regex = /\A  #{deletes}: +[^\|>\s#].*\z/

    files.each do |path|
      # Skip certain locales
      (puts "Skipping #{path}"; next) if File.basename(path, ".yml") =~ skips
      puts "Deleting selected keys from #{path}"
      orig_content = File.open(path, 'r') {|file| file.read}
      File.open(path, 'w') {|file| orig_content.each_line {|line| file.puts line unless line.chomp =~ delete_regex}}
    end
  end

  desc <<-END_DESC
Adds a new top-level translation string to all locale file (only works for childless keys, probably doesn\'t work on windows, doesn't check for duplicates).

Options:
  key="some_key=foo"
  key1="another_key=bar"
  key_fb="foo=bar"         Keys to add in the form key=value, every option of the form key[,\\d,_*] will be recognised
  skip=en,de               Comma-separated list of locale files to ignore (filename without extension)
END_DESC

  task :add_key do
    dir = ENV['DIR'] || './config/locales'
    files = Dir.glob(File.join(dir,'*.yml'))
    skips = ENV['skip'] ? Regexp.union(ENV['skip'].split(',')) : nil
    keys_regex = /\Akey(\d+|_.+)?\z/
    adds = ENV.reject {|k,v| !(k =~ keys_regex)}.values.collect {|v| Array.new v.split("=",2)}
    key_list = adds.collect {|v| v[0]}.join(", ")

    files.each do |path|
      # Skip certain locales
      (puts "Skipping #{path}"; next) if File.basename(path, ".yml") =~ skips
      # TODO: Check for duplicate/existing keys
      puts "Adding #{key_list} to #{path}"
      File.open(path, 'a') do |file|
        adds.each do |kv|
          Hash[*kv].to_yaml.each_line do |line|
            file.puts "  #{line}" unless (line =~ /^---/ || line.empty?)
          end
        end
      end
    end
  end

  desc 'Duplicates a key. Exemple rake locales:dup key=foo new_key=bar'
  task :dup do
    dir = ENV['DIR'] || './config/locales'
    files = Dir.glob(File.join(dir,'*.yml'))
    skips = ENV['skip'] ? Regexp.union(ENV['skip'].split(',')) : nil
    key = ENV['key']
    new_key = ENV['new_key']
    abort "Missing key argument" if key.blank?
    abort "Missing new_key argument" if new_key.blank?

    files.each do |path|
      # Skip certain locales
      (puts "Skipping #{path}"; next) if File.basename(path, ".yml") =~ skips
      puts "Adding #{new_key} to #{path}"

      strings = File.read(path)
      unless strings =~ /^(  #{key}: .+)$/
        puts "Key not found in #{path}"
        next
      end
      line = $1

      File.open(path, 'a') do |file|
        file.puts(line.sub(key, new_key))
      end
    end
  end

  desc 'Check parsing yaml by psych library on Ruby 1.9.'

  # On Fedora 12 and 13, if libyaml-devel is available,
  # in case of installing by rvm,
  # Ruby 1.9 default yaml library is psych.

  task :check_parsing_by_psych do
    begin
      require 'psych'
      parser = Psych::Parser.new
      dir = ENV['DIR'] || './config/locales'
      files = Dir.glob(File.join(dir,'*.yml'))
      files.sort.each do |filename|
        next if File.directory? filename
        puts "parsing #{filename}..."
        begin
          parser.parse File.open(filename)
        rescue => e1
          puts(e1.message)
          puts("")
        end
      end
    rescue => e
      puts(e.message)
    end
  end
end