i18n-verify 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.md +19 -2
- data/Rakefile +5 -0
- data/i18n-verify.gemspec +1 -1
- data/lib/i18n-verify/support.rb +74 -34
- data/lib/tasks/verify.rake +107 -94
- metadata +4 -4
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -24,6 +24,7 @@ i18n-verify is a set of rake tasks:
|
|
24
24
|
* `rake i18n:find_key` for finding keys
|
25
25
|
* `rake i18n:is_complete` for checking if translations are complete
|
26
26
|
* `rake i18n:duplicates` for finding keys with more than one translation for any given locale
|
27
|
+
* `rake i18n:spell` for checking translation misspellings
|
27
28
|
|
28
29
|
All of them will automatically pick up translation files configured for i18n (both yml and rb).
|
29
30
|
|
@@ -73,11 +74,27 @@ Examples:
|
|
73
74
|
* `rake i18n:duplicates`
|
74
75
|
* `rake i18n:duplicates locales=en`
|
75
76
|
|
77
|
+
i18n:spell
|
78
|
+
----------
|
79
|
+
|
80
|
+
It checks for translation misspellings.
|
81
|
+
|
82
|
+
rake i18n:spell [locales=<list>]
|
83
|
+
|
84
|
+
`locales` defaults to all and should be a comma separated list with no spaces.
|
85
|
+
|
86
|
+
Please note that spelling requires aspell to be installed with all the dictionaries spelling is requested for.
|
87
|
+
|
88
|
+
Examples:
|
89
|
+
|
90
|
+
* `rake i18n:spell`
|
91
|
+
* `rake i18n:spell locales=en,fr`
|
92
|
+
|
76
93
|
To do
|
77
94
|
=====
|
78
95
|
|
79
|
-
* Add spell checking support
|
80
96
|
* Write tests (tests for rake tasks, that is!)
|
97
|
+
* More intelligent handling of spelling errors with a dictionary for accepted exceptions
|
81
98
|
* ...
|
82
99
|
|
83
100
|
Contributing to i18n-verify
|
@@ -94,4 +111,4 @@ Contributing to i18n-verify
|
|
94
111
|
Copyright
|
95
112
|
=========
|
96
113
|
|
97
|
-
Copyright (c) 2011 fastcatch. See LICENSE
|
114
|
+
Copyright (c) 2011 fastcatch. See the LICENSE file for further details.
|
data/Rakefile
CHANGED
data/i18n-verify.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "i18n-verify"
|
5
5
|
s.homepage = "http://github.com/fastcatch/i18n-verify"
|
6
|
-
s.version = "0.0.
|
6
|
+
s.version = "0.0.5"
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.summary = %Q{Tools to verify your Ruby on Rails localizations}
|
9
9
|
s.description = %Q{It helps you find keys, undefined translations, duplicate keys, and more}
|
data/lib/i18n-verify/support.rb
CHANGED
@@ -1,7 +1,57 @@
|
|
1
1
|
module I18nVerify
|
2
|
+
|
3
|
+
class Translations < Array
|
4
|
+
def initialize(filenames)
|
5
|
+
# read files and store translations (similar to i18n's internals but include filenames)
|
6
|
+
filenames.each do |filename|
|
7
|
+
# puts "Loading: #{filename}"
|
8
|
+
type = File.extname(filename).tr('.', '').downcase.to_sym
|
9
|
+
case type
|
10
|
+
when :rb
|
11
|
+
data = eval IO.read(filename) # , binding, filename)
|
12
|
+
when :yml
|
13
|
+
data = YAML.load_file(filename)
|
14
|
+
else
|
15
|
+
raise I18n::UnknownFileType.new(type, filename)
|
16
|
+
end
|
17
|
+
raise I18n::InvalidLocaleData.new(filename) unless data.is_a?(Hash)
|
18
|
+
data.each_pair do |locale, d|
|
19
|
+
flatten_keys(d || {}) do |flat_key, translation|
|
20
|
+
self.push({ :filename => filename, :locale => locale.to_s, :key => flat_key, :translation => translation })
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def select(*args, &block)
|
27
|
+
if block_given?
|
28
|
+
super &block
|
29
|
+
else
|
30
|
+
options = args.extract_options!
|
31
|
+
super {|h| options.all?{|key,value| h[key] == value} }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
# convert translations hash to flat keys
|
37
|
+
# i.e. from { :de => {:new => neue, :old => alt} } to [ ['de.new', 'neue'], ['de.old', 'alte'] ]
|
38
|
+
# and yields a flat key and the value to the block
|
39
|
+
def flatten_keys(hash, prev_key=nil, &block)
|
40
|
+
hash.each_pair do |key, value|
|
41
|
+
curr_key = [prev_key, key].compact.join('.')
|
42
|
+
if value.is_a?(Hash)
|
43
|
+
flatten_keys(value, curr_key, &block)
|
44
|
+
else
|
45
|
+
yield curr_key, value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
2
52
|
class Checker
|
3
53
|
def initialize(filenames)
|
4
|
-
@translations =
|
54
|
+
@translations = Translations.new(filenames)
|
5
55
|
end
|
6
56
|
|
7
57
|
def find_key(regexp=Regexp.new(''), group_by_filename=false)
|
@@ -66,43 +116,33 @@ module I18nVerify
|
|
66
116
|
end
|
67
117
|
end
|
68
118
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
# and yields a flat key and the value to the block
|
73
|
-
def flatten_keys(hash, prev_key=nil, &block)
|
74
|
-
hash.each_pair do |key, value|
|
75
|
-
curr_key = [prev_key, key].compact.join('.')
|
76
|
-
if value.is_a?(Hash)
|
77
|
-
flatten_keys(value, curr_key, &block)
|
78
|
-
else
|
79
|
-
yield curr_key, value
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
119
|
+
def spell(locales_requested = [])
|
120
|
+
locales = @translations.collect{|tr| tr[:locale]}.uniq
|
121
|
+
locales_to_check = locales_requested.empty? ? locales : (locales & locales_requested)
|
83
122
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
123
|
+
puts "Checking spelling in locales #{locales_to_check.inspect} out of #{locales.inspect}"
|
124
|
+
|
125
|
+
# take each translation in turn and check spelling
|
126
|
+
@translations.each do |translation|
|
127
|
+
next unless locales_to_check.include? translation[:locale] # skip if in a locale not to be checked
|
128
|
+
|
129
|
+
text = translation[:translation]
|
130
|
+
next unless text.is_a? String # skip if not a string (perhaps an array?)
|
131
|
+
text.gsub!(/%\{[^}]*\}/, "") # remove translation params
|
132
|
+
|
133
|
+
# make aspell check the spelling
|
134
|
+
result = %x[echo "#{text}" | aspell -a --ignore-case --lang="#{translation[:locale]}" --dont-suggest]
|
135
|
+
|
136
|
+
# process result
|
137
|
+
# aspell returns lines in the format of '# <word> <position>' for each misspelled word
|
138
|
+
result.lines do |line|
|
139
|
+
parts = line.split(" ")
|
140
|
+
if parts[0]=='#' # misspelling found
|
141
|
+
# print: misspelled word | file | (full) key | position
|
142
|
+
puts "#{parts[1]} | #{translation[:filename]} | #{[translation[:locale],translation[:key]].join('.')} | #{parts[2]}"
|
102
143
|
end
|
103
144
|
end
|
104
145
|
end
|
105
|
-
translations
|
106
146
|
end
|
107
147
|
|
108
148
|
end
|
data/lib/tasks/verify.rake
CHANGED
@@ -1,95 +1,108 @@
|
|
1
|
-
namespace :i18n do
|
2
|
-
|
3
|
-
#
|
4
|
-
# find_key helps to find where certain (partial) keys have translations
|
5
|
-
#
|
6
|
-
# the first parameter is a regexp to look for (beware of period separators!)
|
7
|
-
# the second parameter is a flag if results are to be grouped by file
|
8
|
-
# (the default is one match per line with filename included)
|
9
|
-
#
|
10
|
-
# Examples:
|
11
|
-
# rake find_key[/models/]
|
12
|
-
# rake find_key[/\.models\.attributes/,true]
|
13
|
-
#
|
14
|
-
desc "Find translation keys matching a regexp"
|
15
|
-
task :find_key, :regexp, :group_by_filename do |t, args|
|
16
|
-
require "#{::Rails.root.to_s}/config/environment.rb"
|
17
|
-
regexp = Regexp.new(args[:regexp] || "")
|
18
|
-
group_by_filename = args[:group_by_filename]
|
19
|
-
checker = I18nVerify::Checker.new(I18n.config.load_path)
|
20
|
-
checker.find_key(regexp,group_by_filename)
|
21
|
-
end
|
22
|
-
|
23
|
-
#
|
24
|
-
# is_complete helps in checking if all translations are set up in all directions
|
25
|
-
# that is: verifies there are no missing keys in any of the trasnlations
|
26
|
-
#
|
27
|
-
# is_complete takes a command line rake param: the list of locales to check (all pairs)
|
28
|
-
# omit for all
|
29
|
-
#
|
30
|
-
# Examples:
|
31
|
-
# rake i18n:is_complete
|
32
|
-
# rake i18n:is_complete locales=en,de
|
33
|
-
#
|
34
|
-
desc "Checks if translations are complete or there are missing ones"
|
35
|
-
task :is_complete do |t, args|
|
36
|
-
require "#{::Rails.root.to_s}/config/environment.rb"
|
37
|
-
locales_requested = (ENV['locales'] || "").downcase.split(',')
|
38
|
-
checker = I18nVerify::Checker.new(I18n.config.load_path)
|
39
|
-
checker.is_complete?(locales_requested)
|
40
|
-
end
|
41
|
-
|
42
|
-
#
|
43
|
-
# duplicates helps in finding keys with multiple translations to the same locale
|
44
|
-
#
|
45
|
-
#
|
46
|
-
# omit for all
|
47
|
-
#
|
48
|
-
# Examples:
|
49
|
-
# rake i18n:duplicates
|
50
|
-
# rake i18n:duplicates locales=en,de
|
51
|
-
#
|
52
|
-
desc "Checks if any keys are translated multiple times"
|
53
|
-
task :duplicates do |t, args|
|
54
|
-
require "#{::Rails.root.to_s}/config/environment.rb"
|
55
|
-
locales_requested = (ENV['locales'] || "").downcase.split(',')
|
56
|
-
checker = I18nVerify::Checker.new(I18n.config.load_path)
|
57
|
-
checker.duplicates(locales_requested)
|
58
|
-
end
|
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
|
-
|
1
|
+
namespace :i18n do
|
2
|
+
|
3
|
+
#
|
4
|
+
# find_key helps to find where certain (partial) keys have translations
|
5
|
+
#
|
6
|
+
# the first parameter is a regexp to look for (beware of period separators!)
|
7
|
+
# the second parameter is a flag if results are to be grouped by file
|
8
|
+
# (the default is one match per line with filename included)
|
9
|
+
#
|
10
|
+
# Examples:
|
11
|
+
# rake find_key[/models/]
|
12
|
+
# rake find_key[/\.models\.attributes/,true]
|
13
|
+
#
|
14
|
+
desc "Find translation keys matching a regexp"
|
15
|
+
task :find_key, :regexp, :group_by_filename do |t, args|
|
16
|
+
require "#{::Rails.root.to_s}/config/environment.rb"
|
17
|
+
regexp = Regexp.new(args[:regexp] || "")
|
18
|
+
group_by_filename = args[:group_by_filename]
|
19
|
+
checker = I18nVerify::Checker.new(I18n.config.load_path)
|
20
|
+
checker.find_key(regexp,group_by_filename)
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# is_complete helps in checking if all translations are set up in all directions
|
25
|
+
# that is: verifies there are no missing keys in any of the trasnlations
|
26
|
+
#
|
27
|
+
# is_complete takes a command line rake param: the list of locales to check (all pairs)
|
28
|
+
# omit for all
|
29
|
+
#
|
30
|
+
# Examples:
|
31
|
+
# rake i18n:is_complete
|
32
|
+
# rake i18n:is_complete locales=en,de
|
33
|
+
#
|
34
|
+
desc "Checks if translations are complete or there are missing ones"
|
35
|
+
task :is_complete do |t, args|
|
36
|
+
require "#{::Rails.root.to_s}/config/environment.rb"
|
37
|
+
locales_requested = (ENV['locales'] || "").downcase.split(',')
|
38
|
+
checker = I18nVerify::Checker.new(I18n.config.load_path)
|
39
|
+
checker.is_complete?(locales_requested)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# duplicates helps in finding keys with multiple translations to the same locale
|
44
|
+
#
|
45
|
+
# duplicates takes a command line rake param: the list of locales to check
|
46
|
+
# omit for all
|
47
|
+
#
|
48
|
+
# Examples:
|
49
|
+
# rake i18n:duplicates
|
50
|
+
# rake i18n:duplicates locales=en,de
|
51
|
+
#
|
52
|
+
desc "Checks if any keys are translated multiple times"
|
53
|
+
task :duplicates do |t, args|
|
54
|
+
require "#{::Rails.root.to_s}/config/environment.rb"
|
55
|
+
locales_requested = (ENV['locales'] || "").downcase.split(',')
|
56
|
+
checker = I18nVerify::Checker.new(I18n.config.load_path)
|
57
|
+
checker.duplicates(locales_requested)
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# spell helps checking translation spelling
|
62
|
+
#
|
63
|
+
# note: it requires aspell and the proper dictionaries installed
|
64
|
+
#
|
65
|
+
# spell takes a command line rake param: the list of locales to check
|
66
|
+
# omit for all
|
67
|
+
#
|
68
|
+
# Examples:
|
69
|
+
# rake i18n:spell
|
70
|
+
# rake i18n:spell locales=en,de
|
71
|
+
#
|
72
|
+
desc "Checks translations for spelling errors"
|
73
|
+
task :spell do |t, args|
|
74
|
+
require "#{::Rails.root.to_s}/config/environment.rb"
|
75
|
+
locales_requested = (ENV['locales'] || "").downcase.split(',')
|
76
|
+
checker = I18nVerify::Checker.new(I18n.config.load_path)
|
77
|
+
checker.spell(locales_requested)
|
78
|
+
end
|
79
|
+
|
80
|
+
desc "Run all checks"
|
81
|
+
task :verify => [:is_complete, :duplicates, :spell] do
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# BONUS :)
|
88
|
+
#
|
89
|
+
namespace :yaml do
|
90
|
+
desc "Finds keys in yaml files; regexp to match keys; command line: rake yaml:find[config/locales/**/*.yml,/\.models\./]"
|
91
|
+
task :find, :filename_pattern, :regexp, :group_by_filename do |t, args|
|
92
|
+
filenames = Dir[args[:filename_pattern] || Rails.root.join('**', '*.{yaml,yml}').to_s]
|
93
|
+
regexp = Regexp.new(args[:regexp] || "")
|
94
|
+
group_by_filename = args[:group_by_filename]
|
95
|
+
|
96
|
+
filenames.each do |filename|
|
97
|
+
print filename + ":\n" if group_by_filename
|
98
|
+
|
99
|
+
File.open( filename ) do |infile|
|
100
|
+
yaml_hash = YAML::parse(infile).transform
|
101
|
+
flatten_keys( yaml_hash ) do |key, value|
|
102
|
+
puts "#{group_by_filename ? '' : (filename + ' #')} #{key}: #{value}\n" if key =~ regexp
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
95
108
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-verify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- fastcatch
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-20 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|