i18n-tasks 0.2.22 → 0.3.0.rc1
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/CHANGES.md +5 -1
- data/Gemfile +0 -1
- data/README.md +59 -49
- data/bin/i18n-tasks +38 -0
- data/i18n-tasks.gemspec +1 -0
- data/lib/i18n/tasks/commands.rb +121 -0
- data/lib/i18n/tasks/commands_base.rb +54 -0
- data/lib/i18n/tasks/configuration.rb +39 -1
- data/lib/i18n/tasks/data/storage/file_storage.rb +1 -1
- data/lib/i18n/tasks/data_traversal.rb +6 -7
- data/lib/i18n/tasks/fill_tasks.rb +20 -48
- data/lib/i18n/tasks/google_translation.rb +1 -1
- data/lib/i18n/tasks/key.rb +11 -26
- data/lib/i18n/tasks/key/key_group.rb +44 -0
- data/lib/i18n/tasks/key/match_pattern.rb +23 -0
- data/lib/i18n/tasks/key/usages.rb +11 -0
- data/lib/i18n/tasks/key_pattern_matching.rb +6 -2
- data/lib/i18n/tasks/missing_keys.rb +15 -12
- data/lib/i18n/tasks/plural_keys.rb +3 -3
- data/lib/i18n/tasks/reports/base.rb +3 -2
- data/lib/i18n/tasks/reports/spreadsheet.rb +2 -1
- data/lib/i18n/tasks/reports/terminal.rb +6 -6
- data/lib/i18n/tasks/scanners/base_scanner.rb +20 -14
- data/lib/i18n/tasks/scanners/pattern_scanner.rb +31 -5
- data/lib/i18n/tasks/scanners/pattern_with_scope_scanner.rb +75 -0
- data/lib/i18n/tasks/translation_data.rb +32 -11
- data/lib/i18n/tasks/unused_keys.rb +3 -2
- data/lib/i18n/tasks/used_keys.rb +14 -11
- data/lib/i18n/tasks/version.rb +1 -1
- data/lib/tasks/i18n-tasks.rake +34 -85
- data/spec/fixtures/app/controllers/events_controller.rb +23 -3
- data/spec/fixtures/app/views/index.html.slim +4 -1
- data/spec/fixtures/app/views/usages.html.slim +2 -0
- data/spec/fixtures/config/i18n-tasks.yml +1 -1
- data/spec/i18n_tasks_spec.rb +66 -38
- data/spec/pattern_scanner_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/support/capture_std.rb +17 -0
- data/spec/support/fixtures.rb +9 -2
- data/spec/support/test_codebase.rb +5 -18
- data/spec/support/test_codebase_env.rake +4 -2
- data/spec/used_keys_spec.rb +1 -0
- metadata +31 -5
@@ -1,13 +1,12 @@
|
|
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(
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
key.to_s.split('.').inject(hash) { |r, seg| r[seg] if r }
|
4
|
+
def t(key, locale = base_locale)
|
5
|
+
key.to_s.split('.').inject(self.data[locale]) { |r, seg| r[seg] if r }
|
6
|
+
end
|
7
|
+
|
8
|
+
def t_proc(locale = base_locale)
|
9
|
+
proc { |k| t(k, locale) }
|
11
10
|
end
|
12
11
|
|
13
12
|
# traverse => map if yield(k, v)
|
@@ -1,55 +1,27 @@
|
|
1
1
|
module I18n::Tasks::FillTasks
|
2
|
-
def
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
2
|
+
def fill_missing_value(opts = {})
|
3
|
+
opts = opts.merge(
|
4
|
+
keys: proc { |locale| keys_to_fill(locale) }
|
5
|
+
)
|
6
|
+
opts[:value] ||= '' unless opts[:values].present?
|
7
|
+
update_data opts
|
9
8
|
end
|
10
9
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
def fill_missing_google_translate(opts = {})
|
11
|
+
from = opts[:from] || base_locale
|
12
|
+
opts = opts.merge(
|
13
|
+
locales: non_base_locales(opts[:locales]),
|
14
|
+
keys: proc { |locale| keys_to_fill(locale).select(&t_proc(from)).select { |k| t(k).is_a?(String) } },
|
15
|
+
values: proc { |keys, locale|
|
16
|
+
google_translate keys.zip(keys.map(&t_proc(from))),
|
17
|
+
to: locale,
|
18
|
+
from: from
|
19
|
+
}
|
20
|
+
)
|
21
|
+
update_data opts
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
21
|
-
|
22
|
-
locales = non_base_locales(locales)
|
23
|
-
normalize_store! locales
|
24
|
-
locales.each do |locale|
|
25
|
-
blank_keys = keys_missing_from_locale(locale).key_names.select { |k|
|
26
|
-
tr = t(k)
|
27
|
-
tr.present? && tr.is_a?(String)
|
28
|
-
}
|
29
|
-
if blank_keys.present?
|
30
|
-
data[locale] = data[locale].deep_merge(
|
31
|
-
list_to_tree google_translate(blank_keys.zip(blank_keys.map { |k| t(k) }), to: locale, from: base_locale)
|
32
|
-
)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def fill_with_base_values!(locales = nil)
|
38
|
-
normalize_store! base_locale
|
39
|
-
locales = non_base_locales(locales)
|
40
|
-
normalize_store! locales
|
41
|
-
locales.each do |locale|
|
42
|
-
set_blank_values! locale do |blank_keys|
|
43
|
-
blank_keys.map { |k| t(k) }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# fill blank values with values from passed block
|
49
|
-
# @param [String] locale
|
50
|
-
def set_blank_values!(locale = base_locale, &fill_with)
|
51
|
-
blank_keys = keys_missing_from_locale(locale).key_names
|
52
|
-
list = blank_keys.zip fill_with.call(blank_keys)
|
53
|
-
data[locale] = data[locale].deep_merge(list_to_tree(list))
|
24
|
+
def keys_to_fill(locale)
|
25
|
+
keys_missing_from_locale(locale).key_names
|
54
26
|
end
|
55
27
|
end
|
@@ -9,7 +9,7 @@ module I18n::Tasks::GoogleTranslation
|
|
9
9
|
opts[:key] = key
|
10
10
|
end
|
11
11
|
if opts[:key].blank?
|
12
|
-
$stderr.puts(Term::ANSIColor.red Term::ANSIColor.yellow 'You may need to provide Google API key as GOOGLE_TRANSLATE_API_KEY or in config/i18n-tasks.yml.
|
12
|
+
$stderr.puts(Term::ANSIColor.red Term::ANSIColor.yellow 'You may need to provide Google API key as GOOGLE_TRANSLATE_API_KEY env var or translation.api_key in config/i18n-tasks.yml.
|
13
13
|
You can obtain the key at https://code.google.com/apis/console.')
|
14
14
|
end
|
15
15
|
list.group_by { |k_v| k_v[0].end_with?('_html'.freeze) ? opts.merge(html: true) : opts.merge(format: 'text') }.map do |opts, strings|
|
data/lib/i18n/tasks/key.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
|
+
require 'i18n/tasks/key/key_group'
|
2
|
+
require 'i18n/tasks/key/match_pattern'
|
3
|
+
require 'i18n/tasks/key/usages'
|
4
|
+
|
1
5
|
module I18n
|
2
6
|
module Tasks
|
3
7
|
class Key
|
4
|
-
|
8
|
+
include ::I18n::Tasks::Key::KeyGroup
|
9
|
+
include ::I18n::Tasks::Key::MatchPattern
|
10
|
+
include ::I18n::Tasks::Key::Usages
|
11
|
+
|
12
|
+
attr_accessor :own_attr
|
5
13
|
|
6
14
|
def initialize(key_or_attr, own_attr = {})
|
7
15
|
@own_attr = if key_or_attr.is_a?(Array)
|
@@ -14,14 +22,6 @@ module I18n
|
|
14
22
|
@own_attr[:key] = @own_attr[:key].to_s
|
15
23
|
end
|
16
24
|
|
17
|
-
def [](prop)
|
18
|
-
@own_attr[prop] || key_group.attr[prop]
|
19
|
-
end
|
20
|
-
|
21
|
-
def attr
|
22
|
-
key_group.attr.merge @own_attr
|
23
|
-
end
|
24
|
-
|
25
25
|
def ==(other)
|
26
26
|
self.attr == other.attr
|
27
27
|
end
|
@@ -30,29 +30,14 @@ module I18n
|
|
30
30
|
"#<#{self.class.name}#{attr.inspect}>"
|
31
31
|
end
|
32
32
|
|
33
|
-
def clone_orphan
|
34
|
-
clone.tap { |k| k.key_group = nil }
|
35
|
-
end
|
36
|
-
|
37
33
|
def key
|
38
34
|
@own_attr[:key]
|
39
35
|
end
|
36
|
+
|
40
37
|
alias to_s key
|
41
38
|
|
42
39
|
def value
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
def locale
|
47
|
-
self[:locale]
|
48
|
-
end
|
49
|
-
|
50
|
-
def type
|
51
|
-
self[:type]
|
52
|
-
end
|
53
|
-
|
54
|
-
def src_pos
|
55
|
-
self[:src_pos]
|
40
|
+
@own_attr[:value]
|
56
41
|
end
|
57
42
|
end
|
58
43
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module I18n
|
2
|
+
module Tasks
|
3
|
+
class Key
|
4
|
+
module KeyGroup
|
5
|
+
attr_accessor :key_group
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.class_eval do
|
9
|
+
extend ClassMethods
|
10
|
+
delegate_to_attr :[], :key?
|
11
|
+
delegate_to_attr_accessor :type, :locale
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def attr
|
16
|
+
key_group.attr.merge @own_attr
|
17
|
+
end
|
18
|
+
|
19
|
+
def clone_orphan
|
20
|
+
clone.tap { |k| k.key_group = nil }
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def delegate_to_attr_accessor(*methods)
|
25
|
+
methods.each do |m|
|
26
|
+
define_method(m) do
|
27
|
+
@own_attr[m] || (kg = key_group) && kg.attr[m]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def delegate_to_attr(*methods)
|
33
|
+
methods.each do |m|
|
34
|
+
define_method(m) do |*args|
|
35
|
+
@own_attr.send(m, *args) ||
|
36
|
+
(kg = key_group) && kg.attr.send(m, *args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module I18n
|
2
|
+
module Tasks
|
3
|
+
class Key
|
4
|
+
module MatchPattern
|
5
|
+
def key_match_pattern
|
6
|
+
@key_match_pattern ||= begin
|
7
|
+
k = key
|
8
|
+
"#{k.gsub(/\#{.*?}/, '*')}#{'*' if k.end_with?('.')}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# A key interpolated with expression
|
13
|
+
def expr?
|
14
|
+
if @is_expr.nil?
|
15
|
+
k = key
|
16
|
+
@is_expr = (k =~ /\#{.*?}/ || k.end_with?('.'))
|
17
|
+
end
|
18
|
+
@is_expr
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -17,12 +17,16 @@ module I18n::Tasks::KeyPatternMatching
|
|
17
17
|
# : matches a single key
|
18
18
|
# {a, b.c} match any in set, can use : and *, match is captured
|
19
19
|
def compile_key_pattern(key_pattern)
|
20
|
-
|
20
|
+
return key_pattern if key_pattern.is_a?(Regexp)
|
21
|
+
/\A#{key_pattern_re_body(key_pattern)}\z/
|
22
|
+
end
|
23
|
+
|
24
|
+
def key_pattern_re_body(key_pattern)
|
25
|
+
key_pattern.
|
21
26
|
gsub(/\./, '\.').
|
22
27
|
gsub(/\*/, '.*').
|
23
28
|
gsub(/:/, '(?<=^|\.)[^.]+?(?=\.|$)').
|
24
29
|
gsub(/\{(.*?)}/) { "(#{$1.strip.gsub /\s*,\s*/, '|'})" }
|
25
|
-
}$/
|
26
30
|
end
|
27
31
|
|
28
32
|
# @return [Array<String>] keys sans passed patterns
|
@@ -3,21 +3,24 @@ module I18n::Tasks
|
|
3
3
|
# @param [:missing_from_base, :missing_from_locale, :eq_base] type (default nil)
|
4
4
|
# @return [KeyGroup]
|
5
5
|
def missing_keys(opts = {})
|
6
|
-
type = opts[:type]
|
7
6
|
locales = non_base_locales(opts[:locales])
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
type = opts[:type]
|
8
|
+
unless type
|
9
|
+
types = opts[:types] || missing_keys_types
|
10
|
+
opts = opts.except(:types).merge(locales: locales)
|
11
|
+
return types.map { |t| missing_keys(opts.merge(type: t)) }.reduce(:+)
|
12
|
+
end
|
13
|
+
if type == :missing_from_base
|
14
|
+
keys_missing_from_base
|
14
15
|
else
|
15
|
-
|
16
|
-
missing_keys(type: :eq_base, locales: locales) +
|
17
|
-
missing_keys(type: :missing_from_locale, locales: locales)
|
16
|
+
locales.map { |locale| send("keys_#{type}", locale) }.reduce(:+) || KeyGroup.new([])
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
20
|
+
def missing_keys_types
|
21
|
+
@missing_keys_types ||= [:missing_from_base, :eq_base, :missing_from_locale]
|
22
|
+
end
|
23
|
+
|
21
24
|
def untranslated_keys(locales = nil)
|
22
25
|
I18n::Tasks.warn_deprecated("#untranslated_keys. Please use #missing_keys instead")
|
23
26
|
missing_keys(locales: locales)
|
@@ -29,7 +32,7 @@ module I18n::Tasks
|
|
29
32
|
KeyGroup.new(
|
30
33
|
used_keys.keys.reject { |k|
|
31
34
|
key = k.key
|
32
|
-
key_value?(key, base_locale) ||
|
35
|
+
k.expr? || key_value?(key, base_locale) || ignore_key?(key, :missing)
|
33
36
|
}.map(&:clone_orphan), type: :missing_from_base, locale: base_locale)
|
34
37
|
end
|
35
38
|
end
|
@@ -49,7 +52,7 @@ module I18n::Tasks
|
|
49
52
|
def keys_eq_base(locale)
|
50
53
|
@keys_eq_base ||= KeyGroup.new(
|
51
54
|
traverse_map_if(data[base_locale]) { |key, base_value|
|
52
|
-
key if base_value == t(
|
55
|
+
key if base_value == t(key, locale) && !ignore_key?(key, :eq_base, locale)
|
53
56
|
}, type: :eq_base, locale: locale)
|
54
57
|
end
|
55
58
|
end
|
@@ -5,13 +5,13 @@ module I18n::Tasks::PluralKeys
|
|
5
5
|
# @param [String] locale to pull key data from
|
6
6
|
# @return the base form if the key is a specific plural form (e.g. apple for apple.many), and the key as passed otherwise
|
7
7
|
def depluralize_key(locale = base_locale, key)
|
8
|
-
return key if key !~ PLURAL_KEY_RE || t(
|
8
|
+
return key if key !~ PLURAL_KEY_RE || t(key, locale).is_a?(Hash)
|
9
9
|
parent_key = key.split('.')[0..-2] * '.'
|
10
|
-
plural_versions = t(
|
10
|
+
plural_versions = t(parent_key, locale)
|
11
11
|
if plural_versions.is_a?(Hash) && plural_versions.all? { |k, v| ".#{k}" =~ PLURAL_KEY_RE && !v.is_a?(Hash) }
|
12
12
|
parent_key
|
13
13
|
else
|
14
14
|
key
|
15
15
|
end
|
16
16
|
end
|
17
|
-
end
|
17
|
+
end
|
@@ -2,11 +2,12 @@
|
|
2
2
|
module I18n::Tasks::Reports
|
3
3
|
class Base
|
4
4
|
|
5
|
-
def initialize
|
6
|
-
@task =
|
5
|
+
def initialize(task = I18n::Tasks::BaseTask.new)
|
6
|
+
@task = task
|
7
7
|
end
|
8
8
|
|
9
9
|
attr_reader :task
|
10
|
+
delegate :base_locale, :locales, to: :task
|
10
11
|
|
11
12
|
MISSING_TYPES = {
|
12
13
|
missing_from_base: {glyph: '✗', summary: 'missing from base locale'},
|
@@ -4,7 +4,8 @@ require 'fileutils'
|
|
4
4
|
module I18n::Tasks::Reports
|
5
5
|
class Spreadsheet < Base
|
6
6
|
|
7
|
-
def save_report(path =
|
7
|
+
def save_report(path = nil)
|
8
|
+
path = 'tmp/i18n-report.xlsx' if path.blank?
|
8
9
|
p = Axlsx::Package.new
|
9
10
|
add_missing_sheet p.workbook
|
10
11
|
add_unused_sheet p.workbook
|
@@ -14,12 +14,12 @@ module I18n
|
|
14
14
|
|
15
15
|
print_info "#{bold 'Types:'} #{missing_types.values.map { |t| "#{t[:glyph]} #{t[:summary]}" } * ', '}"
|
16
16
|
|
17
|
-
print_table headings: [magenta(bold('Locale')), bold('Type'), magenta('i18n Key'), bold(cyan "Base value (#{base_locale})")] do |t|
|
17
|
+
print_table headings: [magenta(bold('Locale')), bold('Type'), magenta(bold 'i18n Key'), bold(cyan "Base value (#{base_locale})")] do |t|
|
18
18
|
t.rows = keys.map { |key|
|
19
19
|
glyph = missing_types[key.type][:glyph]
|
20
20
|
glyph = {missing_from_base: red(glyph), missing_from_locale: yellow(glyph), eq_base: bold(blue(glyph))}[key.type]
|
21
21
|
if key[:type] == :missing_from_base
|
22
|
-
locale = magenta
|
22
|
+
locale = magenta key.locale
|
23
23
|
base_value = ''
|
24
24
|
else
|
25
25
|
locale = magenta key.locale
|
@@ -28,7 +28,7 @@ module I18n
|
|
28
28
|
[{value: locale, alignment: :center},
|
29
29
|
{value: glyph, alignment: :center},
|
30
30
|
magenta(key[:key]),
|
31
|
-
base_value]
|
31
|
+
cyan(base_value)]
|
32
32
|
}
|
33
33
|
end
|
34
34
|
else
|
@@ -41,8 +41,8 @@ module I18n
|
|
41
41
|
keys.sort_by_attr!(key: :asc)
|
42
42
|
if keys.present?
|
43
43
|
keys.each do |k|
|
44
|
-
puts "#{bold "#{k.key}"} #{green
|
45
|
-
k
|
44
|
+
puts "#{bold "#{k.key}"} #{green(k.usages.size.to_s) if k.usages.size > 1}"
|
45
|
+
k.usages.each do |u|
|
46
46
|
line = u[:line].dup.tap { |line|
|
47
47
|
line.strip!
|
48
48
|
line.sub!(/(.*?)(#{k[:key]})(.*)$/) { dark($1) + underline($2) + dark($3)}
|
@@ -58,7 +58,7 @@ module I18n
|
|
58
58
|
def unused_keys(keys = task.unused_keys)
|
59
59
|
print_title unused_title(keys)
|
60
60
|
if keys.present?
|
61
|
-
print_table headings: [bold(magenta('i18n Key')), cyan("Base value (#{base_locale})")] do |t|
|
61
|
+
print_table headings: [bold(magenta('i18n Key')), bold(cyan("Base value (#{base_locale})"))] do |t|
|
62
62
|
t.rows = keys.map { |k| [magenta(k.key), cyan(k.value)] }
|
63
63
|
end
|
64
64
|
else
|
@@ -5,17 +5,22 @@ module I18n::Tasks::Scanners
|
|
5
5
|
include ::I18n::Tasks::KeyPatternMatching
|
6
6
|
attr_reader :config, :key_filter, :record_usages
|
7
7
|
|
8
|
-
def initialize(config)
|
8
|
+
def initialize(config = {})
|
9
9
|
@config = config.dup.with_indifferent_access.tap do |conf|
|
10
10
|
conf[:paths] = %w(app/) if conf[:paths].blank?
|
11
11
|
conf[:include] = Array(conf[:include]) if conf[:include].present?
|
12
|
-
conf
|
12
|
+
if conf.key?(:exclude)
|
13
|
+
conf[:exclude] = Array(conf[:exclude])
|
14
|
+
else
|
15
|
+
# exclude common binary extensions by default (images and fonts)
|
16
|
+
conf[:exclude] = %w(*.jpg *.png *.gif *.svg *.ico *.eot *.ttf *.woff)
|
17
|
+
end
|
13
18
|
end
|
14
19
|
@record_usages = false
|
15
20
|
end
|
16
21
|
|
17
22
|
def key_filter=(value)
|
18
|
-
@key_filter
|
23
|
+
@key_filter = value
|
19
24
|
@key_filter_pattern = compile_key_pattern(value) if @key_filter
|
20
25
|
end
|
21
26
|
|
@@ -24,15 +29,16 @@ module I18n::Tasks::Scanners
|
|
24
29
|
if @record_usages
|
25
30
|
keys_with_usages
|
26
31
|
else
|
27
|
-
@keys ||= traverse_files { |path| scan_file(path, read_file(path)).map(&:key) }.reduce(:+).uniq
|
32
|
+
@keys ||= (traverse_files { |path| scan_file(path, read_file(path)).map(&:key) }.reduce(:+) || []).uniq
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
31
36
|
def keys_with_usages
|
32
37
|
with_usages do
|
33
|
-
traverse_files { |path|
|
38
|
+
keys = traverse_files { |path|
|
34
39
|
::I18n::Tasks::KeyGroup.new(scan_file(path, read_file(path)), src_path: path)
|
35
|
-
}.map(&:keys).reduce(:+)
|
40
|
+
}.map(&:keys).reduce(:+) || []
|
41
|
+
keys.group_by(&:key).map { |key, key_usages|
|
36
42
|
{key: key, usages: key_usages.map { |usage| usage[:src].merge(path: usage[:src_path]) }}
|
37
43
|
}
|
38
44
|
end
|
@@ -53,7 +59,12 @@ module I18n::Tasks::Scanners
|
|
53
59
|
# @return [Array] Results of block calls
|
54
60
|
def traverse_files
|
55
61
|
result = []
|
56
|
-
|
62
|
+
paths = config[:paths].select { |p| File.exists?(p) }
|
63
|
+
if paths.empty?
|
64
|
+
STDERR.puts Term::ANSIColor.yellow("i18n-tasks: [WARN] search.paths (#{config[:paths]}) do not exist")
|
65
|
+
return result
|
66
|
+
end
|
67
|
+
Find.find(*paths) do |path|
|
57
68
|
next if File.directory?(path) ||
|
58
69
|
config[:include] && !path_fnmatch_any?(path, config[:include]) ||
|
59
70
|
path_fnmatch_any?(path, config[:exclude])
|
@@ -65,6 +76,7 @@ module I18n::Tasks::Scanners
|
|
65
76
|
def path_fnmatch_any?(path, globs)
|
66
77
|
globs.any? { |glob| File.fnmatch(glob, path) }
|
67
78
|
end
|
79
|
+
|
68
80
|
protected :path_fnmatch_any?
|
69
81
|
|
70
82
|
def with_key_filter(key_filter = nil)
|
@@ -97,16 +109,10 @@ module I18n::Tasks::Scanners
|
|
97
109
|
}}
|
98
110
|
end
|
99
111
|
|
100
|
-
def extract_key_from_match(match, path)
|
101
|
-
key = strip_literal(match[0])
|
102
|
-
key = absolutize_key(key, path) if path && key.start_with?('.')
|
103
|
-
key
|
104
|
-
end
|
105
|
-
|
106
112
|
# remove the leading colon and unwrap quotes from the key match
|
107
113
|
def strip_literal(literal)
|
108
114
|
key = literal
|
109
|
-
key
|
115
|
+
key = key[1..-1] if ':' == key[0]
|
110
116
|
key = key[1..-2] if %w(' ").include?(key[0])
|
111
117
|
key
|
112
118
|
end
|