i18n_tools 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ module I18nTools
2
+ class MissingScanner < Scanner
3
+ def initialize(locale)
4
+ @locale = locale
5
+ end
6
+
7
+ def results
8
+ missing_ones = []
9
+
10
+ scan do |key|
11
+ missing_ones << key unless I18n.backend.send(:lookup, @locale, key)
12
+ end
13
+
14
+ result = {}
15
+
16
+ missing_ones.each do |key|
17
+ current_hash = result
18
+ parts = key.split(".")
19
+ parts[0..-2].each do |part|
20
+ current_hash[part] ||= {}
21
+ current_hash = current_hash[part]
22
+ end
23
+
24
+ current_hash[parts.last] = ""
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,54 @@
1
+ module I18nTools
2
+ class Scanner
3
+ VIEW_REGEXPS = [/[^\w]t\(\"(.*?)\".*?\)/, /[^\w]t\(\'(.*?)\'.*?\)/]
4
+ CODE_REGEXPS = [/I18n\.t\(\"(.*?)\".*?\)/, /I18n\.t\(\'(.*?)\'.*?\)/]
5
+
6
+ cattr_accessor :file_types
7
+ self.file_types = ['controllers', 'helpers', 'models']
8
+
9
+ protected
10
+ def scan(&block)
11
+ scan_views(&block)
12
+ scan_code(&block)
13
+ end
14
+
15
+ private
16
+ def scan_views(&block)
17
+ Dir['app/views/**/*.erb', 'app/views/**/*.rhtml'].each do |filename|
18
+ next if ignores.any? { |r| filename =~ r }
19
+
20
+ content = File.read(filename)
21
+ VIEW_REGEXPS.each do |view_regexp|
22
+ content.scan(view_regexp) do |match|
23
+ key = match.first
24
+ next if key =~ /\#\{/
25
+ if key =~ /^\./
26
+ namespace = filename.gsub('app/views/', '').gsub('.html.erb', '').gsub('/', '.')
27
+ key = (namespace + key).split('.').collect { |part| part.gsub(/^\_/, '') }.join('.')
28
+ end
29
+ yield key
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def scan_code(&block)
36
+ Dir["lib/**/*.rb", *self.class.file_types.collect { |t| "app/#{t}/**/*.rb" }].each do |filename|
37
+ next if ignores.any? { |r| filename =~ r }
38
+
39
+ content = File.read(filename)
40
+ CODE_REGEXPS.each do |code_regexp|
41
+ content.scan(code_regexp) do |match|
42
+ key = match.first
43
+ next if key =~ /\#\{/
44
+ yield key
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def ignores
51
+ @ignores ||= File.read(".i18nignore").split("\n").reject { |e| e.strip.blank? || e =~ /^#/ }.collect { |i| Regexp.new(i) } rescue []
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,21 @@
1
+ namespace :translations do
2
+ task :setup => :environment do
3
+ require 'i18n_tools'
4
+
5
+ @locale = (ENV['LOCALE'] || 'en').to_sym
6
+ end
7
+
8
+ desc 'Detect missing translations'
9
+ task :missing => :setup do
10
+ require 'ya2yaml'
11
+
12
+ results = I18nTools::MissingScanner.new(@locale).results
13
+ puts({ @locale.to_s => results }.ya2yaml)
14
+ end
15
+
16
+ desc 'Detect translations that are not used in code'
17
+ task :unused => :setup do
18
+ unused = I18nTools::UnusedScanner.new(@locale).results
19
+ puts unused
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ module I18nTools
2
+ class UnusedScanner < Scanner
3
+ def initialize(locale)
4
+ @locale = locale
5
+ end
6
+
7
+ def results
8
+ used_ones = []
9
+
10
+ scan do |key|
11
+ used_ones << [@locale, key].join('.')
12
+ end
13
+
14
+ defined_ones = I18nTools.extract_i18n_keys(@locale.to_s, I18n.backend.send(:lookup, @locale, ''))
15
+
16
+ unused = (defined_ones - used_ones).reject { |key| ignore_keys.any? { |rx| rx =~ key } }.sort
17
+ end
18
+
19
+ protected
20
+ def ignore_keys
21
+ @ignore_keys ||= File.read(".i18nignore_unused").split("\n").reject { |e| e.strip.blank? || e =~ /^#/ }.collect { |key| Regexp.new(Regexp.escape("#{@locale}.#{key}")) } rescue []
22
+ end
23
+ end
24
+ end
data/lib/i18n_tools.rb ADDED
@@ -0,0 +1,19 @@
1
+ # require all necessary files here
2
+
3
+ module I18nTools
4
+ def self.extract_i18n_keys(prefix, object)
5
+ case object
6
+ when Hash
7
+ return prefix if object.keys.include?(:one) && object.keys.include?(:other)
8
+ object.collect do |key, value|
9
+ extract_i18n_keys([prefix, key].join('.'), value)
10
+ end.flatten.compact
11
+ when String
12
+ prefix
13
+ end
14
+ end
15
+ end
16
+
17
+ require File.dirname(__FILE__) + '/i18n_tools/scanner'
18
+ require File.dirname(__FILE__) + '/i18n_tools/missing_scanner'
19
+ require File.dirname(__FILE__) + '/i18n_tools/unused_scanner'
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: i18n_tools
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Thomas Kadauke
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-17 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email: tkadauke@imedo.de
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/i18n_tools/missing_scanner.rb
32
+ - lib/i18n_tools/scanner.rb
33
+ - lib/i18n_tools/tasks.rb
34
+ - lib/i18n_tools/unused_scanner.rb
35
+ - lib/i18n_tools.rb
36
+ has_rdoc: true
37
+ homepage:
38
+ licenses: []
39
+
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ hash: 3
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.3.7
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Tasks for extracting missing and unused translations from Rails projects
70
+ test_files: []
71
+