i18n-tasks 0.1.8 → 0.2.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGES.md +5 -0
- data/README.md +23 -9
- data/i18n-tasks.gemspec +1 -0
- data/lib/i18n/tasks.rb +1 -0
- data/lib/i18n/tasks/base_task.rb +8 -0
- data/lib/i18n/tasks/data/yaml.rb +1 -1
- data/lib/i18n/tasks/data_traversal.rb +13 -3
- data/lib/i18n/tasks/missing_keys.rb +33 -0
- data/lib/i18n/tasks/output/terminal.rb +6 -6
- data/lib/i18n/tasks/source_keys.rb +4 -4
- data/lib/i18n/tasks/translation.rb +20 -0
- data/lib/i18n/tasks/translation_data.rb +33 -2
- data/lib/i18n/tasks/untranslated_keys.rb +12 -0
- data/lib/i18n/tasks/{unused.rb → unused_keys.rb} +2 -3
- data/lib/i18n/tasks/version.rb +1 -1
- data/lib/tasks/i18n-tasks.rake +80 -14
- data/spec/fixtures/app/views/relative/index.html.slim +2 -0
- data/spec/i18n_tasks_spec.rb +25 -6
- data/spec/support/i18n_tasks_output_matcher.rb +12 -6
- data/spec/support/test_codebase.rb +13 -7
- metadata +20 -5
- data/lib/i18n/tasks/missing.rb +0 -54
- data/lib/i18n/tasks/prefill.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4c2dfceb8ce78b38a271f5b2ee5afda329cd15d
|
4
|
+
data.tar.gz: 89936d161a3e2b826164658bb64b7816dbda0a6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed3cec3d3aadfac2f0d30b8b707cb8b5f46dfd1e063c283546be4222644757906c736aeceb4860c5a31319a6a799acf7056d444acda15d99d94ca4389e30c3f0
|
7
|
+
data.tar.gz: 2781e4bf20a94badc077233c21e9d4fa0fe9a2dda74e76ff05429e4833b13bc265868528fb8d9d9c8fce07a32161ca70d7acac5c2b00981ee640dd6e061dbbb8
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -7,13 +7,18 @@ Rails I18n tasks to find missing / unused translations and more. Works with slim
|
|
7
7
|
|
8
8
|
## Usage
|
9
9
|
|
10
|
-
Use `rake -T i18n` to get the list of tasks with descriptions.
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
Use `rake -T i18n` to get the list of tasks with descriptions. These are [the tasks](/lib/tasks/i18n-tasks.rake) available:
|
11
|
+
|
12
|
+
Rake Task | Summary
|
13
|
+
:---------------------------------------------- |:------------------------------------------------------------------
|
14
|
+
i18n:missing | Show missing translations.
|
15
|
+
i18n:unused | Show unused translations.
|
16
|
+
i18n:normalize | Normalize translation data: sort by name and file.
|
17
|
+
i18n:fill:add_missing *[value = key.humanize]* | Add missing `key: value` to base locale.
|
18
|
+
i18n:fill:with_base *[locales = all - base]* | Add missing `key: base value` to each non-base locale.
|
19
|
+
i18n:fill:with_google *[locales = all - base]* | Add missing `key: Google Translated value` to each non-base locale.
|
20
|
+
i18n:fill:with_blanks *[locales = all]* | Add `key: ''` for missing keys to each locale.
|
21
|
+
|
17
22
|
The `i18n:unused` task will detect pattern translations and not report them, e.g.:
|
18
23
|
|
19
24
|
```ruby
|
@@ -31,7 +36,7 @@ For more examples see [the tests](/spec/i18n_tasks_spec.rb).
|
|
31
36
|
Simply add to Gemfile:
|
32
37
|
|
33
38
|
```ruby
|
34
|
-
gem 'i18n-tasks', '~> 0.
|
39
|
+
gem 'i18n-tasks', '~> 0.2.0'
|
35
40
|
```
|
36
41
|
|
37
42
|
## Configuration
|
@@ -59,6 +64,15 @@ data:
|
|
59
64
|
- 'config/locales/%{locale}.yml'
|
60
65
|
```
|
61
66
|
|
67
|
+
### Translation
|
68
|
+
|
69
|
+
Set `GOOGLE_TRANSLATE_API_KEY` environment variable, or specify the key in config/i18n-tasks.yml:
|
70
|
+
|
71
|
+
```yaml
|
72
|
+
translation:
|
73
|
+
api_key: THE_KEY
|
74
|
+
```
|
75
|
+
|
62
76
|
### Usage search
|
63
77
|
|
64
78
|
```yaml
|
@@ -77,7 +91,7 @@ search:
|
|
77
91
|
exclude:
|
78
92
|
- '*.js'
|
79
93
|
# you can override the default grep pattern:
|
80
|
-
pattern:
|
94
|
+
pattern: "\\bt[( ]\\s*(.)((?<=\").+?(?=\")|(?<=').+?(?=')|(?<=:)\\w+\\b)"
|
81
95
|
```
|
82
96
|
|
83
97
|
### Fine-tuning
|
data/i18n-tasks.gemspec
CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_dependency 'rake'
|
22
22
|
spec.add_dependency 'activesupport'
|
23
|
+
spec.add_dependency 'easy_translate'
|
23
24
|
spec.add_dependency 'term-ansicolor'
|
24
25
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
25
26
|
spec.add_development_dependency 'rake'
|
data/lib/i18n/tasks.rb
CHANGED
data/lib/i18n/tasks/base_task.rb
CHANGED
@@ -4,7 +4,11 @@ require 'i18n/tasks/relative_keys'
|
|
4
4
|
require 'i18n/tasks/plural_keys'
|
5
5
|
require 'i18n/tasks/source_keys'
|
6
6
|
require 'i18n/tasks/translation_data'
|
7
|
+
require 'i18n/tasks/translation'
|
7
8
|
require 'i18n/tasks/ignore_keys'
|
9
|
+
require 'i18n/tasks/missing_keys'
|
10
|
+
require 'i18n/tasks/untranslated_keys'
|
11
|
+
require 'i18n/tasks/unused_keys'
|
8
12
|
|
9
13
|
module I18n
|
10
14
|
module Tasks
|
@@ -13,7 +17,11 @@ module I18n
|
|
13
17
|
include RelativeKeys
|
14
18
|
include PluralKeys
|
15
19
|
include SourceKeys
|
20
|
+
include MissingKeys
|
21
|
+
include UntranslatedKeys
|
22
|
+
include UnusedKeys
|
16
23
|
include TranslationData
|
24
|
+
include Translation
|
17
25
|
include IgnoreKeys
|
18
26
|
|
19
27
|
# i18n-tasks config (defaults + config/i18n-tasks.yml)
|
data/lib/i18n/tasks/data/yaml.rb
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
module I18n::Tasks::DataTraversal
|
2
2
|
# translation of the key found in the passed hash or nil
|
3
3
|
# @return [String,nil]
|
4
|
-
def t(hash, key)
|
4
|
+
def t(hash = data[base_locale], key)
|
5
5
|
key.split('.').inject(hash) { |r, seg| r[seg] if r }
|
6
6
|
end
|
7
7
|
|
8
|
+
# traverse => flat_map
|
9
|
+
def traverse_flat_map(hash)
|
10
|
+
list = []
|
11
|
+
traverse hash do |k, v|
|
12
|
+
mapped = yield(k, v)
|
13
|
+
list << mapped if mapped
|
14
|
+
end
|
15
|
+
list
|
16
|
+
end
|
17
|
+
|
8
18
|
# traverse hash, yielding with full key and value
|
9
19
|
# @param hash [Hash{String => String,Hash}] translation data to traverse
|
10
20
|
# @yield [full_key, value] yields full key and value for every translation in #hash
|
@@ -25,8 +35,8 @@ module I18n::Tasks::DataTraversal
|
|
25
35
|
list = list.sort
|
26
36
|
tree = {}
|
27
37
|
list.each do |key, value|
|
28
|
-
key_segments
|
29
|
-
node
|
38
|
+
key_segments = key.to_s.split('.')
|
39
|
+
node = key_segments[0..-2].inject(tree) do |r, segment|
|
30
40
|
r[segment] ||= {}
|
31
41
|
end
|
32
42
|
node[key_segments.last] = value
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module I18n::Tasks::MissingKeys
|
2
|
+
# missing keys, i.e. key that are in the code but are not in the base locale data
|
3
|
+
# @return Array{Hash}
|
4
|
+
def keys_missing_base_value
|
5
|
+
find_source_keys.reject { |key|
|
6
|
+
key_value?(key, base_locale) || pattern_key?(key) || ignore_key?(key, :missing)
|
7
|
+
}.map { |key| {locale: base_locale, type: :none, key: key} }
|
8
|
+
end
|
9
|
+
|
10
|
+
# present in base locale, but untranslated in another locale
|
11
|
+
# @return Array{Hash}
|
12
|
+
def keys_missing_translation(locale)
|
13
|
+
trn = data[locale]
|
14
|
+
r = []
|
15
|
+
traverse data[base_locale] do |key, base_value|
|
16
|
+
value_in_locale = t(trn, key)
|
17
|
+
if value_in_locale.blank? && !ignore_key?(key, :missing)
|
18
|
+
r << {locale: locale, key: key, type: :blank, base_value: base_value}
|
19
|
+
elsif value_in_locale == base_value && !ignore_key?(key, :eq_base, locale)
|
20
|
+
r << {locale: locale, key: key, type: :eq_base, base_value: base_value}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
r
|
24
|
+
end
|
25
|
+
|
26
|
+
# sort first by locale, then by type
|
27
|
+
# @return Array{Hash}
|
28
|
+
def sort_keys(keys)
|
29
|
+
keys.sort { |a, b|
|
30
|
+
(l = a[:locale] <=> b[:locale]).zero? ? a[:type] <=> b[:type] : l
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
@@ -38,14 +38,14 @@ module I18n
|
|
38
38
|
$stderr.puts(bold green message)
|
39
39
|
end
|
40
40
|
|
41
|
-
STATUS_TEXTS = {
|
42
|
-
none: red("✗".ljust(6)),
|
43
|
-
blank: yellow(bold '∅'.ljust(6)),
|
44
|
-
eq_base: blue(bold "=".ljust(6))
|
45
|
-
}
|
46
41
|
|
47
42
|
def print_missing_translation(m, opts)
|
48
|
-
|
43
|
+
status_texts = {
|
44
|
+
none: red("✗".ljust(6)),
|
45
|
+
blank: yellow(bold '∅'.ljust(6)),
|
46
|
+
eq_base: blue(bold "=".ljust(6))
|
47
|
+
}
|
48
|
+
locale, key, base_value, status_text = m[:locale], m[:key], m[:base_value].to_s.try(:strip), " #{status_texts[m[:type]]}"
|
49
49
|
|
50
50
|
key = magenta "#{key}".ljust(opts[:key_col_width])
|
51
51
|
s = if m[:type] == :none
|
@@ -69,13 +69,13 @@ module I18n::Tasks::SourceKeys
|
|
69
69
|
line.scan(search_config[:pattern]) do |t, key|
|
70
70
|
if key.start_with? '.'
|
71
71
|
key = absolutize_key(key, path)
|
72
|
-
elsif t == ':'
|
73
|
-
key = absolutize_key(".#{key}", path)
|
74
72
|
end
|
75
|
-
|
73
|
+
if key =~ /^[\w.\#{}]+$/
|
74
|
+
keys << key
|
75
|
+
end
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
79
|
-
keys
|
79
|
+
keys
|
80
80
|
end
|
81
81
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'easy_translate'
|
2
|
+
|
3
|
+
module I18n::Tasks::Translation
|
4
|
+
def google_translate(strings, opts)
|
5
|
+
return [] if strings.empty?
|
6
|
+
opts = opts.dup
|
7
|
+
if (key = translation_config[:api_key]).present?
|
8
|
+
opts[:key] ||= key
|
9
|
+
end
|
10
|
+
EasyTranslate.translate strings, opts
|
11
|
+
end
|
12
|
+
|
13
|
+
def translation_config
|
14
|
+
@translation_config ||= begin
|
15
|
+
conf = (config[:translation] ||= {}).with_indifferent_access
|
16
|
+
conf[:api_key] ||= ENV['GOOGLE_TRANSLATE_API_KEY']
|
17
|
+
conf
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -17,12 +17,43 @@ module I18n::Tasks::TranslationData
|
|
17
17
|
end
|
18
18
|
|
19
19
|
# whether the value for key exists in locale (defaults: base_locale)
|
20
|
-
def
|
20
|
+
def key_value?(key, locale = base_locale)
|
21
21
|
t(data[locale], key).present?
|
22
22
|
end
|
23
23
|
|
24
24
|
# @return [String] default i18n locale
|
25
25
|
def base_locale
|
26
|
-
I18n.default_locale.to_s
|
26
|
+
config[:base_locale] ||= I18n.default_locale.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Array<String>] all available locales
|
30
|
+
def locales
|
31
|
+
config[:locales] ||= I18n.available_locales.map(&:to_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
# write to store, normalizing all data
|
35
|
+
def normalize_store!(locales = self.locales)
|
36
|
+
Array(locales).each do |target_locale|
|
37
|
+
# the store itself handles normalization
|
38
|
+
data[target_locale] = data[target_locale]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# fill missing / blank keys with values from passed block
|
43
|
+
def fill_blanks!(locale = base_locale, &fill_with)
|
44
|
+
blank_keys =
|
45
|
+
if locale == base_locale
|
46
|
+
# for base locale "blank" is: present in source but not in the base locale.
|
47
|
+
keys_missing_base_value.map { |e| e[:key] } +
|
48
|
+
traverse_flat_map(data[base_locale]) { |key, value|
|
49
|
+
key if value.to_s.blank? && !ignore_key?(key, :missing) }
|
50
|
+
else
|
51
|
+
# for other locales "blank" is: present in base but not in the locale itself.
|
52
|
+
traverse_flat_map(data[base_locale]) { |key|
|
53
|
+
key if !key_value?(key, locale) && !ignore_key?(key, :missing) }
|
54
|
+
end
|
55
|
+
|
56
|
+
list = blank_keys.uniq.zip fill_with.call(blank_keys)
|
57
|
+
data[locale] = data[locale].deep_merge(list_to_tree(list))
|
27
58
|
end
|
28
59
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module I18n::Tasks::UntranslatedKeys
|
2
|
+
# Get all the missing translations as an array of missing keys as hashes with the following options:
|
3
|
+
# :locale
|
4
|
+
# :key
|
5
|
+
# :type — :blank, :missing, or :eq_base
|
6
|
+
# :base_value — translation value in base locale if one is present
|
7
|
+
# @return [Array<Hash{Symbol => String,Symbol,nil}>]
|
8
|
+
def untranslated_keys
|
9
|
+
other_locales = locales - [base_locale]
|
10
|
+
sort_keys keys_missing_base_value + other_locales.map { |locale| keys_missing_translation(locale) }.flatten(1)
|
11
|
+
end
|
12
|
+
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
require 'i18n/tasks/base_task'
|
3
2
|
|
4
3
|
module I18n
|
5
4
|
module Tasks
|
6
|
-
|
5
|
+
module UnusedKeys
|
7
6
|
# @return [Array<[String, String]>] all the unused translations as an array of [key, value] pairs
|
8
|
-
def
|
7
|
+
def unused_keys
|
9
8
|
r = []
|
10
9
|
d = self.data[base_locale]
|
11
10
|
traverse d do |key, value|
|
data/lib/i18n/tasks/version.rb
CHANGED
data/lib/tasks/i18n-tasks.rake
CHANGED
@@ -1,28 +1,94 @@
|
|
1
1
|
require 'set'
|
2
|
-
require '
|
3
|
-
|
4
|
-
require 'i18n/tasks/missing'
|
5
|
-
require 'i18n/tasks/prefill'
|
6
|
-
require 'i18n/tasks/unused'
|
2
|
+
require 'i18n/tasks/base_task'
|
7
3
|
require 'i18n/tasks/output/terminal'
|
8
4
|
|
9
5
|
namespace :i18n do
|
10
|
-
desc '
|
11
|
-
task :
|
12
|
-
|
6
|
+
desc 'show missing translations'
|
7
|
+
task :missing => 'i18n:setup' do
|
8
|
+
term_output.missing i18n_tasks.untranslated_keys
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'show unused translations'
|
12
|
+
task :unused => 'i18n:setup' do
|
13
|
+
term_output.unused i18n_tasks.unused_keys
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'normalize translation data: sort and move to the right files'
|
17
|
+
task :normalize => 'i18n:setup' do
|
18
|
+
normalize_store!
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'fill translations with values'
|
22
|
+
namespace :fill do
|
23
|
+
|
24
|
+
desc 'add <key: placeholder || key.humanize> to the base locale'
|
25
|
+
task :add_missing, [:placeholder] => 'i18n:setup' do |t, args|
|
26
|
+
normalize_store!
|
27
|
+
i18n_tasks.fill_blanks!(base_locale) { |keys|
|
28
|
+
keys.map { |key|
|
29
|
+
args[:placeholder] || key.split('.').last.to_s.humanize
|
30
|
+
}
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
desc 'add <key: ""> to each locale'
|
35
|
+
task :with_blanks, [:locales] => 'i18n:setup' do |t, args|
|
36
|
+
normalize_store!
|
37
|
+
[base_locale, *non_base_locales].each do |locale|
|
38
|
+
fill_blanks!(locale) { |blank_keys| blank_keys.map { '' } }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'add <key: Google Translated value> to each non-base locale, uses env GOOGLE_TRANSLATE_API_KEY'
|
43
|
+
task :with_google, [:locales] => 'i18n:setup' do |t, args|
|
44
|
+
normalize_store!
|
45
|
+
non_base_locales(args).each do |locale|
|
46
|
+
fill_blanks!(locale) { |blank_keys|
|
47
|
+
i18n_tasks.google_translate blank_keys.map { |k| t(k) }, to: locale, from: base_locale
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'add <key: base value> to each non-base locale'
|
53
|
+
task :with_base, [:locales] => 'i18n:setup' do |t, args|
|
54
|
+
normalize_store!
|
55
|
+
non_base_locales(args).each do |locale|
|
56
|
+
fill_blanks!(locale) { |blank_keys| blank_keys.map { |k| t(k) } }
|
57
|
+
end
|
58
|
+
end
|
13
59
|
end
|
14
60
|
|
15
|
-
|
16
|
-
task :missing => :environment do
|
61
|
+
task 'i18n:setup' => :environment do
|
17
62
|
if File.exists?('.i18nignore')
|
18
63
|
STDERR.puts 'Looks like you are using .i18ignore. It is no longer used in favour of config/i18n-tasks.yml.'
|
19
64
|
STDERR.puts 'See README.md https://github.com/glebm/i18n-tasks'
|
20
65
|
end
|
21
|
-
I18n::Tasks::Output::Terminal.new.missing I18n::Tasks::Missing.new.find_keys
|
22
66
|
end
|
23
67
|
|
24
|
-
|
25
|
-
|
26
|
-
|
68
|
+
module I18n::Tasks::RakeHelpers
|
69
|
+
extend ActiveSupport::Concern
|
70
|
+
|
71
|
+
included do
|
72
|
+
delegate :t, :locales, :base_locale, :normalize_store!, :fill_blanks!, to: :i18n_tasks
|
73
|
+
|
74
|
+
def i18n_tasks
|
75
|
+
@i18n_tasks ||= I18n::Tasks::BaseTask.new
|
76
|
+
end
|
77
|
+
|
78
|
+
def term_output
|
79
|
+
@term_output ||= I18n::Tasks::Output::Terminal.new
|
80
|
+
end
|
81
|
+
|
82
|
+
def non_base_locales(args = nil)
|
83
|
+
locales_or_all(args) - [base_locale]
|
84
|
+
end
|
85
|
+
|
86
|
+
def locales_or_all(args = nil)
|
87
|
+
args[:locales] ? args[:locales].strip.split(/\s*\+\s*/) : locales
|
88
|
+
end
|
89
|
+
end
|
27
90
|
end
|
91
|
+
|
92
|
+
include I18n::Tasks::RakeHelpers
|
93
|
+
include Term::ANSIColor
|
28
94
|
end
|
data/spec/i18n_tasks_spec.rb
CHANGED
@@ -5,8 +5,11 @@ describe 'rake i18n' do
|
|
5
5
|
describe 'missing' do
|
6
6
|
it 'detects missing or identical' do
|
7
7
|
TestCodebase.capture_stderr do
|
8
|
-
TestCodebase.rake_result('i18n:missing').should be_i18n_keys %w(
|
9
|
-
|
8
|
+
TestCodebase.rake_result('i18n:missing').should be_i18n_keys %w(
|
9
|
+
en.used_but_missing.a en.missing_symbol_key en.relative.index.missing
|
10
|
+
es.missing_in_es.a es.blank_in_es.a es.same_in_es.a
|
11
|
+
)
|
12
|
+
end.should =~ /Missing keys and translations \(6\)/
|
10
13
|
end
|
11
14
|
end
|
12
15
|
|
@@ -18,10 +21,20 @@ describe 'rake i18n' do
|
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
21
|
-
describe '
|
22
|
-
it '
|
24
|
+
describe 'normalize' do
|
25
|
+
it 'moves keys to the corresponding files as per data.write' do
|
26
|
+
TestCodebase.in_test_app_dir {
|
27
|
+
File.exists?('config/locales/devise.en.yml').should be_false
|
28
|
+
TestCodebase.rake_result('i18n:normalize')
|
29
|
+
YAML.load_file('config/locales/devise.en.yml')['en']['devise']['a'].should == 'EN_TEXT'
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'fill:' do
|
35
|
+
it 'with_base' do
|
23
36
|
TestCodebase.in_test_app_dir { YAML.load_file('config/locales/es.yml')['es']['missing_in_es'].should be_nil }
|
24
|
-
TestCodebase.rake_result('i18n:
|
37
|
+
TestCodebase.rake_result('i18n:fill:with_base')
|
25
38
|
TestCodebase.in_test_app_dir {
|
26
39
|
YAML.load_file('config/locales/es.yml')['es']['missing_in_es']['a'].should == 'EN_TEXT'
|
27
40
|
YAML.load_file('config/locales/devise.en.yml')['en']['devise']['a'].should == 'EN_TEXT'
|
@@ -47,7 +60,13 @@ describe 'rake i18n' do
|
|
47
60
|
'ignore_eq_base_all' => {'a' => v},
|
48
61
|
'ignore_eq_base_es' => {'a' => v},
|
49
62
|
'blank_in_es' => {'a' => v},
|
50
|
-
'relative' => {
|
63
|
+
'relative' => {
|
64
|
+
'index' => {
|
65
|
+
'title' => v,
|
66
|
+
'description' => v,
|
67
|
+
'summary' => v,
|
68
|
+
}
|
69
|
+
},
|
51
70
|
'numeric' => {'a' => v_num},
|
52
71
|
'plural' => {'a' => {'one' => v, 'other' => "%{count} #{v}s"}},
|
53
72
|
'devise' => {'a' => v}
|
@@ -5,12 +5,18 @@ RSpec::Matchers.define :be_i18n_keys do |expected|
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def extract_keys(actual)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
actual = actual.split("\n").map(&:presence).compact.map { |row|
|
9
|
+
row.gsub(/\s+/, ' ').strip.split(' ').map(&:presence).compact
|
10
|
+
}
|
11
|
+
if actual[0][1] =~ /[✗∅=]/
|
12
|
+
locale_col = 0
|
13
|
+
key_col = 2
|
14
|
+
else
|
15
|
+
key_col = 0
|
16
|
+
end
|
17
|
+
actual.map { |row|
|
18
|
+
key = row[key_col]
|
19
|
+
key = row[locale_col] + '.' + key if locale_col
|
14
20
|
key = key[0..-2] if key.end_with?(':')
|
15
21
|
key
|
16
22
|
}.compact
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'yaml'
|
2
3
|
|
3
4
|
module TestCodebase
|
4
5
|
extend self
|
5
6
|
AT = 'tmp/test_codebase'
|
6
7
|
|
7
8
|
DEFAULTS = {
|
8
|
-
|
9
|
-
|
9
|
+
'config/locales/en.yml' => {'en' => {}}.to_yaml,
|
10
|
+
'config/locales/es.yml' => {'es' => {}}.to_yaml
|
10
11
|
}
|
11
12
|
|
12
13
|
def setup(files)
|
@@ -32,11 +33,16 @@ module TestCodebase
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def in_test_app_dir(&block)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
return block.call if @in_dir
|
37
|
+
begin
|
38
|
+
pwd = Dir.pwd
|
39
|
+
Dir.chdir AT
|
40
|
+
@in_dir = true
|
41
|
+
block.call
|
42
|
+
ensure
|
43
|
+
Dir.chdir pwd
|
44
|
+
@in_dir = false
|
45
|
+
end
|
40
46
|
end
|
41
47
|
|
42
48
|
def capture_stderr
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- glebm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: easy_translate
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: term-ansicolor
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,15 +144,16 @@ files:
|
|
130
144
|
- lib/i18n/tasks/data_traversal.rb
|
131
145
|
- lib/i18n/tasks/ignore_keys.rb
|
132
146
|
- lib/i18n/tasks/key_pattern_matching.rb
|
133
|
-
- lib/i18n/tasks/
|
147
|
+
- lib/i18n/tasks/missing_keys.rb
|
134
148
|
- lib/i18n/tasks/output/terminal.rb
|
135
149
|
- lib/i18n/tasks/plural_keys.rb
|
136
|
-
- lib/i18n/tasks/prefill.rb
|
137
150
|
- lib/i18n/tasks/railtie.rb
|
138
151
|
- lib/i18n/tasks/relative_keys.rb
|
139
152
|
- lib/i18n/tasks/source_keys.rb
|
153
|
+
- lib/i18n/tasks/translation.rb
|
140
154
|
- lib/i18n/tasks/translation_data.rb
|
141
|
-
- lib/i18n/tasks/
|
155
|
+
- lib/i18n/tasks/untranslated_keys.rb
|
156
|
+
- lib/i18n/tasks/unused_keys.rb
|
142
157
|
- lib/i18n/tasks/version.rb
|
143
158
|
- lib/tasks/i18n-tasks.rake
|
144
159
|
- spec/fixtures/app/assets/javascripts/application.js
|
data/lib/i18n/tasks/missing.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
require 'i18n/tasks/base_task'
|
3
|
-
|
4
|
-
module I18n
|
5
|
-
module Tasks
|
6
|
-
class Missing < BaseTask
|
7
|
-
|
8
|
-
# Get all the missing translations as an array of missing keys as hashes with the following options:
|
9
|
-
# :locale
|
10
|
-
# :key
|
11
|
-
# :type — :blank, :missing, or :eq_base
|
12
|
-
# :base_value — translation value in base locale if one is present
|
13
|
-
# @return [Array<Hash{Symbol => String,Symbol,nil}>]
|
14
|
-
def find_keys
|
15
|
-
other_locales = I18n.available_locales.map(&:to_s) - [base_locale]
|
16
|
-
sort_keys keys_missing_base_value + other_locales.map { |locale| keys_missing_translation(locale) }.flatten(1)
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
# missing keys, i.e. key that are in the code but are not in the base locale data
|
22
|
-
# @return Array{Hash}
|
23
|
-
def keys_missing_base_value
|
24
|
-
find_source_keys.reject { |key|
|
25
|
-
key_has_value?(key, base_locale) || pattern_key?(key) || ignore_key?(key, :missing)
|
26
|
-
}.map { |key| {locale: base_locale, type: :none, key: key} }
|
27
|
-
end
|
28
|
-
|
29
|
-
# present in base locale, but untranslated in another locale
|
30
|
-
# @return Array{Hash}
|
31
|
-
def keys_missing_translation(locale)
|
32
|
-
trn = data[locale]
|
33
|
-
r = []
|
34
|
-
traverse data[base_locale] do |key, base_value|
|
35
|
-
value_in_locale = t(trn, key)
|
36
|
-
if value_in_locale.blank? && !ignore_key?(key, :missing)
|
37
|
-
r << {locale: locale, key: key, type: :blank, base_value: base_value}
|
38
|
-
elsif value_in_locale == base_value && !ignore_key?(key, :eq_base, locale)
|
39
|
-
r << {locale: locale, key: key, type: :eq_base, base_value: base_value}
|
40
|
-
end
|
41
|
-
end
|
42
|
-
r
|
43
|
-
end
|
44
|
-
|
45
|
-
# sort first by locale, then by type
|
46
|
-
# @return Array{Hash}
|
47
|
-
def sort_keys(keys)
|
48
|
-
keys.sort { |a, b|
|
49
|
-
(l = a[:locale] <=> b[:locale]).zero? ? a[:type] <=> b[:type] : l
|
50
|
-
}
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
data/lib/i18n/tasks/prefill.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'i18n/tasks/base_task'
|
2
|
-
|
3
|
-
module I18n
|
4
|
-
module Tasks
|
5
|
-
# Prefill values from base locale data
|
6
|
-
class Prefill < BaseTask
|
7
|
-
def perform
|
8
|
-
I18n.available_locales.map(&:to_s).each do |target_locale|
|
9
|
-
data[target_locale] = data[base_locale].deep_merge(data[target_locale])
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|