i18n-tasks 0.3.11 → 0.4.0.beta1

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.
@@ -0,0 +1,81 @@
1
+ module I18n::Tasks::Data::Tree
2
+ # Any Enumerable that yields nodes can mix in this module
3
+ module Traversal
4
+
5
+ def nodes(&block)
6
+ walk_depth_first(&block)
7
+ end
8
+
9
+ def leaves(&visitor)
10
+ return to_enum(:leaves) unless visitor
11
+ nodes do |node|
12
+ visitor.yield(node) if node.leaf?
13
+ end
14
+ end
15
+
16
+ # @param root include root in full key
17
+ def keys(root: true, &visitor)
18
+ return to_enum(:keys, root: root) unless visitor
19
+ leaves { |node| visitor.yield(node.full_key(root: root), node) }
20
+ end
21
+
22
+ def levels(&block)
23
+ return to_enum(:levels) unless block
24
+ nodes = to_nodes
25
+ non_null = nodes.reject(&:null?)
26
+ unless non_null.empty?
27
+ block.yield non_null
28
+ Nodes.new(nodes.children).levels(&block)
29
+ end
30
+ end
31
+
32
+ def walk_breadth_first(&visitor)
33
+ return to_enum(:walk_breadth_first) unless visitor
34
+ levels do |nodes|
35
+ nodes.each { |node| visitor.yield(node) unless node.null? }
36
+ end
37
+ end
38
+
39
+ def walk_depth_first(&visitor)
40
+ return to_enum(:walk_depth_first) unless visitor
41
+ each { |node|
42
+ visitor.yield node unless node.null?
43
+ node.children.each do |child|
44
+ child.walk_depth_first(&visitor)
45
+ end if node.children?
46
+ }
47
+ end
48
+
49
+ #-- modify / derive
50
+
51
+ # @return Siblings
52
+ def select_nodes(&block)
53
+ result = Node.new(children: [])
54
+ each do |node|
55
+ if block.yield(node)
56
+ result.append!(
57
+ node.derive(
58
+ parent: result ,
59
+ children: (node.children.select_nodes(&block) if node.children)
60
+ )
61
+ )
62
+ end
63
+ end
64
+ result.children
65
+ end
66
+
67
+ # @return Siblings
68
+ def select_keys(root: true, &block)
69
+ ok = {}
70
+ keys(root: root) do |full_key, node|
71
+ if block.yield(full_key, node)
72
+ node.walk_to_root { |p|
73
+ break if ok[p]
74
+ ok[p] = true
75
+ }
76
+ end
77
+ end
78
+ select_nodes { |node| ok[node] }
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,18 @@
1
+ module I18n::Tasks::FileStructure
2
+ def identify(routes = data.config.read)
3
+
4
+ end
5
+
6
+
7
+ class NonLeafVisitor
8
+ def visit(node)
9
+ puts "non-leaf: #{node}"
10
+ end
11
+ end
12
+
13
+ class LeafVisitor
14
+ def visit(node)
15
+ puts "leaf: #{node}"
16
+ end
17
+ end
18
+ end
@@ -41,11 +41,11 @@ module I18n::Tasks
41
41
  return keys_missing_from_base if locale == base_locale
42
42
  @keys_missing_from_locale ||= {}
43
43
  @keys_missing_from_locale[locale] ||= begin
44
- keys = data[base_locale].traverse_map_if { |key, base_value|
45
- next if ignore_key?(key, :missing)
44
+ keys = data[base_locale].keys(root: false).map { |key, node|
46
45
  key = depluralize_key(key, locale)
47
- key if !key_value?(key, locale)
48
- }.uniq
46
+ next if ignore_key?(key, :missing) || key_value?(key, locale)
47
+ key
48
+ }.compact.uniq
49
49
  KeyGroup.new keys, type: :missing_from_locale, locale: locale
50
50
  end
51
51
  end
@@ -54,9 +54,9 @@ module I18n::Tasks
54
54
  def keys_eq_base(locale)
55
55
  @keys_eq_base ||= {}
