i18n-tasks 0.2.15 → 0.2.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +10 -1
- data/README.md +10 -6
- data/lib/i18n/tasks/configuration.rb +0 -23
- data/lib/i18n/tasks/data/yaml.rb +4 -9
- data/lib/i18n/tasks/key_pattern_matching.rb +1 -4
- data/lib/i18n/tasks/relative_keys.rb +16 -13
- data/lib/i18n/tasks/scanners/base_scanner.rb +65 -0
- data/lib/i18n/tasks/scanners/pattern_scanner.rb +26 -0
- data/lib/i18n/tasks/source_keys.rb +11 -42
- data/lib/i18n/tasks/version.rb +1 -1
- data/spec/{source_keys_spec.rb → pattern_scanner_spec.rb} +3 -4
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5078ec1751923ec5ebfcd79893a7bdca8ae618f
|
4
|
+
data.tar.gz: e29ebefde17fdbefc0408452466e5f1a19a2be71
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55359af166cef34bd9c4708a0a482d5107d54d347615172b39803559355d8738e6da03901562a509ae8b6474cdda7ee6b19d4044a1978520d7cee9e9d81bfacb
|
7
|
+
data.tar.gz: a05eb27caad0776691685f6e70ce271084adf7ae4d71c97f1898736501ddd9b7a5a47627dd1f4623349764dd281aa6ef344aa763190ce38799d882bd565933f5
|
data/CHANGES.md
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
## v0.2.
|
1
|
+
## v0.2.16
|
2
|
+
|
3
|
+
* Key search extracted into its own class, and a custom scanner can now be provided.
|
4
|
+
* Removed support for deprecated settings
|
5
|
+
|
6
|
+
## v0.2.15
|
7
|
+
|
8
|
+
* More robust I18n.t call detection (detect I18n.translate and multiline calls)
|
9
|
+
|
10
|
+
## v0.2.14
|
2
11
|
|
3
12
|
* Google Translate fixes: preserve interpolations, set correct format based on the key (text or html).
|
4
13
|
|
data/README.md
CHANGED
@@ -172,6 +172,9 @@ relative_roots:
|
|
172
172
|
- app/views-mobile
|
173
173
|
```
|
174
174
|
|
175
|
+
It is also possible to use a key scanner by setting `search.scanner`.
|
176
|
+
See [the default scanner](/lib/i18n/tasks/scanners/pattern_scanner.rb) for reference.
|
177
|
+
|
175
178
|
|
176
179
|
### Fine-tuning
|
177
180
|
|
@@ -224,18 +227,19 @@ This is how you can do it with rspec:
|
|
224
227
|
require 'i18n/tasks'
|
225
228
|
require 'i18n/tasks/base_task'
|
226
229
|
|
227
|
-
# spec/
|
230
|
+
# spec/i18n_keys_spec.rb
|
228
231
|
require 'spec_helper'
|
229
|
-
describe '
|
232
|
+
describe 'translation keys' do
|
230
233
|
let(:i18n) { I18n::Tasks::BaseTask.new }
|
231
234
|
|
232
|
-
it 'are all
|
233
|
-
i18n.
|
235
|
+
it 'are all present' do
|
236
|
+
expect(i18n.untranslated_keys).to have(0).keys
|
234
237
|
end
|
235
238
|
|
236
|
-
it 'are all
|
237
|
-
i18n.
|
239
|
+
it 'are all used' do
|
240
|
+
expect(i18n.unused_keys).to have(0).keys
|
238
241
|
end
|
242
|
+
|
239
243
|
end
|
240
244
|
```
|
241
245
|
|
@@ -26,33 +26,10 @@ module I18n::Tasks::Configuration
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
DEFAULT_PATTERN = /\bt(?:ranslate)?[( ]\s*(:?".+?"|:?'.+?'|:\w+)/
|
30
|
-
# search config
|
31
|
-
# @return [Hash{String => String,Hash,Array}]
|
32
|
-
def search_config
|
33
|
-
@config_sections[:search] ||= begin
|
34
|
-
if config.key?(:grep)
|
35
|
-
config[:search] ||= config.delete(:grep)
|
36
|
-
I18n::Tasks.warn_deprecated 'please rename "grep" key to "search" in config/i18n-tasks.yml'
|
37
|
-
end
|
38
|
-
search_config = (config[:search] || {}).with_indifferent_access
|
39
|
-
search_config.tap do |conf|
|
40
|
-
conf[:paths] = %w(app/) if conf[:paths].blank?
|
41
|
-
conf[:include] = Array(conf[:include]) if conf[:include].present?
|
42
|
-
conf[:exclude] = Array(conf[:exclude])
|
43
|
-
conf[:pattern] = conf[:pattern].present? ? Regexp.new(conf[:pattern]) : DEFAULT_PATTERN
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
29
|
def relative_roots
|
49
30
|
@config_sections[:relative_roots] ||= config[:relative_roots].presence || %w(app/views)
|
50
31
|
end
|
51
32
|
|
52
|
-
def relative_roots=(paths)
|
53
|
-
@config_sections[:relative_roots] = paths
|
54
|
-
end
|
55
|
-
|
56
33
|
# translation config
|
57
34
|
# @return [Hash{String => String,Hash,Array}]
|
58
35
|
def translation_config
|
data/lib/i18n/tasks/data/yaml.rb
CHANGED
@@ -19,14 +19,9 @@ module I18n::Tasks
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def config=(config)
|
22
|
-
opt
|
23
|
-
|
24
|
-
|
25
|
-
::I18n::Tasks.warn_deprecated 'please rename "data.paths" key to "data.read" in config/i18n-tasks.yml'
|
26
|
-
end
|
27
|
-
opt = DEFAULTS.deep_merge(opt)
|
28
|
-
@read = opt[:read]
|
29
|
-
@write = opt[:write].map { |x| x.is_a?(String) ? ['*', x] : x }.map { |x|
|
22
|
+
opt = DEFAULTS.deep_merge((config || {}).with_indifferent_access)
|
23
|
+
@read = opt[:read]
|
24
|
+
@write = opt[:write].map { |x| x.is_a?(String) ? ['*', x] : x }.map { |x|
|
30
25
|
[compile_key_pattern(x[0]), x[1]]
|
31
26
|
}
|
32
27
|
@locale_data = {}
|
@@ -34,7 +29,7 @@ module I18n::Tasks
|
|
34
29
|
|
35
30
|
# get locale tree
|
36
31
|
def get(locale)
|
37
|
-
locale
|
32
|
+
locale = locale.to_s
|
38
33
|
@locale_data[locale] ||= begin
|
39
34
|
@read.map do |path|
|
40
35
|
Dir.glob path % {locale: locale}
|
@@ -17,9 +17,6 @@ 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
|
-
if key_pattern.end_with? '.'
|
21
|
-
I18n::Tasks.warn_deprecated %Q(please change pattern "#{key_pattern}" to "#{key_pattern += '*'}" in config/i18n-tasks.yml)
|
22
|
-
end
|
23
20
|
/^#{key_pattern.
|
24
21
|
gsub(/\./, '\.').
|
25
22
|
gsub(/\*/, '.*').
|
@@ -43,4 +40,4 @@ module I18n::Tasks::KeyPatternMatching
|
|
43
40
|
/^(?:#{prefixes.map { |p| Regexp.escape(p) }.join('|')})/
|
44
41
|
end
|
45
42
|
end
|
46
|
-
end
|
43
|
+
end
|
@@ -1,15 +1,18 @@
|
|
1
|
-
module I18n
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
module I18n
|
2
|
+
module Tasks
|
3
|
+
module RelativeKeys
|
4
|
+
# @param key [String] relative i18n key (starts with a .)
|
5
|
+
# @param path [String] path to the file containing the key
|
6
|
+
# @return [String] absolute version of the key
|
7
|
+
def absolutize_key(key, path, roots = relative_roots)
|
8
|
+
# normalized path
|
9
|
+
path = File.expand_path path
|
10
|
+
(path_root = roots.map { |path| File.expand_path path }.sort.reverse.detect { |root| path.start_with?(root + '/') }) or
|
11
|
+
raise "No relative key root detected for \"#{key}\" at #{path}. Please set relative_roots in config/i18n-tasks.yml (currently set to #{relative_roots})"
|
12
|
+
# key prefix based on path
|
13
|
+
prefix = path.gsub(%r(#{path_root}/|(\.[^/]+)*$), '').tr('/', '.').gsub(%r(\._), '.')
|
14
|
+
"#{prefix}#{key}"
|
15
|
+
end
|
16
|
+
end
|
14
17
|
end
|
15
18
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'i18n/tasks/relative_keys'
|
2
|
+
module I18n::Tasks::Scanners
|
3
|
+
class BaseScanner
|
4
|
+
include ::I18n::Tasks::RelativeKeys
|
5
|
+
attr_reader :config
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@config = config.dup.with_indifferent_access.tap do |conf|
|
9
|
+
conf[:paths] = %w(app/) if conf[:paths].blank?
|
10
|
+
conf[:include] = Array(conf[:include]) if conf[:include].present?
|
11
|
+
conf[:exclude] = Array(conf[:exclude])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Array] found key usages, absolutized and unique
|
16
|
+
def keys
|
17
|
+
@keys ||= traverse_files { |path| scan_file(path) }.flatten.uniq
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [String] keys used in file (unimplemented)
|
21
|
+
def scan_file(path)
|
22
|
+
raise 'Unimplemented'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Run given block for every relevant file, according to config
|
26
|
+
# @return [Array] Results of block calls
|
27
|
+
def traverse_files
|
28
|
+
result = []
|
29
|
+
Find.find(*config[:paths]) do |path|
|
30
|
+
next if File.directory?(path)
|
31
|
+
next if config[:include] and !config[:include].any? { |glob| File.fnmatch(glob, path) }
|
32
|
+
next if config[:exclude].any? { |glob| File.fnmatch(glob, path) }
|
33
|
+
result << yield(path)
|
34
|
+
end
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def extract_key_from_match(match, path)
|
41
|
+
key = strip_literal(match[0])
|
42
|
+
key = absolutize_key(key, path) if path && key.start_with?('.')
|
43
|
+
key
|
44
|
+
end
|
45
|
+
|
46
|
+
# remove the leading colon and unwrap quotes from the key match
|
47
|
+
def strip_literal(literal)
|
48
|
+
key = literal
|
49
|
+
key.slice!(0) if ':' == key[0]
|
50
|
+
key = key[1..-2] if %w(' ").include?(key[0])
|
51
|
+
key
|
52
|
+
end
|
53
|
+
|
54
|
+
VALID_KEY_RE = /^[\w.\#{}]+$/
|
55
|
+
|
56
|
+
def valid_key?(key)
|
57
|
+
key =~ VALID_KEY_RE
|
58
|
+
end
|
59
|
+
|
60
|
+
def relative_roots
|
61
|
+
config[:relative_roots]
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Scans for I18n.t usages
|
2
|
+
require 'i18n/tasks/scanners/base_scanner'
|
3
|
+
module I18n::Tasks::Scanners
|
4
|
+
class PatternScanner < BaseScanner
|
5
|
+
LITERAL_RE = /:?".+?"|:?'.+?'|:\w+/
|
6
|
+
DEFAULT_PATTERN = /\bt(?:ranslate)?[( ]\s*(#{LITERAL_RE})/
|
7
|
+
|
8
|
+
# Extract i18n keys from file based on the pattern. The pattern must capture key literal.
|
9
|
+
# @return [String] keys found in file
|
10
|
+
def scan_file(path)
|
11
|
+
keys = []
|
12
|
+
File.open(path, 'rb') do |f|
|
13
|
+
f.read.scan(pattern) do |match|
|
14
|
+
key = extract_key_from_match(match, path)
|
15
|
+
keys << key if valid_key?(key)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
keys
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
def pattern
|
23
|
+
@pattern ||= config[:pattern].present? ? Regexp.new(config[:pattern]) : DEFAULT_PATTERN
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,12 +1,19 @@
|
|
1
1
|
require 'find'
|
2
|
+
require 'i18n/tasks/scanners/pattern_scanner'
|
2
3
|
|
3
4
|
module I18n::Tasks::SourceKeys
|
4
|
-
# find all keys in the source (relative keys are
|
5
|
+
# find all keys in the source (relative keys are absolutized)
|
5
6
|
# @return [Array<String>]
|
6
7
|
def find_source_keys
|
7
|
-
@source_keys ||=
|
8
|
-
|
9
|
-
|
8
|
+
@source_keys ||= scanner.keys
|
9
|
+
end
|
10
|
+
|
11
|
+
def scanner
|
12
|
+
@scanner ||= begin
|
13
|
+
search_config = config[:search].with_indifferent_access
|
14
|
+
class_name = search_config[:scanner] || '::I18n::Tasks::Scanners::PatternScanner'
|
15
|
+
class_name.constantize.new search_config.merge(relative_roots: relative_roots)
|
16
|
+
end
|
10
17
|
end
|
11
18
|
|
12
19
|
# whether the key is used in the source
|
@@ -26,42 +33,4 @@ module I18n::Tasks::SourceKeys
|
|
26
33
|
@pattern_keys_prefixes ||=
|
27
34
|
find_source_keys.select { |k| k =~ /\#{.*?}/ || k.ends_with?('.') }.map { |k| k.split(/\.?#/)[0].presence }.compact
|
28
35
|
end
|
29
|
-
|
30
|
-
# Run given block for every relevant file, according to search_config
|
31
|
-
# @return [Array] Results of block calls
|
32
|
-
def traverse_files
|
33
|
-
result = []
|
34
|
-
Find.find(*search_config[:paths]) do |path|
|
35
|
-
next if File.directory?(path)
|
36
|
-
next if search_config[:include] and !search_config[:include].any? { |glob| File.fnmatch(glob, path) }
|
37
|
-
next if search_config[:exclude].any? { |glob| File.fnmatch(glob, path) }
|
38
|
-
result << yield(path)
|
39
|
-
end
|
40
|
-
result
|
41
|
-
end
|
42
|
-
|
43
|
-
# Extract i18n keys from file
|
44
|
-
# @return [String] keys used in file (absolutized and unique)
|
45
|
-
def extract_keys(path)
|
46
|
-
keys = []
|
47
|
-
File.open(path, 'rb') do |f|
|
48
|
-
f.read.scan(search_config[:pattern]) do |match|
|
49
|
-
key = parse_key(match)
|
50
|
-
key = absolutize_key(key, path) if key.start_with? '.'
|
51
|
-
if key =~ /^[\w.\#{}]+$/
|
52
|
-
keys << key
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
keys
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
# remove the leading colon and unwrap quotes from the key match
|
61
|
-
def parse_key(match)
|
62
|
-
key = match[0]
|
63
|
-
key.slice!(0) if ':' == key[0]
|
64
|
-
key = key[1..-2] if %w(' ").include?(key[0])
|
65
|
-
key
|
66
|
-
end
|
67
36
|
end
|
data/lib/i18n/tasks/version.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe '
|
4
|
-
|
5
|
-
|
6
|
-
let!(:pattern) { task.search_config[:pattern] }
|
3
|
+
describe 'Pattern Scanner' do
|
4
|
+
describe 'default pattern' do
|
5
|
+
let!(:pattern) { I18n::Tasks::Scanners::PatternScanner::DEFAULT_PATTERN }
|
7
6
|
|
8
7
|
['t "a.b"', "t 'a.b'", 't("a.b")', "t('a.b')",
|
9
8
|
"t('a.b', :arg => val)", "t('a.b', arg: val)",
|
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.2.
|
4
|
+
version: 0.2.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- glebm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -213,6 +213,8 @@ files:
|
|
213
213
|
- lib/i18n/tasks/reports/base.rb
|
214
214
|
- lib/i18n/tasks/reports/spreadsheet.rb
|
215
215
|
- lib/i18n/tasks/reports/terminal.rb
|
216
|
+
- lib/i18n/tasks/scanners/base_scanner.rb
|
217
|
+
- lib/i18n/tasks/scanners/pattern_scanner.rb
|
216
218
|
- lib/i18n/tasks/source_keys.rb
|
217
219
|
- lib/i18n/tasks/translation_data.rb
|
218
220
|
- lib/i18n/tasks/untranslated_keys.rb
|
@@ -227,9 +229,9 @@ files:
|
|
227
229
|
- spec/google_translate_spec.rb
|
228
230
|
- spec/i18n_tasks_spec.rb
|
229
231
|
- spec/key_pattern_matching_spec.rb
|
232
|
+
- spec/pattern_scanner_spec.rb
|
230
233
|
- spec/readme_spec.rb
|
231
234
|
- spec/relative_keys_spec.rb
|
232
|
-
- spec/source_keys_spec.rb
|
233
235
|
- spec/spec_helper.rb
|
234
236
|
- spec/support/fixtures.rb
|
235
237
|
- spec/support/i18n_tasks_output_matcher.rb
|
@@ -272,9 +274,9 @@ test_files:
|
|
272
274
|
- spec/google_translate_spec.rb
|
273
275
|
- spec/i18n_tasks_spec.rb
|
274
276
|
- spec/key_pattern_matching_spec.rb
|
277
|
+
- spec/pattern_scanner_spec.rb
|
275
278
|
- spec/readme_spec.rb
|
276
279
|
- spec/relative_keys_spec.rb
|
277
|
-
- spec/source_keys_spec.rb
|
278
280
|
- spec/spec_helper.rb
|
279
281
|
- spec/support/fixtures.rb
|
280
282
|
- spec/support/i18n_tasks_output_matcher.rb
|