i18n-tasks 0.9.16 → 0.9.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d0cac577152584d62e48767e77416aa559bed589
4
- data.tar.gz: 5b981968e66f977fd24c8d2d16fc840614d88146
3
+ metadata.gz: ebc184ed8233c7a409de36ee6fd654fa4830e2f2
4
+ data.tar.gz: c846f15fa5b8e278d4b0dab8b3ec021759b8f603
5
5
  SHA512:
6
- metadata.gz: '09b634136cd5a68aa0f37c5b272cf55bda9880181e68c173d1247acb5c629c825317b0aea9e64f5a09387e1ae4c87813d4988c930dfa07f0d088f616b6da165d'
7
- data.tar.gz: 78d5153233fd8050e9394761010fb11344bdfc84f0d2f6786a2d016026e1027938a3b625a686e004f988bb6551aad3ae677ea8584c7356a09f01266807903e48
6
+ metadata.gz: 558d0ee6c04e5630c48f1e1c206f37931a38c60da5ff3392042940c814bfdbbab94ca0a51840f0b963fcd6adab4c9b3e2d4b5d15ee764670a4b49cd444194242
7
+ data.tar.gz: 8b955b0dd45d4761a9fde64ef0baa81fa3725d51f72ce136ebbac95c0bedb88a0a8392b1029253d780bf60a33fbaf7c1beb801f6430a9311dbe4d4cfe2a6aa9d
data/README.md CHANGED
@@ -24,7 +24,7 @@ i18n-tasks can be used with any project using the ruby [i18n gem][i18n-gem] (def
24
24
  Add i18n-tasks to the Gemfile:
25
25
 
26
26
  ```ruby
27
- gem 'i18n-tasks', '~> 0.9.16'
27
+ gem 'i18n-tasks', '~> 0.9.17'
28
28
  ```
29
29
 
30
30
  Copy the default [configuration file](#configuration):
@@ -39,13 +39,20 @@ Copy rspec test to test for missing and unused translations as part of the suite
39
39
  $ cp $(i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/
40
40
  ```
41
41
 
42
+ Or for minitest:
43
+
44
+ ```console
45
+ $ cp $(i18n-tasks gem-path)/templates/minitest/i18n_test.rb test/
46
+ ```
47
+
42
48
  ## Usage
43
49
 
44
50
  Run `i18n-tasks` to get the list of all the tasks with short descriptions.
45
51
 
46
52
  ### Check health
47
53
 
48
- `i18n-tasks health` checks if any keys are missing or not used:
54
+ `i18n-tasks health` checks if any keys are missing or not used,
55
+ and that all the locale files are normalized (auto-formatted):
49
56
 
50
57
  ```console
51
58
  $ i18n-tasks health
@@ -29,6 +29,7 @@ en:
29
29
  %{value_or_default_or_human_key}
30
30
  desc:
31
31
  add_missing: add missing keys to locale data
32
+ check_normalized: verify that all translation data is normalized
32
33
  config: display i18n-tasks configuration
33
34
  data: show locale data
34
35
  data_merge: merge locale data with trees
@@ -27,6 +27,7 @@ ru:
27
27
  %{value_or_default_or_human_key}
28
28
  desc:
29
29
  add_missing: добавить недостающие ключи к переводам
30
+ check_normalized: проверить, что все файлы переводов нормализованы
30
31
  config: показать конфигурацию
31
32
  data: показать данные переводов
32
33
  data_merge: добавить дерево к переводам
data/i18n-tasks.gemspec CHANGED
@@ -38,7 +38,7 @@ TEXT
38
38
  s.add_dependency 'activesupport', '>= 4.0.2'
39
39
  s.add_dependency 'ast', '>= 2.1.0'
40
40
  s.add_dependency 'easy_translate', '>= 0.5.0'
41
- s.add_dependency 'erubis'
41
+ s.add_dependency 'erubi'
42
42
  s.add_dependency 'highline', '>= 1.7.3'
43
43
  s.add_dependency 'i18n'
44
44
  s.add_dependency 'parser', '>= 2.2.3.0'
data/lib/i18n/tasks.rb CHANGED
@@ -57,7 +57,7 @@ rescue LoadError => _e
57
57
  require 'active_support/core_ext/try'
58
58
  end
59
59
  require 'rainbow'
60
- require 'erubis'
60
+ require 'erubi'
61
61
 
62
62
  require 'i18n/tasks/version'
63
63
  require 'i18n/tasks/base_task'
@@ -17,7 +17,19 @@ module I18n::Tasks
17
17
  args: %i[locales pattern_router]
18
18
 
19
19
  def normalize(opt = {})
20
- i18n.normalize_store! opt[:locales], opt[:pattern_router]
20
+ i18n.normalize_store! locales: opt[:locales],
21
+ force_pattern_router: opt[:pattern_router]
22
+ end
23
+
24
+ cmd :check_normalized,
25
+ pos: '[locale ...]',
26
+ desc: t('i18n_tasks.cmd.desc.check_normalized'),
27
+ args: %i[locales]
28
+
29
+ def check_normalized(opt)
30
+ non_normalized = i18n.non_normalized_paths locales: opt[:locales]
31
+ terminal_report.check_normalized_results(non_normalized)
32
+ :exit_1 unless non_normalized.empty?
21
33
  end
22
34
 
23
35
  cmd :mv,
@@ -18,7 +18,7 @@ module I18n::Tasks
18
18
  fail CommandError, t('i18n_tasks.health.no_keys_detected')
19
19
  end
20
20
  terminal_report.forest_stats forest, stats
21
- [missing(opt), unused(opt)].detect { |result| result == :exit_1 }
21
+ [missing(opt), unused(opt), check_normalized(opt)].detect { |result| result == :exit_1 }
22
22
  end
23
23
  end
24
24
  end
@@ -21,7 +21,9 @@ module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
21
21
 
22
22
  def file_config
23
23
  file = CONFIG_FILES.detect { |f| File.exist?(f) }
24
- config = file && YAML.load(Erubis::Eruby.new(File.read(file, encoding: 'UTF-8')).result)
24
+ # rubocop:disable Security/Eval
25
+ config = file && YAML.load(eval(Erubi::Engine.new(File.read(file, encoding: 'UTF-8')).src))
26
+ # rubocop:enable Security/Eval
25
27
  if config.present?
26
28
  config.with_indifferent_access.tap do |c|
27
29
  if c[:relative_roots]
@@ -59,16 +59,25 @@ module I18n::Tasks
59
59
  !t(key, locale).nil?
60
60
  end
61
61
 
62
- # write to store, normalizing all data
63
- def normalize_store!(from = nil, pattern_router = false)
64
- from = locales unless from
65
- router = pattern_router ? ::I18n::Tasks::Data::Router::PatternRouter.new(data, data.config) : data.router
62
+ # Normalize all the locale data in the store (by writing to the store).
63
+ #
64
+ # @param [Array<String>] locales locales to normalize. Default: all.
65
+ # @param [Boolean] force_pattern_router Whether to use pattern router regardless of the config.
66
+ def normalize_store!(locales: nil, force_pattern_router: false)
67
+ locales = self.locales unless locales
68
+ router = force_pattern_router ? ::I18n::Tasks::Data::Router::PatternRouter.new(data, data.config) : data.router
66
69
  data.with_router(router) do
67
- Array(from).each do |target_locale|
68
- # store handles normalization
70
+ Array(locales).each do |target_locale|
71
+ # The store handles actual normalization:
69
72
  data[target_locale] = data[target_locale]
70
73
  end
71
74
  end
72
75
  end
76
+
77
+ # @param [Array<String>] locales locales to check. Default: all.
78
+ # @return [Array<String>] paths to data that requires normalization
79
+ def non_normalized_paths(locales: nil)
80
+ Array(locales || self.locales).flat_map { |locale| data.non_normalized_paths(locale) }
81
+ end
73
82
  end
74
83
  end
@@ -14,6 +14,7 @@ module I18n
14
14
  adapter_op :dump, format, tree, write_config(format)
15
15
  end
16
16
 
17
+ # @return [Hash]
17
18
  def adapter_parse(tree, format)
18
19
  adapter_op :parse, format, tree, read_config(format)
19
20
  end
@@ -34,8 +35,14 @@ module I18n
34
35
  (config[format] || {})[:read]
35
36
  end
36
37
 
38
+ # @return [Hash]
37
39
  def load_file(path)
38
- adapter_parse ::File.read(path, encoding: 'UTF-8'), self.class.adapter_name_for_path(path)
40
+ adapter_parse read_file(path), self.class.adapter_name_for_path(path)
41
+ end
42
+
43
+ # @return [String]
44
+ def read_file(path)
45
+ ::File.read(path, encoding: 'UTF-8')
39
46
  end
40
47
 
41
48
  def write_tree(path, tree)
@@ -43,14 +50,16 @@ module I18n
43
50
  adapter = self.class.adapter_name_for_path(path)
44
51
  content = adapter_dump(hash, adapter)
45
52
  # Ignore unchanged data
46
- return if File.file?(path) &&
47
- # Comparing hashes for equality directly would ignore key order.
48
- # Round-trip through the adapter and compare the strings instead:
49
- content == adapter_dump(load_file(path), adapter)
53
+ return if File.file?(path) && content == read_file(path)
50
54
  ::FileUtils.mkpath(File.dirname(path))
51
55
  ::File.open(path, 'w') { |f| f.write content }
52
56
  end
53
57
 
58
+ def normalized?(path, tree)
59
+ return false unless File.file?(path)
60
+ read_file(path) == adapter_dump(tree.to_hash(true), self.class.adapter_name_for_path(path))
61
+ end
62
+
54
63
  module ClassMethods
55
64
  # @param pattern [String] File.fnmatch pattern
56
65
  # @param adapter [responds to parse(string)->hash and dump(hash)->string]
@@ -53,6 +53,14 @@ module I18n::Tasks
53
53
  @available_locales = nil
54
54
  end
55
55
 
56
+ # @param [String] locale
57
+ # @return [Array<String>] paths to files that are not normalized
58
+ def non_normalized_paths(locale)
59
+ router.route(locale, get(locale))
60
+ .reject { |path, tree_slice| normalized?(path, tree_slice) }
61
+ .map(&:first)
62
+ end
63
+
56
64
  def write(forest)
57
65
  forest.each { |root| set(root.key, root) }
58
66
  end
@@ -90,6 +90,16 @@ module I18n
90
90
  end
91
91
  end
92
92
 
93
+ def check_normalized_results(non_normalized)
94
+ if non_normalized.empty?
95
+ print_success 'All data is normalized'
96
+ return
97
+ end
98
+ log_stderr Rainbow('The following data requires normalization:').yellow
99
+ puts non_normalized
100
+ log_stderr Rainbow('Run `i18n-tasks normalize` to fix').yellow
101
+ end
102
+
93
103
  private
94
104
 
95
105
  def missing_key_info(leaf)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module I18n
4
4
  module Tasks
5
- VERSION = '0.9.16'
5
+ VERSION = '0.9.17'
6
6
  end
7
7
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/tasks'
4
+
5
+ class I18nTest < ActiveSupport::TestCase
6
+ def setup
7
+ @i18n = I18n::Tasks::BaseTask.new
8
+ @missing_keys = @i18n.missing_keys
9
+ @unused_keys = @i18n.unused_keys
10
+ end
11
+
12
+ def test_no_missing_keys
13
+ assert_empty @missing_keys,
14
+ "Missing #{@missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them"
15
+ end
16
+
17
+ def test_no_unused_keys
18
+ assert_empty @unused_keys,
19
+ "#{@unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
20
+ end
21
+
22
+ def test_files_are_normalized
23
+ non_normalized = @i18n.non_normalized_paths
24
+ error_message = "The following files need to be normalized:\n" \
25
+ "#{non_normalized.map { |path| " #{path}" }.join("\n")}\n" \
26
+ 'Please run `i18n-tasks normalize` to fix'
27
+ assert_empty non_normalized, error_message
28
+ end
29
+ end
@@ -16,4 +16,12 @@ RSpec.describe 'I18n' do
16
16
  expect(unused_keys).to be_empty,
17
17
  "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
18
18
  end
19
+
20
+ it 'files are normalized' do
21
+ non_normalized = i18n.non_normalized_paths
22
+ error_message = "The following files need to be normalized:\n" \
23
+ "#{non_normalized.map { |path| " #{path}" }.join("\n")}\n" \
24
+ 'Please run `i18n-tasks normalize` to fix'
25
+ expect(non_normalized).to be_empty, error_message
26
+ end
19
27
  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.9.16
4
+ version: 0.9.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-21 00:00:00.000000000 Z
11
+ date: 2017-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.5.0
55
55
  - !ruby/object:Gem::Dependency
56
- name: erubis
56
+ name: erubi
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -328,6 +328,7 @@ files:
328
328
  - lib/i18n/tasks/used_keys.rb
329
329
  - lib/i18n/tasks/version.rb
330
330
  - templates/config/i18n-tasks.yml
331
+ - templates/minitest/i18n_test.rb
331
332
  - templates/rspec/i18n_spec.rb
332
333
  homepage: https://github.com/glebm/i18n-tasks
333
334
  licenses: