i18n-tasks 0.9.6 → 0.9.7

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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/Rakefile +2 -1
  4. data/bin/i18n-tasks +1 -0
  5. data/config/locales/en.yml +15 -9
  6. data/config/locales/ru.yml +80 -74
  7. data/i18n-tasks.gemspec +9 -8
  8. data/lib/i18n/tasks.rb +2 -5
  9. data/lib/i18n/tasks/cli.rb +14 -18
  10. data/lib/i18n/tasks/command/commander.rb +2 -3
  11. data/lib/i18n/tasks/command/commands/health.rb +1 -1
  12. data/lib/i18n/tasks/command/commands/meta.rb +2 -2
  13. data/lib/i18n/tasks/command/commands/missing.rb +17 -19
  14. data/lib/i18n/tasks/command/commands/tree.rb +3 -3
  15. data/lib/i18n/tasks/command/commands/usages.rb +6 -5
  16. data/lib/i18n/tasks/command/commands/xlsx.rb +1 -1
  17. data/lib/i18n/tasks/command/dsl.rb +1 -2
  18. data/lib/i18n/tasks/command/option_parsers/enum.rb +6 -6
  19. data/lib/i18n/tasks/command/option_parsers/locale.rb +3 -1
  20. data/lib/i18n/tasks/command/options/data.rb +22 -21
  21. data/lib/i18n/tasks/command_error.rb +1 -3
  22. data/lib/i18n/tasks/configuration.rb +37 -27
  23. data/lib/i18n/tasks/console_context.rb +3 -2
  24. data/lib/i18n/tasks/data.rb +5 -4
  25. data/lib/i18n/tasks/data/adapter/json_adapter.rb +13 -12
  26. data/lib/i18n/tasks/data/adapter/yaml_adapter.rb +13 -14
  27. data/lib/i18n/tasks/data/file_formats.rb +15 -10
  28. data/lib/i18n/tasks/data/file_system_base.rb +18 -22
  29. data/lib/i18n/tasks/data/router/conservative_router.rb +3 -6
  30. data/lib/i18n/tasks/data/router/pattern_router.rb +4 -5
  31. data/lib/i18n/tasks/data/tree/node.rb +20 -19
  32. data/lib/i18n/tasks/data/tree/nodes.rb +4 -3
  33. data/lib/i18n/tasks/data/tree/siblings.rb +36 -29
  34. data/lib/i18n/tasks/data/tree/traversal.rb +32 -35
  35. data/lib/i18n/tasks/google_translation.rb +22 -25
  36. data/lib/i18n/tasks/html_keys.rb +2 -0
  37. data/lib/i18n/tasks/ignore_keys.rb +3 -2
  38. data/lib/i18n/tasks/key_pattern_matching.rb +9 -8
  39. data/lib/i18n/tasks/locale_list.rb +4 -6
  40. data/lib/i18n/tasks/locale_pathname.rb +8 -8
  41. data/lib/i18n/tasks/logging.rb +3 -3
  42. data/lib/i18n/tasks/missing_keys.rb +29 -31
  43. data/lib/i18n/tasks/plural_keys.rb +6 -7
  44. data/lib/i18n/tasks/references.rb +72 -41
  45. data/lib/i18n/tasks/reports/base.rb +8 -7
  46. data/lib/i18n/tasks/reports/spreadsheet.rb +15 -16
  47. data/lib/i18n/tasks/reports/terminal.rb +32 -32
  48. data/lib/i18n/tasks/scanners/file_scanner.rb +6 -5
  49. data/lib/i18n/tasks/scanners/files/caching_file_finder_provider.rb +1 -2
  50. data/lib/i18n/tasks/scanners/files/caching_file_reader.rb +0 -1
  51. data/lib/i18n/tasks/scanners/files/file_finder.rb +12 -15
  52. data/lib/i18n/tasks/scanners/files/file_reader.rb +0 -1
  53. data/lib/i18n/tasks/scanners/occurrence_from_position.rb +8 -7
  54. data/lib/i18n/tasks/scanners/pattern_mapper.rb +2 -2
  55. data/lib/i18n/tasks/scanners/pattern_scanner.rb +9 -7
  56. data/lib/i18n/tasks/scanners/pattern_with_scope_scanner.rb +1 -2
  57. data/lib/i18n/tasks/scanners/relative_keys.rb +11 -11
  58. data/lib/i18n/tasks/scanners/results/key_occurrences.rb +3 -4
  59. data/lib/i18n/tasks/scanners/results/occurrence.rb +8 -7
  60. data/lib/i18n/tasks/scanners/ruby_ast_call_finder.rb +2 -2
  61. data/lib/i18n/tasks/scanners/ruby_ast_scanner.rb +39 -31
  62. data/lib/i18n/tasks/scanners/scanner_multiplexer.rb +9 -3
  63. data/lib/i18n/tasks/split_key.rb +5 -6
  64. data/lib/i18n/tasks/stats.rb +10 -8
  65. data/lib/i18n/tasks/string_interpolation.rb +1 -1
  66. data/lib/i18n/tasks/unused_keys.rb +2 -2
  67. data/lib/i18n/tasks/used_keys.rb +47 -43
  68. data/lib/i18n/tasks/version.rb +1 -1
  69. data/templates/rspec/i18n_spec.rb +2 -2
  70. metadata +30 -3
@@ -14,7 +14,7 @@ module I18n::Tasks
14
14
  forest = i18n.data_forest(opt[:locales])
15
15
  stats = i18n.forest_stats(forest)
16
16
  if stats[:key_count].zero?
17
- raise CommandError.new t('i18n_tasks.health.no_keys_detected')
17
+ fail CommandError, t('i18n_tasks.health.no_keys_detected')
18
18
  end
19
19
  terminal_report.forest_stats forest, stats
20
20
  [missing(opt), unused(opt)].detect { |result| result == :exit_1 }
@@ -13,8 +13,8 @@ module I18n::Tasks
13
13
  cfg = i18n.config_for_inspect
14
14
  cfg = cfg.slice(*opts[:arguments]) if opts[:arguments].present?
15
15
  cfg = cfg.to_yaml
16
- cfg.sub! /\A---\n/, ''
17
- cfg.gsub! /^([^\s-].+?:)/, Term::ANSIColor.cyan(Term::ANSIColor.bold('\1'))
16
+ cfg.sub!(/\A---\n/, '')
17
+ cfg.gsub!(/^([^\s-].+?:)/, Term::ANSIColor.cyan(Term::ANSIColor.bold('\1')))
18
18
  puts cfg
19
19
  end
20
20
 
@@ -14,9 +14,12 @@ module I18n::Tasks
14
14
  Array,
15
15
  t('i18n_tasks.cmd.args.desc.missing_types', valid: missing_types * ', '),
16
16
  parser: OptionParsers::Enum::ListParser.new(
17
- missing_types,
18
- proc { |invalid, valid| I18n.t('i18n_tasks.cmd.errors.invalid_missing_type',
19
- invalid: invalid * ', ', valid: valid * ', ', count: invalid.length) })
17
+ missing_types,
18
+ proc do |invalid, valid|
19
+ I18n.t('i18n_tasks.cmd.errors.invalid_missing_type',
20
+ invalid: invalid * ', ', valid: valid * ', ', count: invalid.length)
21
+ end
22
+ )
20
23
 
21
24
  cmd :missing,
22
25
  pos: '[locale ...]',
@@ -45,27 +48,22 @@ module I18n::Tasks
45
48
  cmd :add_missing,
46
49
  pos: '[locale ...]',
47
50
  desc: t('i18n_tasks.cmd.desc.add_missing'),
48
- args: [:locales, :out_format, arg(:value) + [{default: '%{value_or_default_or_human_key}'}],
51
+ args: [:locales, :out_format, arg(:value) + [{ default: '%{value_or_default_or_human_key}' }],
49
52
  ['--nil-value', 'Set value to nil. Takes precedence over the value argument.']]
50
53
 
51
- def add_missing(opt = {})
52
- added = i18n.empty_forest
53
- locales = (opt[:locales] || i18n.locales)
54
- value = opt[:'nil-value'] ? nil : opt[:value]
55
- if locales[0] == i18n.base_locale
56
- # Merge base locale first, as this may affect the value for the other locales
57
- forest = i18n.missing_keys({locales: [locales[0]]}.update(opt.slice(:types, :base_locale))).
58
- set_each_value!(value)
54
+ def add_missing(opt = {}) # rubocop:disable Metrics/AbcSize
55
+ [ # Merge base locale first, as this may affect the value for the other locales
56
+ [i18n.base_locale] & opt[:locales],
57
+ opt[:locales] - [i18n.base_locale]
58
+ ].reject(&:empty?).each_with_object(i18n.empty_forest) do |locales, added|
59
+ forest = i18n.missing_keys(locales: locales, **opt.slice(:types, :base_locale))
60
+ .set_each_value!(opt[:'nil-value'] ? nil : opt[:value])
59
61
  i18n.data.merge! forest
60
62
  added.merge! forest
61
- locales = locales[1..-1]
63
+ end.tap do |added|
64
+ log_stderr t('i18n_tasks.add_missing.added', count: added.leaves.count)
65
+ print_forest added, opt
62
66
  end
63
- forest = i18n.missing_keys({locales: locales}.update(opt.slice(:types, :base_locale))).
64
- set_each_value!(value)
65
- i18n.data.merge! forest
66
- added.merge! forest
67
- log_stderr t('i18n_tasks.add_missing.added', count: added.leaves.count)
68
- print_forest added, opt
69
67
  end
70
68
  end
71
69
  end
@@ -50,8 +50,8 @@ module I18n::Tasks
50
50
  key = arg_or_pos! :key, opt
51
51
  name = arg_or_pos! :name, opt
52
52
  forest = forest_pos_or_stdin! opt
53
- raise CommandError.new('pass full key to rename (-k, --key)') if key.blank?
54
- raise CommandError.new('pass new name (-n, --name)') if name.blank?
53
+ fail CommandError, 'pass full key to rename (-k, --key)' if key.blank?
54
+ fail CommandError, 'pass new name (-n, --name)' if name.blank?
55
55
  forest.rename_each_key!(key, name)
56
56
  print_forest forest, opt
57
57
  end
@@ -76,7 +76,7 @@ module I18n::Tasks
76
76
  value = arg_or_pos! :value, opt
77
77
  forest = forest_pos_or_stdin!(opt)
78
78
  key_pattern = opt[:pattern]
79
- raise CommandError.new('pass value (-v, --value)') if value.blank?
79
+ fail CommandError, 'pass value (-v, --value)' if value.blank?
80
80
  forest.set_each_value!(value, key_pattern)
81
81
  print_forest forest, opt
82
82
  end
@@ -16,7 +16,8 @@ module I18n::Tasks
16
16
 
17
17
  def find(opt = {})
18
18
  opt[:filter] ||= opt.delete(:pattern) || opt[:arguments].try(:first)
19
- print_forest i18n.used_tree(strict: opt[:strict], key_filter: opt[:filter].presence, include_raw_references: true), opt, :used_keys
19
+ result = i18n.used_tree(strict: opt[:strict], key_filter: opt[:filter].presence, include_raw_references: true)
20
+ print_forest result, opt, :used_keys
20
21
  end
21
22
 
22
23
  cmd :unused,
@@ -54,10 +55,10 @@ module I18n::Tasks
54
55
  return if ENV['CONFIRM'] || opt[:confirm]
55
56
  locales = bold(unused_keys.flat_map { |root| root.key.split('+') }.sort.uniq * ', ')
56
57
  msg = [
57
- red(t('i18n_tasks.remove_unused.confirm', count: unused_keys.leaves.count, locales: locales)),
58
- yellow(t('i18n_tasks.common.continue_q')),
59
- yellow('(yes/no)')
60
- ] * ' '
58
+ red(t('i18n_tasks.remove_unused.confirm', count: unused_keys.leaves.count, locales: locales)),
59
+ yellow(t('i18n_tasks.common.continue_q')),
60
+ yellow('(yes/no)')
61
+ ].join(' ')
61
62
  exit 1 unless agree msg
62
63
  end
63
64
  end
@@ -15,7 +15,7 @@ module I18n::Tasks
15
15
  begin
16
16
  require 'axlsx'
17
17
  rescue LoadError
18
- message = %Q(For spreadsheet report please add axlsx gem to Gemfile:\ngem 'axlsx', '~> 2.0')
18
+ message = %(For spreadsheet report please add axlsx gem to Gemfile:\ngem 'axlsx', '~> 2.0')
19
19
  log_stderr Term::ANSIColor.red Term::ANSIColor.bold message
20
20
  exit 1
21
21
  end
@@ -17,8 +17,7 @@ module I18n::Tasks
17
17
  def cmd(name, conf = nil)
18
18
  if conf
19
19
  conf = conf.dup
20
- conf[:args] = (args = conf[:args]) ? args.map { |arg| Symbol === arg ? arg(arg) : arg } : []
21
-
20
+ conf[:args] = (conf[:args] || []).map { |arg| arg.is_a?(Symbol) ? arg(arg) : arg }
22
21
  dsl(:cmds)[name] = conf
23
22
  else
24
23
  dsl(:cmds)[name]
@@ -4,9 +4,9 @@ module I18n::Tasks
4
4
  module OptionParsers
5
5
  module Enum
6
6
  class Parser
7
- DEFAULT_ERROR = proc { |invalid, valid|
7
+ DEFAULT_ERROR = proc do |invalid, valid|
8
8
  I18n.t('i18n_tasks.cmd.enum_opt.invalid', invalid: invalid, valid: valid * ', ')
9
- }
9
+ end
10
10
 
11
11
  def initialize(valid, error_message = DEFAULT_ERROR)
12
12
  @valid = valid.map(&:to_s)
@@ -18,15 +18,15 @@ module I18n::Tasks
18
18
  if @valid.include?(value)
19
19
  value
20
20
  else
21
- raise CommandError.new @error_message.call(value, @valid)
21
+ fail CommandError, @error_message.call(value, @valid)
22
22
  end
23
23
  end
24
24
  end
25
25
 
26
26
  class ListParser
27
- DEFAULT_ERROR = proc { |invalid, valid|
27
+ DEFAULT_ERROR = proc do |invalid, valid|
28
28
  I18n.t('i18n_tasks.cmd.enum_list_opt.invalid', invalid: invalid * ', ', valid: valid * ', ')
29
- }
29
+ end
30
30
 
31
31
  def initialize(valid, error_message = DEFAULT_ERROR)
32
32
  @valid = valid.map(&:to_s)
@@ -44,7 +44,7 @@ module I18n::Tasks
44
44
  values
45
45
  end
46
46
  else
47
- raise CommandError.new @error_message.call(invalid, @valid)
47
+ fail CommandError, @error_message.call(invalid, @valid)
48
48
  end
49
49
  end
50
50
  end
@@ -8,7 +8,7 @@ module I18n::Tasks
8
8
 
9
9
  def validate!(locale)
10
10
  if VALID_LOCALE_RE !~ locale
11
- raise CommandError.new(I18n.t('i18n_tasks.cmd.errors.invalid_locale', invalid: locale))
11
+ fail CommandError, I18n.t('i18n_tasks.cmd.errors.invalid_locale', invalid: locale)
12
12
  end
13
13
  locale
14
14
  end
@@ -16,6 +16,7 @@ module I18n::Tasks
16
16
 
17
17
  module Parser
18
18
  module_function
19
+
19
20
  extend Validator
20
21
 
21
22
  # @param [#base_locale, #locales] context
@@ -30,6 +31,7 @@ module I18n::Tasks
30
31
 
31
32
  module ListParser
32
33
  module_function
34
+
33
35
  extend Validator
34
36
 
35
37
  # @param [#base_locale,#locales] context
@@ -7,22 +7,23 @@ module I18n::Tasks
7
7
  module Data
8
8
  include Command::DSL
9
9
 
10
- DATA_FORMATS = %w(yaml json keys)
11
- OUT_FORMATS = ['terminal-table', *DATA_FORMATS, 'inspect']
10
+ DATA_FORMATS = %w(yaml json keys).freeze
11
+ OUT_FORMATS = ['terminal-table', *DATA_FORMATS, 'inspect'].freeze
12
12
 
13
- format_arg = proc { |type, values|
13
+ format_arg = proc do |type, values|
14
14
  default = values.first
15
15
  arg type,
16
16
  '-f',
17
17
  '--format FORMAT',
18
18
  values,
19
- {'yml' => 'yaml'},
19
+ { 'yml' => 'yaml' },
20
20
  t("i18n_tasks.cmd.args.desc.#{type}", valid_text: values * ', ', default_text: default),
21
21
  parser: OptionParsers::Enum::Parser.new(values,
22
- proc { |value, valid|
23
- I18n.t('i18n_tasks.cmd.errors.invalid_format',
24
- invalid: value, valid: valid * ', ') })
25
- }
22
+ proc do |value, valid|
23
+ I18n.t('i18n_tasks.cmd.errors.invalid_format',
24
+ invalid: value, valid: valid * ', ')
25
+ end)
26
+ end
26
27
 
27
28
  # i18n-tasks-use t('i18n_tasks.cmd.args.desc.data_format')
28
29
  format_arg.call(:data_format, DATA_FORMATS)
@@ -41,7 +42,7 @@ module I18n::Tasks
41
42
  sources = []
42
43
  else
43
44
  sources = [$stdin.read]
44
- num -= 1 if num
45
+ num -= 1 if num
45
46
  end
46
47
  if num
47
48
  num.times { sources << args.shift }
@@ -53,14 +54,14 @@ module I18n::Tasks
53
54
  end
54
55
 
55
56
  def merge_forests_stdin_and_pos!(opt)
56
- forests_stdin_and_pos!(opt).inject(i18n.empty_forest) { |result, forest|
57
+ forests_stdin_and_pos!(opt).inject(i18n.empty_forest) do |result, forest|
57
58
  result.merge! forest
58
- }
59
+ end
59
60
  end
60
61
 
61
62
  def parse_forest(src, format)
62
- if !src
63
- raise CommandError.new(I18n.t('i18n_tasks.cmd.errors.pass_forest'))
63
+ unless src
64
+ fail CommandError, I18n.t('i18n_tasks.cmd.errors.pass_forest')
64
65
  end
65
66
  if format == 'keys'
66
67
  ::I18n::Tasks::Data::Tree::Siblings.from_key_names parse_keys(src)
@@ -76,14 +77,14 @@ module I18n::Tasks
76
77
  def print_forest(forest, opts, version = :show_tree)
77
78
  format = opts[:format].to_s
78
79
  case format
79
- when 'terminal-table'
80
- terminal_report.send(version, forest)
81
- when 'inspect'
82
- puts forest.inspect
83
- when 'keys'
84
- puts forest.key_names(root: true)
85
- when *DATA_FORMATS
86
- puts i18n.data.adapter_dump forest.to_hash(true), format
80
+ when 'terminal-table'
81
+ terminal_report.send(version, forest)
82
+ when 'inspect'
83
+ puts forest.inspect
84
+ when 'keys'
85
+ puts forest.key_names(root: true)
86
+ when *DATA_FORMATS
87
+ puts i18n.data.adapter_dump forest.to_hash(true), format
87
88
  end
88
89
  end
89
90
  end
@@ -5,12 +5,10 @@ module I18n
5
5
  # 1. show error message of the backtrace
6
6
  # 2. exit with non-zero exit code
7
7
  class CommandError < StandardError
8
-
9
- def initialize(error = nil, message)
8
+ def initialize(error = nil, message) # rubocop:disable Style/OptionalArguments
10
9
  super(message)
11
10
  set_backtrace error.backtrace if error