56
56
  @keys_eq_base[locale] ||= begin
57
- keys = data[base_locale].traverse_map_if { |key, base_value|
58
- key if base_value == t(key, locale) && !ignore_key?(key, :eq_base, locale)
59
- }
57
+ keys = data[base_locale].keys(root: false).map { |key, node|
58
+ key if node.value == t(key, locale) && !ignore_key?(key, :eq_base, locale)
59
+ }.compact
60
60
  KeyGroup.new keys, type: :eq_base, locale: locale
61
61
  end
62
62
  end
@@ -5,11 +5,11 @@ 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(key, locale = base_locale)
8
- return key if key !~ PLURAL_KEY_RE || t(key, locale).is_a?(Hash)
9
- parent_key = key.split('.')[0..-2] * '.'
10
- plural_versions = t(parent_key, locale) || (locale != base_locale && t(parent_key, base_locale))
11
- if plural_versions.is_a?(Hash) && plural_versions.all? { |k, v| !v.is_a?(Hash) && ".#{k}" =~ PLURAL_KEY_RE }
12
- parent_key
8
+ return key if key !~ PLURAL_KEY_RE
9
+ node = node(key, locale)
10
+ nodes = node.try(:siblings).presence || (locale != base_locale && node(key, base_locale).try(:siblings))
11
+ if nodes && nodes.all? { |x| x.leaf? && ".#{x.key}" =~ PLURAL_KEY_RE }
12
+ key.split('.')[0..-2] * '.'
13
13
  else
14
14
  key
15
15
  end
@@ -8,11 +8,11 @@ module I18n
8
8
  def unused_keys(locale = base_locale)
9
9
  @unused_keys ||= {}
10
10
  @unused_keys[locale] ||= begin
11
- keys = data[locale].traverse_map_if { |key, value|
11
+ keys = data[locale].keys(root: false).map { |key, value|
12
12
  next if used_in_expr?(key) || ignore_key?(key, :unused)
13
13
  key = depluralize_key(key, locale)
14
- [key, value] unless used_key?(key)
15
- }.uniq
14
+ key unless used_key?(key)
15
+ }.compact.uniq
16
16
  KeyGroup.new keys, locale: locale, type: :unused
17
17
  end
18
18
  end
@@ -21,10 +21,9 @@ module I18n
21
21
  locales ||= self.locales
22
22
  unused = unused_keys
23
23
  locales.each do |locale|
24
- used_key_values = data[locale].traverse_map_if { |key, value|
25
- [key, value] unless unused.include?(depluralize_key(key, locale))
24
+ data[locale] = data[locale].select_keys(root: false) { |key, value|
25
+ !unused.include?(depluralize_key(key, locale))
26
26
  }
27
- data[locale] = used_key_values
28
27
  end
29
28
  end
30
29
  end
@@ -1,5 +1,5 @@
1
1
  module I18n
2
2
  module Tasks
3
- VERSION = '0.3.11'
3
+ VERSION = '0.4.0.beta1'
4
4
  end
5
5
  end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Conservative router' do
4
+ describe '#available_locales' do
5
+ before do
6
+ TestCodebase.setup(
7
+ 'config/locales/en.yml' => {en: {a: 1}}.to_yaml,
8
+ 'config/locales/other.en.yml' => {en: {b: 1}}.to_yaml,
9
+ 'config/locales/es.yml' => {es: {}}.to_yaml,
10
+ 'config/locales/other.es.yml' => {es: {c: 1}}.to_yaml
11
+ )
12
+ end
13
+ after do
14
+ TestCodebase.teardown
15
+ end
16
+ let(:data) {
17
+ I18n::Tasks::Data::FileSystem.new(
18
+ router: 'conservative_router',
19
+ base_locale: 'en',
20
+ read: 'config/locales/*%{locale}.yml',
21
+ write: ['config/locales/not_found.%{locale}.yml']
22
+ )
23
+ }
24
+
25
+ it 'preserves existing keys' do
26
+ TestCodebase.in_test_app_dir do
27
+ data['es'] = data['es']
28
+ data.reload
29
+ data['es']['es.c'].data[:path].should == 'config/locales/other.es.yml'
30
+ end
31
+ end
32
+
33
+ it 'infers new keys from base locale' do
34
+ TestCodebase.in_test_app_dir do
35
+ data['es'] = data['es'].merge!(build_tree(es: {a: 1, b: 2}))
36
+ data.reload
37
+ data['es']['es.a'].data[:path].should == 'config/locales/es.yml'
38
+ data['es']['es.b'].data[:path].should == 'config/locales/other.es.yml'
39
+ end
40
+ end
41
+
42
+ it 'falls back to pattern_router when the key is new' do
43
+ TestCodebase.in_test_app_dir do
44
+ data['es'] = data['es'].merge!(build_tree(es: {z: 2}))
45
+ data.reload
46
+ data['es']['es.z'].data[:path].should == 'config/locales/not_found.es.yml'
47
+ end
48
+ end
49
+ end
50
+ end
@@ -45,7 +45,8 @@ describe 'File system i18n' do
45
45
  'c.yml' => {en: {c: 1}}.stringify_keys.to_yaml
46
46
  )
