i18n-tasks 0.2.22 → 0.3.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|