i18n-tasks 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 548b6c0914a87c8129d182758dfce8fd3e296f4c
4
- data.tar.gz: afb9f738e869ca9250569559482b6abef7a729a7
3
+ metadata.gz: be5ef7d26c3df1ed7c2d3492c2ddbee544e561c0
4
+ data.tar.gz: c294aa392797e900e990defa0fbed3c5a7d7cafa
5
5
  SHA512:
6
- metadata.gz: eacb09e1ed32e1e3023cc4484f3c907cfacb27e3ca58d938eb19411e3fdfdacdb7e4451bab2e4e677db577b64b0f6ec64751766cc520dd1b73e675a0ebe03aa4
7
- data.tar.gz: 42867a547082972542fae5bfe92e6793a88c5b6bfb321485395d5e8b6ee010f015c66f0c3e4df81756554e0854ce3f1ac9a7488825a7a44096e08a89de9179f5
6
+ metadata.gz: 783c897ba722831c9893301270e3a8dee8c7dd0775a32bb293c137a3b643f4fd50c9d05628e794891c72bbcfadce25f844da3d3846b750c495ea94bf8ee15d00
7
+ data.tar.gz: df5d3744b47f1ed0366cb6305823d6f38737e4b583af2ac586808ada0a9a2a0c7a7470db592871962ad1ff3e82a5e4d76790d41207445ca3080054c666573e9a
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - jruby-19mode # JRuby in 1.9 mode
5
+ - rbx-19mode
6
+ - 1.9.3
data/README.md CHANGED
@@ -1,22 +1,29 @@
1
- i18n-tasks
1
+ i18n-tasks [![Build Status](https://travis-ci.org/glebm/i18n-tasks.png?branch=master)](https://travis-ci.org/glebm/i18n-tasks)
2
2
  ==========
3
3
 
4
- I18n tasks to find missing / unused translations and more
4
+ Rails I18n tasks to find missing / unused translations and more. Works with slim / coffee / haml etc.
5
5
 
6
- There are 3 tasks available to manage translations.
6
+ Use `rake -T i18n` to get the list of tasks with descriptions. There are 3 tasks available at the moment:
7
7
 
8
- $ rake -T i18n
9
- rake i18n:missing # show keys with translation values identical to base
10
- rake i18n:prefill # add keys from base locale to others
11
- rake i18n:unused # find potentially unused translations
8
+ * `i18n:missing` task shows all the keys that have not been translated yet *([source](https://github.com/glebm/i18n-tasks/blob/master/lib/i18n/tasks/missing.rb))*
9
+ * `i18n:prefill` task normalizes locale files, and adds missing keys from base locale to others *([source](https://github.com/glebm/i18n-tasks/blob/master/lib/i18n/tasks/prefill.rb))*
10
+ * `i18n:unused` task shows potentially unused translations *([source](https://github.com/glebm/i18n-tasks/blob/master/lib/i18n/tasks/unused.rb))*
12
11
 
13
- * `i18n:missing` task shows all the keys that have not been translated yet
14
- * `i18n:prefill` task adds missing keys to locale files, prefilling with base locale (en) value by default
15
- * `i18n:unused` task shows potentially unused translations (it may give false positives)
12
+ `i18n:unused` will detect pattern translations and not report them, e.g.:
13
+
14
+ t 'category.' + category.key # 'category.arts_and_crafts' considered used
15
+ t "category.#{category.key}" # also works
16
+
17
+ For more examples see [the tests](https://github.com/glebm/i18n-tasks/blob/master/spec/i18n_tasks_spec.rb#L43-L59).
16
18
 
17
19
  Installation
18
- ============
20
+ ------------
19
21
 
20
22
  Simply add to Gemfile:
21
23
 
22
24
  gem 'i18n-tasks', '~> 0.0.1'
25
+
26
+ Configuration
27
+ -------------
28
+
29
+ Currently i18n-tasks only reports / writes to locale data in `config/locales/{locale_code}.yml`. *PRs making this configurable welcome!*
data/Rakefile CHANGED
@@ -1 +1,5 @@
1
1
  require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new(:spec)
4
+ task :default => :spec
5
+
data/i18n-tasks.gemspec CHANGED
@@ -18,6 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
+ spec.add_dependency 'rails'
22
+ spec.add_dependency 'rake'
21
23
  spec.add_development_dependency 'bundler', '~> 1.3'
22
24
  spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec-rails'
23
26
  end
@@ -0,0 +1,9 @@
1
+ require 'i18n/tasks/task_helpers'
2
+
3
+ module I18n
4
+ module Tasks
5
+ class BaseTask
6
+ include TaskHelpers
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ require 'i18n/tasks/base_task'
2
+
3
+ module I18n
4
+ module Tasks
5
+ class Missing < BaseTask
6
+ def perform
7
+ (I18n.available_locales.map(&:to_s) - [base_locale]).each do |locale|
8
+ trn = get_locale_data(locale)[locale]
9
+ traverse base[base_locale] do |key, base_value|
10
+ translated = t(trn, key)
11
+ if translated.blank? || translated == base_value
12
+ puts "#{locale}.#{key}: #{base_value}"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ require 'i18n/tasks/base_task'
2
+
3
+ module I18n
4
+ module Tasks
5
+ class Prefill < BaseTask
6
+ def perform
7
+ # Will also rewrite en, good for ordering
8
+ I18n.available_locales.map(&:to_s).each do |target_locale|
9
+ trn = get_locale_data(target_locale)
10
+ prefilled = { target_locale => base[base_locale] }.deep_merge(trn)
11
+ File.open(locale_file_path(target_locale), 'w'){ |f| f.write prefilled.to_yaml }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ require 'open3'
2
+
3
+ module I18n
4
+ module Tasks
5
+ module TaskHelpers
6
+ def run_command(*args)
7
+ _in, out, _err = Open3.popen3(*args)
8
+ out.gets nil
9
+ end
10
+
11
+ # locale data hash, with locale name as root
12
+ def get_locale_data(locale)
13
+ # todo multiple files, configuration option
14
+ YAML.load_file "config/locales/#{locale}.yml"
15
+ end
16
+
17
+ # main locale file path (for writing to)
18
+ def locale_file_path(locale)
19
+ "config/locales/#{locale}.yml"
20
+ end
21
+
22
+ # traverse hash, yielding with full key and value
23
+ def traverse(path = '', hash, &block)
24
+ hash.each do |k, v|
25
+ if v.is_a?(Hash)
26
+ traverse("#{path}.#{k}", v, &block)
27
+ else
28
+ block.call("#{path}.#{k}"[1..-1], v)
29
+ end
30
+ end
31
+ end
32
+
33
+ def t(hash, key)
34
+ key.split('.').inject(hash) { |r, seg| r.try(:[], seg) }
35
+ end
36
+
37
+ def base_locale
38
+ I18n.default_locale.to_s
39
+ end
40
+
41
+ def base
42
+ @base ||= get_locale_data(base_locale)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,18 @@
1
+ require 'i18n/tasks/base_task'
2
+
3
+ module I18n
4
+ module Tasks
5
+ class Unused < BaseTask
6
+ def perform
7
+ grep_out = run_command 'grep', '-horI', %q{\\bt(\\?\\s*['"]\\([^'"]*\\)['"]}, 'app/'
8
+ used_keys = grep_out.split("\n").map { |r| r.match(/['"](.*?)['"]/)[1] }.uniq.to_set
9
+ pattern_prefixes = used_keys.select { |k| k =~ /\#{.*?}/ || k.ends_with?('.') }.map { |k| k.split(/\.?#/)[0] }
10
+ traverse base[base_locale] do |key, value|
11
+ if !used_keys.include?(key) && !pattern_prefixes.any? { |pp| key.start_with?(pp) }
12
+ puts "#{key}: #{value}"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,5 +1,5 @@
1
1
  module I18n
2
2
  module Tasks
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -1,65 +1,23 @@
1
1
  require 'set'
2
- require 'open3'
2
+ require 'active_support/core_ext'
3
+
4
+ require 'i18n/tasks/missing'
5
+ require 'i18n/tasks/prefill'
6
+ require 'i18n/tasks/unused'
3
7
 
4
8
  namespace :i18n do
5
9
  desc 'add keys from base locale to others'
6
10
  task :prefill => :environment do
7
- # Will also rewrite en, good for ordering
8
- I18n.available_locales.map(&:to_s).each do |target_locale|
9
- trn = YAML.load_file trn_path(target_locale)
10
- prefilled = { target_locale => base[base_locale] }.deep_merge(trn)
11
- File.open(trn_path(target_locale), 'w'){ |f| f.write prefilled.to_yaml }
12
- end
11
+ I18n::Tasks::Prefill.new.perform
13
12
  end
14
13
 
15
14
  desc 'show keys with translation values identical to base'
16
15
  task :missing => :environment do
17
- (I18n.available_locales.map(&:to_s) - [base_locale]).each do |locale|
18
- trn = YAML.load_file(trn_path(locale))[locale]
19
- traverse base[base_locale] do |key, base_value|
20
- translated = t(trn, key)
21
- if translated.blank? || translated == base_value
22
- puts "#{locale}.#{key}: #{base_value}"
23
- end
24
- end
25
- end
16
+ I18n::Tasks::Missing.new.perform
26
17
  end
27
18
 
28
19
  desc 'find potentially unused translations'
29
20
  task :unused => :environment do
30
- _in, out, _err = Open3.popen3 'grep', '-horI', %q{\\bt(\\?\\s*['"]\\([^'"]*\\)['"]}, 'app/'
31
- used_keys = out.gets(nil).split("\n").map { |r| r.match(/['"](.*?)['"]/)[1] }.uniq.to_set
32
- pattern_prefixes = used_keys.select { |key| key =~ /\#{.*?}/ || key.ends_with?('.') }.map { |key| key.split(/\.?#/)[0] }
33
- traverse base[base_locale] do |key, value|
34
- if !used_keys.include?(key) && !pattern_prefixes.any? { |pp| key.start_with?(pp) }
35
- puts "#{key}: #{value}"
36
- end
37
- end
38
- end
39
-
40
- define_method :trn_path do |locale|
41
- "config/locales/#{locale}.yml"
42
- end
43
-
44
- define_method :traverse do |path = '', hash, &block|
45
- hash.each do |k, v|
46
- if v.is_a?(Hash)
47
- traverse("#{path}.#{k}", v, &block)
48
- else
49
- block.call("#{path}.#{k}"[1..-1], v)
50
- end
51
- end
52
- end
53
-
54
- define_method :t do |hash, key|
55
- key.split('.').inject(hash) { |r, seg| r.try(:[], seg) }
56
- end
57
-
58
- define_method :base_locale do
59
- I18n.default_locale.to_s
60
- end
61
-
62
- define_method :base do
63
- @base ||= YAML.load_file trn_path(base_locale)
21
+ I18n::Tasks::Unused.new.perform
64
22
  end
65
23
  end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'rake i18n' do
4
+ describe 'missing' do
5
+ it 'detects missing or identical' do
6
+ TestCodebase.rake_result('i18n:missing').should be_i18n_keys %w(es.missing_in_es.a es.blank_in_es.a es.same_in_es.a)
7
+ end
8
+ end
9
+
10
+ describe 'unused' do
11
+ it 'detects unused' do
12
+ TestCodebase.rake_result('i18n:unused').should be_i18n_keys %w(unused.a)
13
+ end
14
+ end
15
+
16
+ describe 'prefill' do
17
+ it 'detects unused' do
18
+ TestCodebase.in_test_app_dir { YAML.load_file('config/locales/es.yml')['es']['missing_in_es'].should be_nil }
19
+ TestCodebase.rake_result('i18n:prefill')
20
+ TestCodebase.in_test_app_dir { YAML.load_file('config/locales/es.yml')['es']['missing_in_es']['a'].should == 'EN_TEXT' }
21
+ end
22
+ end
23
+
24
+ # --- setup ---
25
+ before do
26
+ gen_data = ->(v) {
27
+ {
28
+ 'ca' => {'a' => v, 'b' => v, 'c' => v, 'd' => v, 'e' => "#{v}%{i}", 'f' => "#{v}%{i}"},
29
+ 'cb' => {'a' => v, 'b' => "#{v}%{i}"},
30
+ 'hash_pattern' => {'a' => v},
31
+ 'hash_pattern2' => {'a' => v},
32
+ 'unused' => {'a' => v},
33
+ 'missing_in_es' => {'a' => v},
34
+ 'same_in_es' => {'a' => v},
35
+ 'blank_in_es' => {'a' => v}
36
+ }
37
+ }
38
+
39
+ en_data = gen_data.('EN_TEXT')
40
+ es_data = gen_data.('ES_TEXT').except('missing_in_es')
41
+ es_data['same_in_es']['a'] = 'EN_TEXT'
42
+ es_data['blank_in_es']['a'] = ''
43
+
44
+ fs = {
45
+ 'config/locales/en.yml' => {'en' => en_data}.to_yaml,
46
+ 'config/locales/es.yml' => {'es' => es_data}.to_yaml,
47
+ 'app/views/index.html.slim' => <<-SLIM,
48
+ p \#{t('ca.a')} \#{t 'ca.b'} \#{t "ca.c"}
49
+ p \#{t 'ca.d'} \#{t 'ca.f', i: 'world'} \#{t 'ca.e', i: 'world'}
50
+ p \#{t 'missing_in_es.a'} \#{t 'same_in_es.a'} \#{t 'blank_in_es.a'}
51
+ SLIM
52
+ 'app/controllers/events_controller.slim' => <<-RUBY,
53
+ class EventsController < ApplicationController
54
+ def show
55
+ redirect_to :edit, notice: I18n.t('cb.a')
56
+ I18n.t("cb.b", i: "Hello")
57
+ I18n.t("hash_pattern.\#{some_value}", i: "Hello")
58
+ I18n.t("hash_pattern2." + some_value, i: "Hello")
59
+ end
60
+ end
61
+ RUBY
62
+ }
63
+ TestCodebase.setup fs
64
+ end
65
+
66
+ after do
67
+ TestCodebase.teardown
68
+ end
69
+ end
@@ -0,0 +1,13 @@
1
+ ENV['RAKE_ENV'] ||= 'test'
2
+ require 'rspec/autorun'
3
+ $: << File.expand_path('../lib', __FILE__)
4
+ require 'i18n/tasks'
5
+ require 'rake'
6
+ Rake.load_rakefile 'tasks/i18n-tasks.rake'
7
+ Rake.load_rakefile 'support/test_codebase_env.rake'
8
+ Dir['spec/support/**/*.rb'].each { |f| require "./#{f}" }
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
13
+
@@ -0,0 +1,5 @@
1
+ RSpec::Matchers.define :be_i18n_keys do |expected|
2
+ match do |actual|
3
+ actual.split("\n").map { |x| x.split(':')[0] }.sort == expected.sort
4
+ end
5
+ end
@@ -0,0 +1,50 @@
1
+ require 'fileutils'
2
+ module TestCodebase
3
+ extend self
4
+ AT = 'tmp/test_codebase'
5
+
6
+ DEFAULTS = {
7
+ 'config/locales/en.yml' => {'en' => {}}.to_yaml,
8
+ 'config/locales/es.yml' => {'es' => {}}.to_yaml
9
+ }
10
+
11
+ def setup(files)
12
+ FileUtils.mkdir_p AT
13
+ in_test_app_dir do
14
+ DEFAULTS.merge(files).each do |path, content|
15
+ FileUtils.mkdir_p File.dirname(path)
16
+ File.open(path, 'w') { |f| f.write(content) }
17
+ end
18
+ end
19
+ end
20
+
21
+ def teardown
22
+ FileUtils.rm_rf AT
23
+ end
24
+
25
+ def rake_result(task)
26
+ in_test_app_dir {
27
+ rake_task = Rake::Task[task]
28
+ rake_task.reenable
29
+ capture_stdout { rake_task.invoke }
30
+ }
31
+ end
32
+
33
+ def in_test_app_dir(&block)
34
+ pwd = Dir.pwd
35
+ Dir.chdir AT
36
+ block.call
37
+ ensure
38
+ Dir.chdir pwd
39
+ end
40
+
41
+ private
42
+ def capture_stdout
43
+ out = StringIO.new
44
+ $stdout = out
45
+ yield
46
+ out.string
47
+ ensure
48
+ $stdout = STDOUT
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ task :environment do
2
+ I18n.default_locale = 'en'
3
+ I18n.available_locales = %w(en es)
4
+ end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-23 00:00:00.000000000 Z
11
+ date: 2013-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: bundler
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +66,20 @@ dependencies:
38
66
  - - '>='
39
67
  - !ruby/object:Gem::Version
40
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
41
83
  description: Rails I18n tasks to find missing / unused translations and more
42
84
  email:
43
85
  - glex.spb@gmail.com
@@ -48,15 +90,26 @@ files:
48
90
  - .gitignore
49
91
  - .ruby-gemset
50
92
  - .ruby-version
93
+ - .travis.yml
51
94
  - Gemfile
52
95
  - LICENSE.txt
53
96
  - README.md
54
97
  - Rakefile
55
98
  - i18n-tasks.gemspec
56
99
  - lib/i18n/tasks.rb
100
+ - lib/i18n/tasks/base_task.rb
101
+ - lib/i18n/tasks/missing.rb
102
+ - lib/i18n/tasks/prefill.rb
57
103
  - lib/i18n/tasks/railtie.rb
104
+ - lib/i18n/tasks/task_helpers.rb
105
+ - lib/i18n/tasks/unused.rb
58
106
  - lib/i18n/tasks/version.rb
59
107
  - lib/tasks/i18n-tasks.rake
108
+ - spec/i18n_tasks_spec.rb
109
+ - spec/spec_helper.rb
110
+ - spec/support/i18n_tasks_output_matcher.rb
111
+ - spec/support/test_codebase.rb
112
+ - spec/support/test_codebase_env.rake
60
113
  homepage: https://github.com/glebm/i18n-tasks
61
114
  licenses:
62
115
  - MIT
@@ -81,4 +134,9 @@ rubygems_version: 2.0.3
81
134
  signing_key:
82
135
  specification_version: 4
83
136
  summary: Rails I18n tasks to find missing / unused translations and more
84
- test_files: []
137
+ test_files:
138
+ - spec/i18n_tasks_spec.rb
139
+ - spec/spec_helper.rb
140
+ - spec/support/i18n_tasks_output_matcher.rb
141
+ - spec/support/test_codebase.rb
142
+ - spec/support/test_codebase_env.rake