47
47
  TestCodebase.in_test_app_dir {
48
- expect(data[:en].data.symbolize_keys).to eq(a: 1, b: 1, c: 1)
48
+ actual = data[:en].to_hash['en'].symbolize_keys
49
+ expect(actual).to eq(a: 1, b: 1, c: 1)
49
50
  }
50
51
  end
51
52
 
@@ -55,7 +56,7 @@ describe 'File system i18n' do
55
56
  locale_data = {'pizza' => keys, 'sushi' => keys}
56
57
  TestCodebase.setup
57
58
  TestCodebase.in_test_app_dir {
58
- data[:en] = locale_data
59
+ data[:en] = data[:en].merge!('en' => locale_data)
59
60
  files = %w(pizza.en.yml sushi.en.yml)
60
61
  Dir['*.yml'].sort.should == files.sort
61
62
  files.each { |f| YAML.load_file(f)['en'].should == {File.basename(f, '.en.yml') => keys} }
@@ -80,7 +81,7 @@ describe 'File system i18n' do
80
81
  'c.json' => {en: {c: 1}}.stringify_keys.to_json
81
82
  )
82
83
  TestCodebase.in_test_app_dir {
83
- expect(data[:en].data.symbolize_keys).to eq(a: 1, b: 1, c: 1)
84
+ expect(data[:en].to_hash['en'].symbolize_keys).to eq(a: 1, b: 1, c: 1)
84
85
  }
85
86
  end
86
87
 
@@ -90,7 +91,7 @@ describe 'File system i18n' do
90
91
  locale_data = {'pizza' => keys, 'sushi' => keys}
91
92
  TestCodebase.setup
