i18n_lookup 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,6 +5,8 @@ $logger = Logger.new(STDOUT)
5
5
 
6
6
  # if ENV['I18N_DEBUG'] is set to true, all keys are printed on console
7
7
  module I18nLookup
8
+ require 'i18n_lookup/railtie' if defined?(Rails)
9
+
8
10
  protected
9
11
 
10
12
  def lookup(locale, key, scope = [], options = {})
@@ -0,0 +1,13 @@
1
+ require 'i18n_lookup'
2
+ require 'rails'
3
+
4
+ module I18nLookup
5
+ class Railtie < Rails::Railtie
6
+ railtie_name :i18n_lookup
7
+
8
+ rake_tasks do
9
+ load "tasks/i18n_normalize.rake"
10
+ load "tasks/i18n_missing_keys.rake"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,116 @@
1
+ namespace :i18n do
2
+ desc "Find and list translation keys that do not exist in all locales"
3
+ task :missing_keys => :environment do
4
+ finder = MissingKeysFinder.new(I18n.backend)
5
+ finder.find_missing_keys
6
+ end
7
+ end
8
+
9
+
10
+ class MissingKeysFinder
11
+
12
+ def initialize(backend)
13
+ @backend = backend
14
+ self.load_config
15
+ self.load_translations
16
+ end
17
+
18
+ # Returns an array with all keys from all locales
19
+ def all_keys
20
+ I18n.backend.send(:translations).collect do |check_locale, translations|
21
+ collect_keys([], translations).sort
22
+ end.flatten.uniq
23
+ end
24
+
25
+ def find_missing_keys
26
+ output_available_locales
27
+ output_unique_key_stats(all_keys)
28
+
29
+ missing_keys = {}
30
+ all_keys.each do |key|
31
+
32
+ I18n.available_locales.each do |locale|
33
+
34
+ skip = false
35
+ ls = locale.to_s
36
+ if !@yaml[ls].nil?
37
+ @yaml[ls].each do |re|
38
+ if key.match(re)
39
+ skip = true
40
+ break
41
+ end
42
+ end
43
+ end
44
+
45
+ if !key_exists?(key, locale) && skip == false
46
+ if missing_keys[key]
47
+ missing_keys[key] << locale
48
+ else
49
+ missing_keys[key] = [locale]
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ output_missing_keys(missing_keys)
56
+ return missing_keys
57
+ end
58
+
59
+ def output_available_locales
60
+ puts "#{I18n.available_locales.size} #{I18n.available_locales.size == 1 ? 'locale' : 'locales'} available: #{I18n.available_locales.join(', ')}"
61
+ end
62
+
63
+ def output_missing_keys(missing_keys)
64
+ puts "#{missing_keys.size} #{missing_keys.size == 1 ? 'key is missing' : 'keys are missing'} from one or more locales:"
65
+ missing_keys.keys.sort.each do |key|
66
+ puts %|'\e[1;33m#{key}\e[0;0m': Missing from #{missing_keys[key].collect(&:inspect).join(', ')}; Value: '\e[1;34m#{I18n.t(key, :locale => :en)}\e[0;0m'|
67
+ end
68
+ end
69
+
70
+ def output_unique_key_stats(keys)
71
+ number_of_keys = keys.size
72
+ puts "#{number_of_keys} #{number_of_keys == 1 ? 'unique key' : 'unique keys'} found."
73
+ end
74
+
75
+ def collect_keys(scope, translations)
76
+ full_keys = []
77
+ translations.to_a.each do |key, translations|
78
+ next if translations.nil?
79
+
80
+ new_scope = scope.dup << key
81
+ if translations.is_a?(Hash)
82
+ full_keys += collect_keys(new_scope, translations)
83
+ else
84
+ full_keys << new_scope.join('.')
85
+ end
86
+ end
87
+ return full_keys
88
+ end
89
+
90
+ # Returns true if key exists in the given locale
91
+ def key_exists?(key, locale)
92
+ I18n.locale = locale
93
+ I18n.translate(key, :raise => true)
94
+ return true
95
+ rescue I18n::MissingInterpolationArgument
96
+ return true
97
+ rescue I18n::MissingTranslationData
98
+ return false
99
+ end
100
+
101
+ def load_translations
102
+ # Make sure we’ve loaded the translations
103
+ I18n.backend.send(:init_translations)
104
+ end
105
+
106
+ def load_config
107
+ @yaml = {}
108
+ begin
109
+ @yaml = YAML.load_file(File.join(Rails.root, 'config', 'ignore_missing_keys.yml'))
110
+ rescue => e
111
+ STDERR.puts "No ignore_missing_keys.yml config file."
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,100 @@
1
+ # -*- coding: utf-8 -*-
2
+ namespace :i18n do
3
+ desc 'Writes current default locale translations to a normalized file and deletes unused locale files'
4
+ task :normalize => :environment do
5
+ class Hash
6
+ def to_hash_recursive
7
+ result = self.to_hash
8
+
9
+ result.each do |key, value|
10
+ case value
11
+ when Hash
12
+ result[key] = value.to_hash_recursive
13
+ when Array
14
+ result[key] = value.to_hash_recursive
15
+ end
16
+ end
17
+
18
+ result
19
+ end
20
+
21
+ def sort_by_key(recursive=false, &block)
22
+ self.keys.sort(&block).reduce({}) do |seed, key|
23
+ seed[key] = self[key]
24
+ if recursive && seed[key].is_a?(Hash)
25
+ seed[key] = seed[key].sort_by_key(true, &block)
26
+ end
27
+ seed
28
+ end
29
+ end
30
+ end
31
+
32
+ class Array
33
+ def to_hash_recursive
34
+ result = self
35
+
36
+ result.each_with_index do |value,i|
37
+ case value
38
+ when Hash
39
+ result[i] = value.to_hash_recursive
40
+ when Array
41
+ result[i] = value.to_hash_recursive
42
+ end
43
+ end
44
+
45
+ result
46
+ end
47
+ end
48
+
49
+ def current_i18n_yaml(locale)
50
+ default_locale_translations = I18n.backend.send(:translations)[locale].with_indifferent_access.to_hash_recursive
51
+ i18n_yaml = {locale.to_s => default_locale_translations}.sort_by_key(true).to_yaml
52
+ process = i18n_yaml.split(/\n/).reject{|e| e == ''}[1..-1] # remove "---" from first line in yaml
53
+
54
+ # add an empty line if yaml tree level changes by 2 or more
55
+ tmp_ary = []
56
+ process.each_with_index do |line, idx|
57
+ tmp_ary << line
58
+ unless process[idx+1].nil?
59
+ this_line_spcs = line.match(/\A\s*/)[0].length
60
+ next_line_spcs = process[idx+1].match(/\A\s*/)[0].length
61
+ tmp_ary << '' if next_line_spcs - this_line_spcs < -2
62
+ end
63
+ end
64
+
65
+ tmp_ary * "\n"
66
+ end
67
+
68
+ generated_locale_yaml = {}
69
+
70
+ I18n.backend.send(:translations).keys.each do |locale|
71
+ generated_locale_yaml[locale] = current_i18n_yaml(locale)
72
+ end
73
+
74
+ # delete unused locale files
75
+ repo_root = %x(git rev-parse --show-toplevel).strip
76
+ repo_locales = I18n.load_path.dup.keep_if{|p| p.include?(repo_root)}
77
+ repo_locales.each do |locale_file|
78
+ FileUtils.rm locale_file
79
+ puts "removed \"#{locale_file}\""
80
+ end
81
+
82
+ # write normalized locale to file
83
+ generated_locale_yaml.keys.each do |locale|
84
+ fn = File.join Rails.root, 'config', 'locales', locale.to_s + '.yml'
85
+ f_size_before = File.exists?(fn) ? File.size(fn) : 0
86
+
87
+ File.open(fn, 'w') { |file| file.puts generated_locale_yaml[locale]}
88
+ f_size_after = File.size fn
89
+ puts "\n(re)generated #{fn}\n"
90
+
91
+ if f_size_before == 0
92
+ puts "\"#{fn}\" created, file size: #{f_size_after} bytes.\n"
93
+ elsif f_size_before != f_size_after
94
+ puts "\"#{fn}\" changed from #{f_size_before} to #{f_size_after} bytes.\n"
95
+ else
96
+ puts "\"#{fn}\" is still #{f_size_after} bytes.\n"
97
+ end
98
+ end
99
+ end
100
+ end
File without changes
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: i18n_lookup
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.0
5
+ version: 0.3.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Thomas Metzmacher
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-24 00:00:00.000000000 Z
12
+ date: 2014-06-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: i18n
@@ -91,21 +91,24 @@ dependencies:
91
91
  - !ruby/object:Gem::Version
