i18n-verify 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|