92
93
  TestCodebase.in_test_app_dir {
93
- data[:en] = locale_data
94
+ data[:en] = data[:en].merge!('en' => locale_data)
94
95
  files = %w(pizza.en.json sushi.en.json)
95
96
  Dir['*.json'].sort.should == files.sort
96
97
  files.each { |f| JSON.parse(File.read f)['en'].should == {File.basename(f, '.en.json') => keys} }
@@ -33,9 +33,9 @@ describe 'Google Translation' do
33
33
 
34
34
  it 'works' do
35
35
  in_test_app_dir do
36
- task.data[:en] = {'common' => {'hello' => TEST_STRING}}
36
+ task.data[:en] = build_tree('en' => {'common' => {'hello' => TEST_STRING}})
37
37
  cmd.translate_missing
38
- expect(task.data[:es].t('common.hello')).to eq(TEST_RESULT)
38
+ expect(task.t('common.hello', 'es')).to eq(TEST_RESULT)
39
39
  end
40
40
  end
41
41
  end
@@ -9,7 +9,7 @@ describe 'i18n-tasks' do
9
9
  describe 'missing' do
10
10
  let (:expected_missing_keys) {
11
11
  %w( en.used_but_missing.key en.relative.index.missing
12
- es.missing_in_es.a es.blank_in_es.a es.same_in_es.a
12
+ es.missing_in_es.a es.same_in_es.a
13
13
  en.hash.pattern_missing.a en.hash.pattern_missing.b
14
14
  en.missing_symbol_key en.missing_symbol.key_two en.missing_symbol.key_three
15
15
  es.missing_in_es_plural_1.a es.missing_in_es_plural_2.a)
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Tree siblings / forest' do
4
+
5
+ context 'a tree' do
6
+ let(:a_hash) { {a: 1, b: {ba: 1, bb: 2}}.deep_stringify_keys }
7
+
8
+ it '::from_nested_hash' do
9
+ a = build_tree(a_hash)
10
+ expect(a.to_hash).to eq(a_hash)
11
+ end
12
+
13
+ it '#derive' do
14
+ a = build_tree(a_hash)
15
+ b = a.derive.append! build_tree(c: 1)
16
+
17
+ # a was not modified
18
+ expect(a.to_hash).to eq(a_hash)
19
+ # but b was
20
+ expect(b.to_hash).to eq(a_hash.merge('c' => 1))
21
+ end
22
+
23
+ it '#merge' do
24
+ a = build_tree(a_hash)
25
+ b_hash = {b: {bc: 1}, c: 1}.deep_stringify_keys
26
+ expect(a.merge(build_tree(b_hash)).to_hash).to eq(a_hash.deep_merge(b_hash))
27
+ end
28
+ end
29
+ end
@@ -5,7 +5,7 @@ describe 'Plural keys' do
5
5
  before do
6
6
  TestCodebase.setup('config/locales/en.yml' => '')
7
7
  TestCodebase.in_test_app_dir do
8
- task.data['en'] = {
8
+ tree = ::I18n::Tasks::Data::Tree::Siblings.from_nested_hash('en' => {
9
9
  'regular_key' => 'a',
10
10
  'plural_key' => {
11
11
  'one' => 'one', 'other' => '%{count}'
@@ -14,7 +14,8 @@ describe 'Plural keys' do
14
14
  'one' => 'a',
15
15
  'green' => 'b'
16
16
  }
17
- }
17
+ })
18
+ task.data['en'] = tree
18
19
  task.data['en']
19
20
  end
20
21
  end
data/spec/spec_helper.rb CHANGED
@@ -19,4 +19,5 @@ Dir['spec/support/**/*.rb'].each { |f| require "./#{f}" }
19
19
  RSpec.configure do |config|
20
20
  config.include FixturesSupport
21
21
  config.include CaptureStd
22
+ config.include Trees
22
23
  end
@@ -0,0 +1,5 @@
1
+ module Trees
2
+ def build_tree(hash)
3
+ I18n::Tasks::Data::Tree::Siblings.from_nested_hash(hash)
4
+ end
5
+ end
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.3.11
4
+ version: 0.4.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-20 00:00:00.000000000 Z
11
+ date: 2014-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubis
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 0.4.0
47
+ version: 0.5.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 0.4.0
54
+ version: 0.5.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: term-ansicolor
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: 3.4.7
103
+ version: 3.5.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: 3.4.7
110
+ version: 3.5.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: axlsx
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -193,6 +193,7 @@ extra_rdoc_files: []
193
193
  files:
194
194
  - ".coveralls.yml"
195
195
  - ".gitignore"
196
+ - ".jrubyrc"
196
197
  - ".travis.yml"
197
198
  - CHANGES.md
198
199
  - Gemfile
@@ -200,6 +201,8 @@ files:
200
201
  - README.md
201
202
  - Rakefile
202
203
  - bin/i18n-tasks
204
+ - config/locales/en.yml
205
+ - config/locales/es.yml
203
206
  - i18n-tasks.gemspec
204
207
  - lib/i18n/tasks.rb
205
208
  - lib/i18n/tasks/base_task.rb
@@ -212,8 +215,13 @@ files:
212
215
  - lib/i18n/tasks/data/file_formats.rb
213
216
  - lib/i18n/tasks/data/file_system.rb
214
217
  - lib/i18n/tasks/data/file_system_base.rb
215
- - lib/i18n/tasks/data/locale_tree.rb
216
- - lib/i18n/tasks/data/router.rb
218
+ - lib/i18n/tasks/data/router/conservative_router.rb
219
+ - lib/i18n/tasks/data/router/pattern_router.rb
220
+ - lib/i18n/tasks/data/tree/node.rb
221
+ - lib/i18n/tasks/data/tree/nodes.rb
222
+ - lib/i18n/tasks/data/tree/siblings.rb
223
+ - lib/i18n/tasks/data/tree/traversal.rb
224
+ - lib/i18n/tasks/file_structure.rb
217
225
  - lib/i18n/tasks/fill_tasks.rb
218
226
  - lib/i18n/tasks/google_translation.rb
219
227
  - lib/i18n/tasks/ignore_keys.rb
@@ -236,6 +244,7 @@ files:
236
244
  - lib/i18n/tasks/unused_keys.rb
237
245
  - lib/i18n/tasks/used_keys.rb
238
246
  - lib/i18n/tasks/version.rb
247
+ - spec/conservative_router_spec.rb
239
248
  - spec/file_system_data_spec.rb
240
249
  - spec/fixtures/app/assets/javascripts/application.js
241
250
  - spec/fixtures/app/controllers/events_controller.rb
@@ -247,6 +256,7 @@ files:
247
256
  - spec/i18n_tasks_spec.rb
248
257
  - spec/key_group_spec.rb
249
258
  - spec/key_pattern_matching_spec.rb
259
+ - spec/locale_tree/siblings_spec.rb
250
260
  - spec/pattern_scanner_spec.rb
251
261
  - spec/plural_keys_spec.rb
252
262
  - spec/readme_spec.rb
@@ -257,6 +267,7 @@ files:
257
267
  - spec/support/i18n_tasks_output_matcher.rb
258
268
  - spec/support/key_pattern_matcher.rb
259
269
  - spec/support/test_codebase.rb
270
+ - spec/support/trees.rb
260
271
  - spec/used_keys_spec.rb
261
272
  homepage: https://github.com/glebm/i18n-tasks
262
273
  licenses:
@@ -274,17 +285,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
274
285
  version: '0'
275
286
  required_rubygems_version: !ruby/object:Gem::Requirement
276
287
  requirements:
277
- - - ">="
288
+ - - ">"
278
289
  - !ruby/object:Gem::Version
279
- version: '0'
290
+ version: 1.3.1
280
291
  requirements: []
281
292
  rubyforge_project:
282
- rubygems_version: 2.2.0
293
+ rubygems_version: 2.2.2
283
294
  signing_key:
284
295
  specification_version: 4
285
296
  summary: Manage translations in ruby applications with the awesome power of static
286
297
  analysis — Edit
287
298
  test_files:
299
+ - spec/conservative_router_spec.rb
288
300
  - spec/file_system_data_spec.rb
289
301
  - spec/fixtures/app/assets/javascripts/application.js
290
302
  - spec/fixtures/app/controllers/events_controller.rb
@@ -296,6 +308,7 @@ test_files:
296
308
  - spec/i18n_tasks_spec.rb
297
309
  - spec/key_group_spec.rb
298
310
  - spec/key_pattern_matching_spec.rb
311
+ - spec/locale_tree/siblings_spec.rb
299
312
  - spec/pattern_scanner_spec.rb
300
313
  - spec/plural_keys_spec.rb
301
314
  - spec/readme_spec.rb
@@ -306,5 +319,6 @@ test_files:
306
319
  - spec/support/i18n_tasks_output_matcher.rb
307
320
  - spec/support/key_pattern_matcher.rb
308
321
  - spec/support/test_codebase.rb
322
+ - spec/support/trees.rb
309
323
  - spec/used_keys_spec.rb
310
324
  has_rdoc: