i18n-tasks 0.0.1 → 0.0.2

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