92
92
  version: 4.0.2
93
93
  prerelease: false
94
- description: Prints out the I18n calls
94
+ description: A toolset for I18n handling
95
95
  email: kontakt@thomet.de
96
96
  executables: []
97
97
  extensions: []
98
98
  extra_rdoc_files: []
99
99
  files:
100
- - i18n_lookup.rb
101
- - i18n_lookup_spec.rb
100
+ - lib/i18n_lookup/railtie.rb
101
+ - lib/i18n_lookup.rb
102
+ - lib/tasks/i18n_missing_keys.rake
103
+ - lib/tasks/i18n_normalize.rake
104
+ - spec/i18n_lookup_spec.rb
102
105
  homepage: http://www.thomet.de/
103
106
  licenses:
104
107
  - MIT
105
108
  post_install_message:
106
109
  rdoc_options: []
107
110
  require_paths:
108
- - .
111
+ - lib
109
112
  required_ruby_version: !ruby/object:Gem::Requirement
110
113
  none: false
111
114
  requirements:
@@ -125,5 +128,5 @@ signing_key:
125
128
  specification_version: 3
126
129
  summary: I18n Lookup
127
130
  test_files:
128
- - i18n_lookup_spec.rb
131
+ - spec/i18n_lookup_spec.rb
129
132
  has_rdoc: