i18n_lookup 0.2.0 → 0.3.0

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.
@@ -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: