i18n-tasks 1.0.14 → 1.1.0

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +138 -39
  3. data/Rakefile +4 -4
  4. data/bin/i18n-tasks +3 -3
  5. data/config/locales/en.yml +17 -1
  6. data/config/locales/ru.yml +18 -1
  7. data/i18n-tasks.gemspec +28 -38
  8. data/lib/i18n/tasks/base_task.rb +19 -19
  9. data/lib/i18n/tasks/cli.rb +37 -30
  10. data/lib/i18n/tasks/command/collection.rb +4 -4
  11. data/lib/i18n/tasks/command/commander.rb +5 -5
  12. data/lib/i18n/tasks/command/commands/check_prism.rb +126 -0
  13. data/lib/i18n/tasks/command/commands/data.rb +33 -33
  14. data/lib/i18n/tasks/command/commands/eq_base.rb +3 -3
  15. data/lib/i18n/tasks/command/commands/health.rb +6 -5
  16. data/lib/i18n/tasks/command/commands/interpolations.rb +14 -3
  17. data/lib/i18n/tasks/command/commands/meta.rb +6 -6
  18. data/lib/i18n/tasks/command/commands/missing.rb +28 -26
  19. data/lib/i18n/tasks/command/commands/tree.rb +33 -33
  20. data/lib/i18n/tasks/command/commands/usages.rb +24 -24
  21. data/lib/i18n/tasks/command/dsl.rb +1 -1
  22. data/lib/i18n/tasks/command/option_parsers/enum.rb +8 -7
  23. data/lib/i18n/tasks/command/option_parsers/locale.rb +4 -4
  24. data/lib/i18n/tasks/command/options/common.rb +16 -16
  25. data/lib/i18n/tasks/command/options/data.rb +18 -18
  26. data/lib/i18n/tasks/command/options/locales.rb +33 -24
  27. data/lib/i18n/tasks/commands.rb +14 -12
  28. data/lib/i18n/tasks/concurrent/cache.rb +1 -1
  29. data/lib/i18n/tasks/concurrent/cached_value.rb +1 -1
  30. data/lib/i18n/tasks/configuration.rb +26 -20
  31. data/lib/i18n/tasks/console_context.rb +11 -11
  32. data/lib/i18n/tasks/data/adapter/json_adapter.rb +1 -1
  33. data/lib/i18n/tasks/data/adapter/yaml_adapter.rb +5 -5
  34. data/lib/i18n/tasks/data/file_formats.rb +3 -3
  35. data/lib/i18n/tasks/data/file_system.rb +5 -5
  36. data/lib/i18n/tasks/data/file_system_base.rb +26 -26
  37. data/lib/i18n/tasks/data/language_names.rb +202 -0
  38. data/lib/i18n/tasks/data/router/conservative_router.rb +3 -3
  39. data/lib/i18n/tasks/data/router/isolating_router.rb +19 -19
  40. data/lib/i18n/tasks/data/router/pattern_router.rb +5 -5
  41. data/lib/i18n/tasks/data/tree/node.rb +27 -27
  42. data/lib/i18n/tasks/data/tree/nodes.rb +10 -10
  43. data/lib/i18n/tasks/data/tree/siblings.rb +20 -20
  44. data/lib/i18n/tasks/data/tree/traversal.rb +5 -5
  45. data/lib/i18n/tasks/data.rb +4 -4
  46. data/lib/i18n/tasks/html_keys.rb +2 -2
  47. data/lib/i18n/tasks/ignore_keys.rb +9 -9
  48. data/lib/i18n/tasks/interpolations.rb +21 -1
  49. data/lib/i18n/tasks/key_pattern_matching.rb +8 -8
  50. data/lib/i18n/tasks/logging.rb +2 -1
  51. data/lib/i18n/tasks/missing_keys.rb +24 -8
  52. data/lib/i18n/tasks/plural_keys.rb +6 -4
  53. data/lib/i18n/tasks/references.rb +4 -4
  54. data/lib/i18n/tasks/reports/base.rb +18 -14
  55. data/lib/i18n/tasks/reports/terminal.rb +64 -47
  56. data/lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb +3 -3
  57. data/lib/i18n/tasks/scanners/ast_matchers/default_i18n_subject_matcher.rb +3 -3
  58. data/lib/i18n/tasks/scanners/ast_matchers/message_receivers_matcher.rb +10 -10
  59. data/lib/i18n/tasks/scanners/ast_matchers/rails_model_matcher.rb +2 -2
  60. data/lib/i18n/tasks/scanners/erb_ast_scanner.rb +69 -10
  61. data/lib/i18n/tasks/scanners/file_scanner.rb +5 -5
  62. data/lib/i18n/tasks/scanners/files/caching_file_finder.rb +3 -3
  63. data/lib/i18n/tasks/scanners/files/caching_file_finder_provider.rb +3 -3
  64. data/lib/i18n/tasks/scanners/files/caching_file_reader.rb +2 -2
  65. data/lib/i18n/tasks/scanners/files/file_finder.rb +8 -8
  66. data/lib/i18n/tasks/scanners/files/file_reader.rb +1 -1
  67. data/lib/i18n/tasks/scanners/local_ruby_parser.rb +9 -9
  68. data/lib/i18n/tasks/scanners/occurrence_from_position.rb +1 -1
  69. data/lib/i18n/tasks/scanners/pattern_mapper.rb +7 -7
  70. data/lib/i18n/tasks/scanners/pattern_scanner.rb +20 -20
  71. data/lib/i18n/tasks/scanners/pattern_with_scope_scanner.rb +8 -8
  72. data/lib/i18n/tasks/scanners/prism_scanners/arguments_visitor.rb +48 -0
  73. data/lib/i18n/tasks/scanners/prism_scanners/nodes.rb +374 -0
  74. data/lib/i18n/tasks/scanners/prism_scanners/visitor.rb +337 -0
  75. data/lib/i18n/tasks/scanners/relative_keys.rb +8 -8
  76. data/lib/i18n/tasks/scanners/results/key_occurrences.rb +3 -3
  77. data/lib/i18n/tasks/scanners/results/occurrence.rb +14 -10
  78. data/lib/i18n/tasks/scanners/ruby_ast_call_finder.rb +1 -1
  79. data/lib/i18n/tasks/scanners/ruby_key_literals.rb +6 -6
  80. data/lib/i18n/tasks/scanners/ruby_parser_factory.rb +27 -0
  81. data/lib/i18n/tasks/scanners/ruby_scanner.rb +225 -0
  82. data/lib/i18n/tasks/scanners/scanner.rb +2 -2
  83. data/lib/i18n/tasks/scanners/scanner_multiplexer.rb +1 -1
  84. data/lib/i18n/tasks/split_key.rb +4 -4
  85. data/lib/i18n/tasks/stats.rb +3 -3
  86. data/lib/i18n/tasks/translation.rb +8 -5
  87. data/lib/i18n/tasks/translators/base_translator.rb +43 -13
  88. data/lib/i18n/tasks/translators/deepl_translator.rb +22 -14
  89. data/lib/i18n/tasks/translators/google_translator.rb +178 -26
  90. data/lib/i18n/tasks/translators/openai_translator.rb +56 -31
  91. data/lib/i18n/tasks/translators/watsonx_translator.rb +155 -0
  92. data/lib/i18n/tasks/translators/yandex_translator.rb +13 -9
  93. data/lib/i18n/tasks/unused_keys.rb +1 -1
  94. data/lib/i18n/tasks/used_keys.rb +32 -32
  95. data/lib/i18n/tasks/version.rb +1 -1
  96. data/lib/i18n/tasks.rb +17 -16
  97. data/templates/config/i18n-tasks.yml +14 -2
  98. data/templates/minitest/i18n_test.rb +3 -3
  99. data/templates/rspec/i18n_spec.rb +7 -7
  100. metadata +38 -172
  101. data/lib/i18n/tasks/scanners/ruby_ast_scanner.rb +0 -145
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'i18n/tasks/concurrent/cached_value'
3
+ require "i18n/tasks/concurrent/cached_value"
4
4
 
5
5
  module I18n::Tasks::Concurrent
6
6
  # A thread-safe cache.
@@ -35,7 +35,7 @@ module I18n::Tasks::Concurrent
35
35
  # Below are the implementations for major ruby engines, based on concurrent-ruby.
36
36
  # rubocop:disable Lint/DuplicateMethods,Naming/AccessorMethodName
37
37
  case RUBY_ENGINE
38
- when 'rbx'
38
+ when "rbx"
39
39
  def get_result_volatile
40
40
  Rubinius.memory_barrier
41
41
  @result
@@ -2,10 +2,11 @@
2
2
 
3
3
  module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
4
4
  DEFAULTS = {
5
- base_locale: 'en',
6
- internal_locale: 'en',
5
+ base_locale: "en",
6
+ internal_locale: "en",
7
7
  search: ::I18n::Tasks::UsedKeys::SEARCH_DEFAULTS,
8
- data: ::I18n::Tasks::Data::DATA_DEFAULTS
8
+ data: ::I18n::Tasks::Data::DATA_DEFAULTS,
9
+ translation_backend: :google
9
10
  }.freeze
10
11
 
11
12
  # i18n-tasks config (defaults + config/i18n-tasks.yml)
@@ -20,20 +21,20 @@ module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
20
21
  ].freeze
21
22
 
22
23
  def file_config
23
- file = @config_override || CONFIG_FILES.detect { |f| File.exist?(f) }
24
+ file = @config_override || CONFIG_FILES.detect { |f| File.exist?(f) }
24
25
  # rubocop:disable Security/Eval
25
- config = file && YAML.load(eval(Erubi::Engine.new(File.read(file, encoding: 'UTF-8')).src))
26
+ config = file && YAML.load(eval(Erubi::Engine.new(File.read(file, encoding: "UTF-8")).src))
26
27
  # rubocop:enable Security/Eval
27
28
  if config.present?
28
29
  config.with_indifferent_access.tap do |c|
29
30
  if c[:relative_roots]
30
- warn_deprecated 'Please move relative_roots under search in config/i18n-tasks.yml.'
31
+ warn_deprecated "Please move relative_roots under search in config/i18n-tasks.yml."
31
32
  c[:search][:relative_roots] = c.delete(:relative_roots)
32
33
  end
33
34
 
34
35
  if c.dig(:search, :exclude_method_name_paths)
35
36
  warn_deprecated(
36
- 'Please rename exclude_method_name_paths to relative_exclude_method_name_paths in config/i18n-tasks.yml.'
37
+ "Please rename exclude_method_name_paths to relative_exclude_method_name_paths in config/i18n-tasks.yml."
37
38
  )
38
39
  c[:search][:relative_exclude_method_name_paths] = c[:search].delete(:exclude_method_name_paths)
39
40
  end
@@ -59,16 +60,21 @@ module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
59
60
 
60
61
  # translation config
61
62
  # @return [Hash{String => String,Hash,Array}]
62
- def translation_config
63
+ def translation_config # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
63
64
  @config_sections[:translation] ||= begin
64
65
  conf = (config[:translation] || {}).with_indifferent_access
65
- conf[:google_translate_api_key] = ENV['GOOGLE_TRANSLATE_API_KEY'] if ENV.key?('GOOGLE_TRANSLATE_API_KEY')
66
- conf[:deepl_api_key] = ENV['DEEPL_AUTH_KEY'] if ENV.key?('DEEPL_AUTH_KEY')
67
- conf[:deepl_host] = ENV['DEEPL_HOST'] if ENV.key?('DEEPL_HOST')
68
- conf[:deepl_version] = ENV['DEEPL_VERSION'] if ENV.key?('DEEPL_VERSION')
69
- conf[:openai_api_key] = ENV['OPENAI_API_KEY'] if ENV.key?('OPENAI_API_KEY')
70
- conf[:openai_model] = ENV['OPENAI_MODEL'] if ENV.key?('OPENAI_MODEL')
71
- conf[:yandex_api_key] = ENV['YANDEX_API_KEY'] if ENV.key?('YANDEX_API_KEY')
66
+ conf[:backend] ||= DEFAULTS[:translation_backend]
67
+ conf[:google_translate_api_key] = ENV["GOOGLE_TRANSLATE_API_KEY"] if ENV.key?("GOOGLE_TRANSLATE_API_KEY")
68
+ conf[:deepl_api_key] = ENV["DEEPL_AUTH_KEY"] if ENV.key?("DEEPL_AUTH_KEY")
69
+ conf[:deepl_host] = ENV["DEEPL_HOST"] if ENV.key?("DEEPL_HOST")
70
+ conf[:deepl_version] = ENV["DEEPL_VERSION"] if ENV.key?("DEEPL_VERSION")
71
+ conf[:openai_api_key] = ENV["OPENAI_API_KEY"] if ENV.key?("OPENAI_API_KEY")
72
+ conf[:openai_model] = ENV["OPENAI_MODEL"] if ENV.key?("OPENAI_MODEL")
73
+ conf[:openai_locale_prompts] ||= {}
74
+ conf[:watsonx_api_key] = ENV["WATSONX_API_KEY"] if ENV.key?("WATSONX_API_KEY")
75
+ conf[:watsonx_project_id] = ENV["WATSONX_PROJECT_ID"] if ENV.key?("WATSONX_PROJECT_ID")
76
+ conf[:watsonx_model] = ENV["WATSONX_MODEL"] if ENV.key?("WATSONX_MODEL")
77
+ conf[:yandex_api_key] = ENV["YANDEX_API_KEY"] if ENV.key?("YANDEX_API_KEY")
72
78
  conf
73
79
  end
74
80
  end
@@ -86,11 +92,11 @@ module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
86
92
  def internal_locale
87
93
  @config_sections[:internal_locale] ||= begin
88
94
  internal_locale = (config[:internal_locale] || DEFAULTS[:internal_locale]).to_s
89
- valid_locales = Dir[File.join(I18n::Tasks.gem_path, 'config', 'locales', '*.yml')]
90
- .map { |f| File.basename(f, '.yml') }
95
+ valid_locales = Dir[File.join(I18n::Tasks.gem_path, "config", "locales", "*.yml")]
96
+ .map { |f| File.basename(f, ".yml") }
91
97
  unless valid_locales.include?(internal_locale)
92
98
  log_warn "invalid internal_locale #{internal_locale.inspect}. " \
93
- "Available internal locales: #{valid_locales * ', '}."
99
+ "Available internal locales: #{valid_locales * ", "}."
94
100
  internal_locale = DEFAULTS[:internal_locale].to_s
95
101
  end
96
102
  internal_locale
@@ -98,7 +104,7 @@ module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
98
104
  end
99
105
 
100
106
  def ignore_config(type = nil)
101
- key = type ? "ignore_#{type}" : 'ignore'
107
+ key = type ? "ignore_#{type}" : "ignore"
102
108
  @config_sections[key] ||= config[key]
103
109
  end
104
110
 
@@ -121,7 +127,7 @@ module I18n::Tasks::Configuration # rubocop:disable Metrics/ModuleLength
121
127
  def config_for_inspect
122
128
  to_hash_from_indifferent(config_sections.reject { |_k, v| v.blank? }).tap do |sections|
123
129
  sections.each_value do |section|
124
- section.merge! section.delete('config') if section.is_a?(Hash) && section.key?('config')
130
+ section.merge! section.delete("config") if section.is_a?(Hash) && section.key?("config")
125
131
  end
126
132
  end
127
133
  end
@@ -16,12 +16,12 @@ module I18n::Tasks
16
16
 
17
17
  class << self
18
18
  def start
19
- require 'irb'
19
+ require "irb"
20
20
  IRB.setup nil
21
21
  ctx = IRB::Irb.new.context
22
22
  IRB.conf[:MAIN_CONTEXT] = ctx
23
- $stderr.puts Messages.banner
24
- require 'irb/ext/multi-irb'
23
+ warn Messages.banner
24
+ require "irb/ext/multi-irb"
25
25
  IRB.irb nil, new
26
26
  end
27
27
  end
@@ -30,18 +30,18 @@ module I18n::Tasks
30
30
  module_function
31
31
 
32
32
  def banner
33
- Rainbow("i18n-tasks v#{I18n::Tasks::VERSION} IRB").bright + "\nType #{Rainbow('guide').green} to learn more"
33
+ Rainbow("i18n-tasks v#{I18n::Tasks::VERSION} IRB").bright + "\nType #{Rainbow("guide").green} to learn more"
34
34
  end
35
35
 
36
36
  def guide
37
- "#{Rainbow('i18n-tasks IRB Quick Start guide').green.bright}\n#{<<~TEXT}"
38
- #{Rainbow('Data as trees').yellow}
37
+ "#{Rainbow("i18n-tasks IRB Quick Start guide").green.bright}\n#{<<~TEXT}"
38
+ #{Rainbow("Data as trees").yellow}
39
39
  tree(locale)
40
40
  used_tree(key_filter: nil, strict: nil)
41
41
  unused_tree(locale: base_locale, strict: nil)
42
42
  build_tree('es' => {'hello' => 'Hola'})
43
43
 
44
- #{Rainbow('Traversal').yellow}
44
+ #{Rainbow("Traversal").yellow}
45
45
  tree = missing_diff_tree('es')
46
46
  tree.nodes { |node| }
47
47
  tree.nodes.to_a
@@ -49,23 +49,23 @@ module I18n::Tasks
49
49
  tree.each { |root_node| }
50
50
  # also levels, depth_first, and breadth_first
51
51
 
52
- #{Rainbow('Select nodes').yellow}
52
+ #{Rainbow("Select nodes").yellow}
53
53
  tree.select_nodes { |node| } # new tree with only selected nodes
54
54
 
55
- #{Rainbow('Match by full key').yellow}
55
+ #{Rainbow("Match by full key").yellow}
56
56
  tree.select_keys { |key, leaf| } # new tree with only selected keys
57
57
  tree.grep_keys(/hello/) # grep, using ===
58
58
  tree.keys { |key, leaf| } # enumerate over [full_key, leaf_node]
59
59
  # Pass {root: true} to include root node in full_key (usually locale)
60
60
 
61
- #{Rainbow('Nodes').yellow}
61
+ #{Rainbow("Nodes").yellow}
62
62
  node = node(key, locale)
63
63
  node.key # only the part after the last dot
64
64
  node.full_key # full key. Includes root key, pass {root: false} to override.
65
65
  # also: value, value_or_children_hash, data, walk_to_root, walk_from_root
66
66
  Tree::Node.new(key: 'en')
67
67
 
68
- #{Rainbow('Keys').yellow}
68
+ #{Rainbow("Keys").yellow}
69
69
  t(key, locale)
70
70
  key_value?(key, locale)
71
71
  depluralize_key(key, locale) # convert 'hat.one' to 'hat'
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
3
+ require "json"
4
4
 
5
5
  module I18n::Tasks
6
6
  module Data
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml'
3
+ require "yaml"
4
4
  module I18n::Tasks
5
5
  module Data
6
6
  module Adapter
7
7
  module YamlAdapter
8
- EMOJI_REGEX = /\\u[\da-f]{8}/i.freeze
9
- TRAILING_SPACE_REGEX = / $/.freeze
8
+ EMOJI_REGEX = /\\u[\da-f]{8}/i
9
+ TRAILING_SPACE_REGEX = / $/
10
10
 
11
11
  class << self
12
12
  # @return [Hash] locale tree
@@ -26,12 +26,12 @@ module I18n::Tasks
26
26
 
27
27
  # @return [String]
28
28
  def restore_emojis(yaml)
29
- yaml.gsub(EMOJI_REGEX) { |m| [m[-8..].to_i(16)].pack('U') }
29
+ yaml.gsub(EMOJI_REGEX) { |m| [m[-8..].to_i(16)].pack("U") }
30
30
  end
31
31
 
32
32
  # @return [String]
33
33
  def strip_trailing_spaces(yaml)
34
- yaml.gsub(TRAILING_SPACE_REGEX, '')
34
+ yaml.gsub(TRAILING_SPACE_REGEX, "")
35
35
  end
36
36
  end
37
37
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'fileutils'
3
+ require "fileutils"
4
4
 
5
5
  module I18n
6
6
  module Tasks
@@ -21,7 +21,7 @@ module I18n
21
21
 
22
22
  def adapter_op(op, format, tree, config)
23
23
  self.class.adapter_by_name(format).send(op, tree, config)
24
- rescue Exception => e # rubocop:disable Lint/RescueException
24
+ rescue => e
25
25
  raise CommandError, "#{format} #{op} error: #{e.message}"
26
26
  end
27
27
 
@@ -44,7 +44,7 @@ module I18n
44
44
 
45
45
  # @return [String]
46
46
  def read_file(path)
47
- ::File.read(path, encoding: 'UTF-8')
47
+ ::File.read(path, encoding: "UTF-8")
48
48
  end
49
49
 
50
50
  def write_tree(path, tree, sort = true)
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'i18n/tasks/data/file_system_base'
4
- require 'i18n/tasks/data/adapter/json_adapter'
5
- require 'i18n/tasks/data/adapter/yaml_adapter'
3
+ require "i18n/tasks/data/file_system_base"
4
+ require "i18n/tasks/data/adapter/json_adapter"
5
+ require "i18n/tasks/data/adapter/yaml_adapter"
6
6
 
7
7
  module I18n::Tasks
8
8
  module Data
9
9
  class FileSystem < FileSystemBase
10
- register_adapter :yaml, '*.yml', Adapter::YamlAdapter
11
- register_adapter :json, '*.json', Adapter::JsonAdapter
10
+ register_adapter :yaml, "*.yml", Adapter::YamlAdapter
11
+ register_adapter :json, "*.json", Adapter::JsonAdapter
12
12
  end
13
13
  end
14
14
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'i18n/tasks/data/tree/node'
4
- require 'i18n/tasks/data/router/pattern_router'
5
- require 'i18n/tasks/data/router/conservative_router'
6
- require 'i18n/tasks/data/router/isolating_router'
7
- require 'i18n/tasks/data/file_formats'
8
- require 'i18n/tasks/key_pattern_matching'
3
+ require "i18n/tasks/data/tree/node"
4
+ require "i18n/tasks/data/router/pattern_router"
5
+ require "i18n/tasks/data/router/conservative_router"
6
+ require "i18n/tasks/data/router/isolating_router"
7
+ require "i18n/tasks/data/file_formats"
8
+ require "i18n/tasks/key_pattern_matching"
9
9
 
10
10
  module I18n::Tasks
11
11
  module Data
@@ -18,8 +18,8 @@ module I18n::Tasks
18
18
  attr_writer :router
19
19
 
20
20
  DEFAULTS = {
21
- read: ['config/locales/%{locale}.yml'],
22
- write: ['config/locales/%{locale}.yml']
21
+ read: ["config/locales/%{locale}.yml"],
22
+ write: ["config/locales/%{locale}.yml"]
23
23
  }.freeze
24
24
 
25
25
  def initialize(config = {})
@@ -29,9 +29,9 @@ module I18n::Tasks
29
29
  locales = config[:locales].presence
30
30
  @locales = LocaleList.normalize_locale_list(locales || available_locales, base_locale, true)
31
31
  if locales.present?
32
- log_verbose "locales read from config #{@locales * ', '}"
32
+ log_verbose "locales read from config #{@locales * ", "}"
33
33
  else
34
- log_verbose "locales inferred from data: #{@locales * ', '}"
34
+ log_verbose "locales inferred from data: #{@locales * ", "}"
35
35
  end
36
36
  end
37
37
 
@@ -43,7 +43,7 @@ module I18n::Tasks
43
43
  @trees[locale] ||= read_locale(locale)
44
44
  end
45
45
 
46
- alias [] get
46
+ alias_method :[], :get
47
47
 
48
48
  # @param [String, Symbol] locale
49
49
  # @return [::I18n::Tasks::Data::Siblings]
@@ -72,14 +72,14 @@ module I18n::Tasks
72
72
  @available_locales = nil
73
73
  end
74
74
 
75
- alias []= set
75
+ alias_method :[]=, :set
76
76
 
77
77
  # @param [String] locale
78
78
  # @return [Array<String>] paths to files that are not normalized
79
79
  def non_normalized_paths(locale)
80
80
  router.route(locale, get(locale))
81
- .reject { |path, tree_slice| normalized?(path, tree_slice) }
82
- .map(&:first)
81
+ .reject { |path, tree_slice| normalized?(path, tree_slice) }
82
+ .map(&:first)
83
83
  end
84
84
 
85
85
  def write(forest)
@@ -107,7 +107,7 @@ module I18n::Tasks
107
107
 
108
108
  # @return self
109
109
  def reload
110
- @trees = nil
110
+ @trees = nil
111
111
  @available_locales = nil
112
112
  self
113
113
  end
@@ -117,10 +117,10 @@ module I18n::Tasks
117
117
  @available_locales ||= begin
118
118
  locales = Set.new
119
119
  Array(config[:read]).map do |pattern|
120
- [pattern, Dir.glob(format(pattern, locale: '*'))] if pattern.include?('%{locale}')
120
+ [pattern, Dir.glob(format(pattern, locale: "*"))] if pattern.include?("%{locale}")
121
121
  end.compact.each do |pattern, paths|
122
- p = pattern.gsub('\\', '\\\\').gsub('/', '\/').gsub('.', '\.')
123
- p = p.gsub(/(\*+)/) { Regexp.last_match(1) == '**' ? '.*' : '[^/]*?' }.gsub('%{locale}', '([^/.]+)')
122
+ p = pattern.gsub("\\", "\\\\").gsub("/", '\/').gsub(".", '\.')
123
+ p = p.gsub(/(\*+)/) { (Regexp.last_match(1) == "**") ? ".*" : "[^/]*?" }.gsub("%{locale}", "([^/.]+)")
124
124
  re = /\A#{p}\z/
125
125
  paths.each do |path|
126
126
  locales << Regexp.last_match(1) if re =~ path
@@ -143,7 +143,7 @@ module I18n::Tasks
143
143
  end
144
144
 
145
145
  def with_router(router)
146
- router_was = self.router
146
+ router_was = self.router
147
147
  self.router = router
148
148
  yield
149
149
  ensure
@@ -151,13 +151,13 @@ module I18n::Tasks
151
151
  end
152
152
 
153
153
  ROUTER_NAME_ALIASES = {
154
- 'conservative_router' => 'I18n::Tasks::Data::Router::ConservativeRouter',
155
- 'isolating_router' => 'I18n::Tasks::Data::Router::IsolatingRouter',
156
- 'pattern_router' => 'I18n::Tasks::Data::Router::PatternRouter'
154
+ "conservative_router" => "I18n::Tasks::Data::Router::ConservativeRouter",
155
+ "isolating_router" => "I18n::Tasks::Data::Router::IsolatingRouter",
156
+ "pattern_router" => "I18n::Tasks::Data::Router::PatternRouter"
157
157
  }.freeze
158
158
  def router
159
159
  @router ||= begin
160
- name = @config[:router].presence || 'conservative_router'
160
+ name = @config[:router].presence || "conservative_router"
161
161
  name = ROUTER_NAME_ALIASES[name] || name
162
162
  router_class = ActiveSupport::Inflector.constantize(name)
163
163
  router_class.new(self, @config.merge(base_locale: base_locale, locales: locales))
@@ -173,7 +173,7 @@ module I18n::Tasks
173
173
  [path.freeze, load_file(path) || {}]
174
174
  end.map do |path, data|
175
175
  if router.is_a?(I18n::Tasks::Data::Router::IsolatingRouter)
176
- data.transform_values! { |tree| { "<#{router.alternate_path_for(path, base_locale)}>" => tree } }
176
+ data.transform_values! { |tree| {"<#{router.alternate_path_for(path, base_locale)}>" => tree} }
177
177
  end
178
178
  filter_nil_keys! path, data
179
179
  Data::Tree::Siblings.from_nested_hash(data).tap do |s|
@@ -188,11 +188,11 @@ module I18n::Tasks
188
188
  data.delete(key)
189
189
  log_warn <<~TEXT
190
190
  Skipping a nil key found in #{path.inspect}:
191
- key: #{suffix.join('.')}.`nil`
191
+ key: #{suffix.join(".")}.`nil`
192
192
  value: #{value.inspect}
193
193
  Nil keys are not supported by i18n.
194
194
  The following unquoted YAML keys result in a nil key:
195
- #{%w[null Null NULL ~].join(', ')}
195
+ #{%w[null Null NULL ~].join(", ")}
196
196
  See http://yaml.org/type/null.html
197
197
  TEXT