12
11
  end
13
12
  end
14
13
  end
15
14
  end
16
-
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
- module I18n::Tasks::Configuration
2
+ module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
3
3
  DEFAULTS = {
4
- base_locale: 'en'.freeze,
5
- internal_locale: 'en'.freeze,
6
- search: ::I18n::Tasks::UsedKeys::SEARCH_DEFAULTS,
7
- data: ::I18n::Tasks::Data::DATA_DEFAULTS
8
- }
4
+ base_locale: 'en',
5
+ internal_locale: 'en',
6
+ search: ::I18n::Tasks::UsedKeys::SEARCH_DEFAULTS,
7
+ data: ::I18n::Tasks::Data::DATA_DEFAULTS
8
+ }.freeze
9
9
 
10
10
  # i18n-tasks config (defaults + config/i18n-tasks.yml)
11
11
  # @return [Hash{String => String,Hash,Array}]
@@ -14,9 +14,9 @@ module I18n::Tasks::Configuration
14
14
  end
15
15
 
16
16
  CONFIG_FILES = %w(
17
- config/i18n-tasks.yml config/i18n-tasks.yml.erb
18
- i18n-tasks.yml i18n-tasks.yml.erb
19
- )
17
+ config/i18n-tasks.yml config/i18n-tasks.yml.erb
18
+ i18n-tasks.yml i18n-tasks.yml.erb
19
+ ).freeze
20
20
 
21
21
  def file_config
22
22
  file = CONFIG_FILES.detect { |f| File.exist?(f) }
@@ -24,7 +24,7 @@ module I18n::Tasks::Configuration
24
24
  if config.present?
25
25
  config.with_indifferent_access.tap do |c|
26
26
  if c[:relative_roots]
27
- warn_deprecated 'config/i18n-tasks.yml has relative_roots on top level. Please move relative_roots under search.'
27
+ warn_deprecated 'Please move relative_roots under search in config/i18n-tasks.yml.'
28
28
  c[:search][:relative_roots] = c.delete(:relative_roots)
29
29
  end
30
30
  end
@@ -44,8 +44,8 @@ module I18n::Tasks::Configuration
44
44
  def data_config
45
45
  @config_sections[:data] ||= begin
46
46
  {
47
- adapter: data.class.name,
48
- config: data.config
47
+ adapter: data.class.name,
48
+ config: data.config
49
49
  }
50
50
  end
51
51
  end
@@ -54,7 +54,7 @@ module I18n::Tasks::Configuration
54
54
  # @return [Hash{String => String,Hash,Array}]
55
55
  def translation_config
56
56
  @config_sections[:translation] ||= begin
57
- conf = (config[:translation] || {}).with_indifferent_access
57
+ conf = (config[:translation] || {}).with_indifferent_access
58
58
  conf[:api_key] ||= ENV['GOOGLE_TRANSLATE_API_KEY'] if ENV.key?('GOOGLE_TRANSLATE_API_KEY')
59
59
  conf
60
60
  end
@@ -71,11 +71,21 @@ module I18n::Tasks::Configuration
71
71
  end
72
72
 
73
73
  def internal_locale
74
- @config_sections[:internal_locale] ||= (config[:internal_locale] || DEFAULTS[:internal_locale]).to_s
74
+ @config_sections[:internal_locale] ||= begin
75
+ internal_locale = (config[:internal_locale] || DEFAULTS[:internal_locale]).to_s
76
+ valid_locales = Dir[File.join(I18n::Tasks.gem_path, 'config', 'locales', '*.yml')]
77
+ .map { |f| File.basename(f, '.yml') }
78
+ unless valid_locales.include?(internal_locale)
79
+ log_warn "invalid internal_locale #{internal_locale.inspect}. "\
80
+ "Available internal locales: #{valid_locales * ', '}."
81
+ internal_locale = DEFAULTS[:internal_locale].to_s
82
+ end
83
+ internal_locale
84
+ end
75
85
  end
76
86
 
77
87
  def ignore_config(type = nil)
78
- key = type ? "ignore_#{type}" : 'ignore'
88
+ key = type ? "ignore_#{type}" : 'ignore'
79
89
  @config_sections[key] ||= config[key]
80
90
  end
81
91
 
@@ -96,25 +106,25 @@ module I18n::Tasks::Configuration
96
106
  end
97
107
 
98
108
  def config_for_inspect
99
- to_hash_from_indifferent(config_sections.reject { |k, v| v.blank? }).tap do |sections|
109
+ to_hash_from_indifferent(config_sections.reject { |_k, v| v.blank? }).tap do |sections|
100
110
  sections.each do |_k, section|
101
- section.merge! section.delete('config') if Hash === section && section.key?('config')
111
+ section.merge! section.delete('config') if section.is_a?(Hash) && section.key?('config')
102
112
  end
103
113
  end
104
114
  end
105
115
 
106
116
  private
107
117
 
108
- def to_hash_from_indifferent(v)
109
- case v
110
- when Hash
111
- v.stringify_keys.to_hash.tap do |h|
112
- h.each { |k, v| h[k] = to_hash_from_indifferent(v) if Hash === v || Array === v }
113
- end
114
- when Array
115
- v.map { |e| to_hash_from_indifferent e }
116
- else
117
- v
118
+ def to_hash_from_indifferent(value)
119
+ case value
120
+ when Hash
121
+ value.stringify_keys.to_hash.tap do |h|
122
+ h.each { |k, v| h[k] = to_hash_from_indifferent(v) if v.is_a?(Hash) || v.is_a?(Array) }
123
+ end
124
+ when Array
125
+ value.map { |e| to_hash_from_indifferent e }
126
+ else
127
+ value
118
128
  end
119
129
  end
120
130
  end
@@ -27,14 +27,15 @@ module I18n::Tasks
27
27
 
28
28
  module Messages
29
29
  include Term::ANSIColor
30
- extend self
30
+
31
+ module_function
31
32
 
32
33
  def banner
33
34
  bold("i18n-tasks v#{I18n::Tasks::VERSION} IRB") + "\nType #{green 'guide'} to learn more"
34
35
  end
35
36
 
36
37
  def guide
37
- green(bold "i18n-tasks IRB Quick Start guide") + "\n" + <<-TEXT
38
+ green(bold('i18n-tasks IRB Quick Start guide')) + "\n" + <<-TEXT
38
39
  #{yellow 'Data as trees'}
39
40
  tree(locale)
40
41
  used_tree(key_filter: nil, strict: nil)
@@ -4,15 +4,16 @@ require 'i18n/tasks/data/file_system'
4
4
  module I18n::Tasks
5
5
  module Data
6
6
  DATA_DEFAULTS = {
7
- adapter: 'I18n::Tasks::Data::FileSystem'
8
- }
7
+ adapter: 'I18n::Tasks::Data::FileSystem'
8
+ }.freeze
9
9
 
10
10
  # I18n data provider
11
11
  # @see I18n::Tasks::Data::FileSystem
12
12
  def data
13
13
  @data ||= begin
14
14
  data_config = (config[:data] || {}).deep_symbolize_keys
15
- data_config.merge!(base_locale: base_locale, locales: config[:locales])
15
+ data_config[:base_locale] = base_locale
16
+ data_config[:locales] = config[:locales]
16
17
  adapter_class = data_config[:adapter].presence || data_config[:class].presence || DATA_DEFAULTS[:adapter]
17
18
  adapter_class = adapter_class.to_s
18
19
  adapter_class = 'I18n::Tasks::Data::FileSystem' if adapter_class == 'file_system'
@@ -59,7 +60,7 @@ module I18n::Tasks
59
60
 
60
61
  # write to store, normalizing all data
61
62
  def normalize_store!(from = nil, pattern_router = false)
62
- from = self.locales unless from
63
+ from = locales unless from
63
64
  router = pattern_router ? ::I18n::Tasks::Data::Router::PatternRouter.new(data, data.config) : data.router
64
65
  data.with_router(router) do
65
66
  Array(from).each do |target_locale|