i18n-verify 0.0.1 → 0.0.2

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.
@@ -0,0 +1,11 @@
1
+ require 'i18n_verify'
2
+ require 'rails'
3
+ module I18nVerify
4
+ class Railtie < Rails::Railtie
5
+ railtie_name :i18n_verify
6
+
7
+ rake_tasks do
8
+ load "tasks/i18n_verify.rake"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,111 @@
1
+ # the user interface is in rake tasks
2
+ # for more info see lib/tasks/i18n-verify.rake
3
+
4
+ module I18nVerfiy
5
+
6
+ require 'i18n-verify/railtie' if defined?(Rails)
7
+
8
+ class Checker
9
+ def initialize(filenames = )
10
+ @translations = load_files(filenames)
11
+ end
12
+
13
+ def find_key(match=Regexp,new(''), group_by_filename=false)
14
+ # select translations with matching keys
15
+ matching_translations = @translations.select {|t| [t[:locale],t[:key]].join('.') =~ regexp}
16
+
17
+ # print matching translations
18
+ if group_by_filename
19
+ matching_translations.group_by {|t| t[:filename]}.each_pair do |filename, translations|
20
+ puts "#{filename}:"
21
+ translations.each do |t|
22
+ puts " #{[t[:locale],t[:key]].join('.')}: #{t[:translation]}\n"
23
+ end
24
+ end
25
+ else
26
+ matching_translations.each do |t|
27
+ puts "#{t[:filename]} # #{[t[:locale],t[:key]].join('.')}: #{t[:translation]}\n"
28
+ end
29
+ end
30
+ end
31
+
32
+ def is_complete?(locales_requested = [])
33
+ # check each pair of locales
34
+ # if the first one has keys the second one doesn't => these are the incomplete translations
35
+ locales = @translations.collect{|tr| tr[:locale]}.uniq
36
+ locales_to_check = locales_requested.empty? ? locales : (locales & locales_requested)
37
+
38
+ puts "Checking locales #{locales_to_check.inspect} out of #{locales.inspect} for completeness"
39
+ locales_to_check.permutation.each do |first, second|
40
+ first_translations = @translations.select {|translation| translation[:locale] == first}
41
+ second_translations = @translations.select {|translation| translation[:locale] == second}
42
+
43
+ differences = first_translations.select {|f| f if second_translations.none? {|s| f[:key]==s[:key]} }.compact
44
+ if differences.empty?
45
+ puts "#{first} => #{second}: complete\n"
46
+ else
47
+ puts "Missing from #{second} vs. #{first}:\n"
48
+ differences.each do |difference|
49
+ puts " " + [difference[:locale], difference[:key]].join('.') + " defined for #{first} in #{difference[:filename]}\n"
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def duplicates(locales_requested = [])
56
+ locales = @translations.collect{|tr| tr[:locale]}.uniq
57
+ locales_to_check = locales_requested.empty? ? locales : (locales & locales_requested)
58
+
59
+ puts "Checking locales #{locales_to_check.inspect} out of #{locales.inspect} for redundancy"
60
+
61
+ # collect and print duplicate translations
62
+ locales_to_check.each do |locale|
63
+ puts "#{locale}:"
64
+ translations_by_key = @translations.select {|t| t[:locale] == locale}.uniq.group_by {|t| t[:key]}
65
+ translations_by_key.reject {|t| t[1].count == 1}.each_pair do |key, translations|
66
+ puts " #{key}: #{translations.collect{|t| t[:filename]}.join(", ")}"
67
+ end
68
+ end
69
+ end
70
+
71
+ protected
72
+ # convert translations hash to flat keys
73
+ # i.e. from { :de => {:new => neue, :old => alt} } to [ ['de.new', 'neue'], ['de.old', 'alte'] ]
74
+ # and yields a flat key and the value to the block
75
+ def flatten_keys(hash, prev_key=nil, &block)
76
+ hash.each_pair do |key, value|
77
+ curr_key = [prev_key, key].compact.join('.')
78
+ if value.is_a?(Hash)
79
+ flatten_keys(value, curr_key, &block)
80
+ else
81
+ yield curr_key, value
82
+ end
83
+ end
84
+ end
85
+
86
+ # read files and store translations (similar to i18n's internals but include filenames)
87
+ def load_files(filenames)
88
+ translations = []
89
+ filenames.each do |filename|
90
+ type = File.extname(filename).tr('.', '').downcase.to_sym
91
+ case type
92
+ when :rb
93
+ data = eval IO.read(filename) # , binding, filename)
94
+ when :yml
95
+ data = YAML.load_file(filename)
96
+ else
97
+ raise I18n::UnknownFileType.new(type, filename)
98
+ end
99
+ raise I18n::InvalidLocaleData.new(filename) unless data.is_a?(Hash)
100
+ data.each_pair do |locale, d|
101
+ flatten_keys(d || {}) do |flat_key, translation|
102
+ translations.push({ :filename => filename, :locale => locale.to_s, :key => flat_key, :translation => translation })
103
+ end
104
+ end
105
+ end
106
+ translations
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -0,0 +1,97 @@
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
+ translations = load_files( I18n.config.load_path )
38
+ locales_requested = ENV['locales'].downcase.split(',')
39
+ checker = I18nVerify:Checker.new(I18n.config.load_path)
40
+ checker.is_complete?(locales_requested)
41
+ end
42
+
43
+ #
44
+ # duplicates helps in finding keys with multiple translations to the same locale
45
+ #
46
+ # redundancies takes a command line rake param: the list of locales to check
47
+ # omit for all
48
+ #
49
+ # Examples:
50
+ # rake i18n:duplicates
51
+ # rake i18n:duplicates locales=en,de
52
+ #
53
+ desc "Checks if any keys are translated multiple times"
54
+ task :duplicates do |t, args|
55
+ require "#{::Rails.root.to_s}/config/environment.rb"
56
+ translations = load_files( I18n.config.load_path )
57
+ locales_requested = ENV['locales'].downcase.split(',')
58
+ checker = I18nVerify:Checker.new(I18n.config.load_path)
59
+ checker.duplicates?(locales_requested)
60
+ end
61
+
62
+ =begin
63
+ # TODO: write method
64
+ desc "Checks translations spellings"
65
+ task :spelling do |t, args|
66
+ end
67
+ =end
68
+
69
+ desc "Run all checks"
70
+ task :verify => [:is_complete, :duplicates] do
71
+ end
72
+
73
+ end
74
+
75
+ #
76
+ # BONUS :)
77
+ #
78
+ namespace :yaml do
79
+ desc "Finds keys in yaml files; regexp to match keys; command line: rake yaml:find[config/locales/**/*.yml,/\.models\./]"
80
+ task :find, :filename_pattern, :regexp, :group_by_filename do |t, args|
81
+ filenames = Dir[args[:filename_pattern] || Rails.root.join('**', '*.{yaml,yml}').to_s]
82
+ regexp = Regexp.new(args[:regexp] || "")
83
+ group_by_filename = args[:group_by_filename]
84
+
85
+ filenames.each do |filename|
86
+ print filename + ":\n" if group_by_filename
87
+
88
+ File.open( filename ) do |infile|
89
+ yaml_hash = YAML::parse(infile).transform
90
+ flatten_keys( yaml_hash ) do |key, value|
91
+ puts "#{group_by_filename ? '' : (filename + ' #')} #{key}: #{value}\n" if key =~ regexp
92
+ end
93
+ end
94
+
95
+ end
96
+ end
97
+ 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: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - fastcatch
@@ -28,6 +28,9 @@ extensions: []
28
28
  extra_rdoc_files: []
29
29
 
30
30
  files:
31
+ - lib/i18n-verify/railtie.rb
32
+ - lib/i18n_verify.rb
33
+ - lib/tasks/i18_verify.rake
31
34
  - LICENSE.txt
32
35
  - README.markdown
33
36
  has_rdoc: true