198
198
  elsif value.is_a?(Hash)
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ module I18n
4
+ module Tasks
5
+ module Data
6
+ module LanguageNames # rubocop:disable Metrics/ModuleLength
7
+ # Data loaded from https://github.com/grosser/i18n_data
8
+ # I18nData.languages.transform_keys!(&:to_sym).transform_values!{|v| v.split(";").first }
9
+ DATA = {
10
+ AA: "Afar",
11
+ AB: "Abkhazian",
12
+ AF: "Afrikaans",
13
+ AK: "Akan",
14
+ AM: "Amharic",
15
+ AR: "Arabic",
16
+ AN: "Aragonese",
17
+ AS: "Assamese",
18
+ AV: "Avaric",
19
+ AE: "Avestan",
20
+ AY: "Aymara",
21
+ AZ: "Azerbaijani",
22
+ BA: "Bashkir",
23
+ BM: "Bambara",
24
+ BE: "Belarusian",
25
+ BN: "Bengali",
26
+ BH: "Bihari languages",
27
+ BI: "Bislama",
28
+ BO: "Tibetan",
29
+ BS: "Bosnian",
30
+ BR: "Breton",
31
+ BG: "Bulgarian",
32
+ CA: "Catalan",
33
+ CS: "Czech",
34
+ CH: "Chamorro",
35
+ CE: "Chechen",
36
+ CU: "Church Slavic",
37
+ CV: "Chuvash",
38
+ KW: "Cornish",
39
+ CO: "Corsican",
40
+ CR: "Cree",
41
+ CY: "Welsh",
42
+ DA: "Danish",
43
+ DE: "German",
44
+ DV: "Divehi",
45
+ DZ: "Dzongkha",
46
+ EL: "Greek, Modern (1453-)",
47
+ EN: "English",
48
+ EO: "Esperanto",
49
+ ET: "Estonian",
50
+ EU: "Basque",
51
+ EE: "Ewe",
52
+ FO: "Faroese",
53
+ FA: "Persian",
54
+ FJ: "Fijian",
55
+ FI: "Finnish",
56
+ FR: "French",
57
+ FY: "Western Frisian",
58
+ FF: "Fulah",
59
+ GD: "Gaelic",
60
+ GA: "Irish",
61
+ GL: "Galician",
62
+ GV: "Manx",
63
+ GN: "Guarani",
64
+ GU: "Gujarati",
65
+ HT: "Haitian",
66
+ HA: "Hausa",
67
+ HE: "Hebrew",
68
+ HZ: "Herero",
69
+ HI: "Hindi",
70
+ HO: "Hiri Motu",
71
+ HR: "Croatian",
72
+ HU: "Hungarian",
73
+ HY: "Armenian",
74
+ IG: "Igbo",
75
+ IO: "Ido",
76
+ II: "Sichuan Yi",
77
+ IU: "Inuktitut",
78
+ IE: "Interlingue",
79
+ IA: "Interlingua (International Auxiliary Language Association)",
80
+ ID: "Indonesian",
81
+ IK: "Inupiaq",
82
+ IS: "Icelandic",
83
+ IT: "Italian",
84
+ JV: "Javanese",
85
+ JA: "Japanese",
86
+ KL: "Kalaallisut",
87
+ KN: "Kannada",
88
+ KS: "Kashmiri",
89
+ KA: "Georgian",
90
+ KR: "Kanuri",
91
+ KK: "Kazakh",
92
+ KM: "Central Khmer",
93
+ KI: "Kikuyu",
94
+ RW: "Kinyarwanda",
95
+ KY: "Kirghiz",
96
+ KV: "Komi",
97
+ KG: "Kongo",
98
+ KO: "Korean",
99
+ KJ: "Kuanyama",
100
+ KU: "Kurdish",
101
+ LO: "Lao",
102
+ LA: "Latin",
103
+ LV: "Latvian",
104
+ LI: "Limburgan",
105
+ LN: "Lingala",
106
+ LT: "Lithuanian",
107
+ LB: "Luxembourgish",
108
+ LU: "Luba-Katanga",
109
+ LG: "Ganda",
110
+ MH: "Marshallese",
111
+ ML: "Malayalam",
112
+ MR: "Marathi",
113
+ MK: "Macedonian",
114
+ MG: "Malagasy",
115
+ MT: "Maltese",
116
+ MN: "Mongolian",
117
+ MI: "Maori",
118
+ MS: "Malay",
119
+ MY: "Burmese",
120
+ NA: "Nauru",
121
+ NV: "Navajo",
122
+ NR: "Ndebele, South",
123
+ ND: "Ndebele, North",
124
+ NG: "Ndonga",
125
+ NE: "Nepali",
126
+ NL: "Dutch",
127
+ NN: "Norwegian Nynorsk",
128
+ NB: "Bokmål, Norwegian",
129
+ NO: "Norwegian",
130
+ NY: "Chichewa",
131
+ OC: "Occitan (post 1500)",
132
+ OJ: "Ojibwa",
133
+ OR: "Oriya",
134
+ OM: "Oromo",
135
+ OS: "Ossetian",
136
+ PA: "Panjabi",
137
+ PI: "Pali",
138
+ PL: "Polish",
139
+ PT: "Portuguese",
140
+ PS: "Pushto",
141
+ QU: "Quechua",
142
+ RM: "Romansh",
143
+ RO: "Romanian",
144
+ RN: "Rundi",
145
+ RU: "Russian",
146
+ SG: "Sango",
147
+ SA: "Sanskrit",
148
+ SI: "Sinhala",
149
+ SK: "Slovak",
150
+ SL: "Slovenian",
151
+ SE: "Northern Sami",
152
+ SM: "Samoan",
153
+ SN: "Shona",
154
+ SD: "Sindhi",
155
+ SO: "Somali",
156
+ ST: "Sotho, Southern",
157
+ ES: "Spanish",
158
+ SQ: "Albanian",
159
+ SC: "Sardinian",
160
+ SR: "Serbian",
161
+ SS: "Swati",
162
+ SU: "Sundanese",
163
+ SW: "Swahili",
164
+ SV: "Swedish",
165
+ TY: "Tahitian",
166
+ TA: "Tamil",
167
+ TT: "Tatar",
168
+ TE: "Telugu",
169
+ TG: "Tajik",
170
+ TL: "Tagalog",
171
+ TH: "Thai",
172
+ TI: "Tigrinya",
173
+ TO: "Tonga (Tonga Islands)",
174
+ TN: "Tswana",
175
+ TS: "Tsonga",
176
+ TK: "Turkmen",
177
+ TR: "Turkish",
178
+ TW: "Twi",
179
+ UG: "Uighur",
180
+ UK: "Ukrainian",
181
+ UR: "Urdu",
182
+ UZ: "Uzbek",
183
+ VE: "Venda",
184
+ VI: "Vietnamese",
185
+ VO: "Volapük",
186
+ WA: "Walloon",
187
+ WO: "Wolof",
188
+ XH: "Xhosa",
189
+ YI: "Yiddish",
190
+ YO: "Yoruba",
191
+ ZA: "Zhuang",
192
+ ZH: "Chinese",
193
+ ZU: "Zulu"
194
+ }.freeze
195
+
196
+ def language_name(locale)
197
+ DATA[locale.upcase.to_sym] || locale
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'i18n/tasks/data/router/pattern_router'
3
+ require "i18n/tasks/data/router/pattern_router"
4
4
 
5
5
  module I18n::Tasks
6
6
  module Data::Router
7
7
  # Keep the path, or infer from base locale
8
8
  class ConservativeRouter < PatternRouter
9
9
  def initialize(adapter, config)
10
- @adapter = adapter
10
+ @adapter = adapter
11
11
  @base_locale = config[:base_locale]
12
- @locales = config[:locales]
12
+ @locales = config[:locales]
13
13
  super
14
14
  end
15
15