i18n-verify 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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