i18n-linter-rb 0.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.
- checksums.yaml +7 -0
- data/exe/i18n-linter-rb +5 -0
- data/lib/i18n_linter_rb/cli.rb +116 -0
- data/lib/i18n_linter_rb/linter.rb +44 -0
- data/lib/i18n_linter_rb/version.rb +3 -0
- data/lib/i18n_linter_rb.rb +9 -0
- metadata +65 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8be824b04d9dc87841bb4a53ded28fdc99c745db2b5ec0473aefb3feb0903430
|
|
4
|
+
data.tar.gz: 7cc5a3f6398b114022e1c103f639642c9200dbfda01e61e1b0e13671e675faa0
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 66b748b2fcdb6d546c0678fccc86dec7e5d9316c6f4ced5c3bd0edf3c511363988971648be72e40b3d56668b45e5b32bdf3f1197a90fd23c4860dac6355d2ca2
|
|
7
|
+
data.tar.gz: 9b7963b6f8c53d4e372831455ca52bcc8ac2ebb4ab8d9305a72be8e5df97a60e7db81b5d23f7650f2638b630721c2b3211d16aae1011320e8261a203b9015fa4
|
data/exe/i18n-linter-rb
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
require "optparse"
|
|
2
|
+
require "i18n_linter_rb/linter"
|
|
3
|
+
|
|
4
|
+
module I18nLinterRb
|
|
5
|
+
class Cli
|
|
6
|
+
DEFAULT_LOCALES_PATH = "config/locales".freeze
|
|
7
|
+
DEFAULT_SOURCE_LOCALE = "en".freeze
|
|
8
|
+
DEFAULT_TARGET_LOCALES = %w[es].freeze
|
|
9
|
+
|
|
10
|
+
USAGE_GUIDE = <<~GUIDE
|
|
11
|
+
|
|
12
|
+
No locales directory found.
|
|
13
|
+
|
|
14
|
+
i18n-linter-rb looks for a Rails locales directory by default:
|
|
15
|
+
config/locales/
|
|
16
|
+
|
|
17
|
+
If your translations live somewhere else, pass the path explicitly:
|
|
18
|
+
|
|
19
|
+
i18n-linter-rb --path path/to/locales
|
|
20
|
+
i18n-linter-rb --path path/to/locales --from en --to es fr pt
|
|
21
|
+
|
|
22
|
+
You can also create an .i18n_linter.yml file in your project root:
|
|
23
|
+
|
|
24
|
+
locales_path: path/to/locales
|
|
25
|
+
source_locale: en
|
|
26
|
+
target_locales: [es, fr]
|
|
27
|
+
|
|
28
|
+
GUIDE
|
|
29
|
+
|
|
30
|
+
def initialize(argv)
|
|
31
|
+
@argv = argv
|
|
32
|
+
@options = {}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def run
|
|
36
|
+
parse_options
|
|
37
|
+
resolve_locales_path
|
|
38
|
+
|
|
39
|
+
source_path = File.join(@locales_path, "#{@options[:from]}.yml")
|
|
40
|
+
missing = {}
|
|
41
|
+
|
|
42
|
+
@options[:to].each do |target_locale|
|
|
43
|
+
target_path = File.join(@locales_path, "#{target_locale}.yml")
|
|
44
|
+
linter = Linter.new(source_locale: @options[:from], target_locale: target_locale)
|
|
45
|
+
keys = linter.missing_keys_in_target(source_path, target_path)
|
|
46
|
+
missing[target_locale] = keys unless keys.empty?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
report(missing)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def parse_options
|
|
55
|
+
parser = OptionParser.new do |opts|
|
|
56
|
+
opts.banner = "Usage: i18n-linter-rb [options]"
|
|
57
|
+
|
|
58
|
+
opts.on("-p", "--path PATH", "Locales directory (default: #{DEFAULT_LOCALES_PATH})") do |path|
|
|
59
|
+
@options[:path] = path
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
opts.on("-f", "--from LOCALE", "Source locale (default: #{DEFAULT_SOURCE_LOCALE})") do |locale|
|
|
63
|
+
@options[:from] = locale
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
opts.on("-t", "--to LOCALES x,y,z", Array, "Target locales (default: #{DEFAULT_TARGET_LOCALES.join(',')})") do |locales|
|
|
67
|
+
@options[:to] = locales
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
opts.on("-v", "--version", "Show version") do
|
|
71
|
+
puts I18nLinterRb::VERSION
|
|
72
|
+
exit
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
opts.on("-h", "--help", "Show this help") do
|
|
76
|
+
puts opts
|
|
77
|
+
exit
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
parser.parse!(@argv)
|
|
82
|
+
@options[:from] ||= load_config["source_locale"] || DEFAULT_SOURCE_LOCALE
|
|
83
|
+
@options[:to] ||= load_config["target_locales"] || DEFAULT_TARGET_LOCALES
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def resolve_locales_path
|
|
87
|
+
@locales_path = @options[:path] || load_config["locales_path"] || DEFAULT_LOCALES_PATH
|
|
88
|
+
|
|
89
|
+
unless File.directory?(@locales_path)
|
|
90
|
+
abort(USAGE_GUIDE)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def load_config
|
|
95
|
+
@load_config ||= begin
|
|
96
|
+
config_path = ".i18n_linter.yml"
|
|
97
|
+
File.exist?(config_path) ? YAML.load_file(config_path) : {}
|
|
98
|
+
rescue Psych::SyntaxError => e
|
|
99
|
+
warn("Invalid .i18n_linter.yml: #{e.message}")
|
|
100
|
+
{}
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def report(missing)
|
|
105
|
+
if missing.empty?
|
|
106
|
+
puts "All translations are complete."
|
|
107
|
+
else
|
|
108
|
+
missing.each do |locale, keys|
|
|
109
|
+
puts "Missing keys in #{locale}.yml:"
|
|
110
|
+
keys.each { |key| puts " - #{key}" }
|
|
111
|
+
end
|
|
112
|
+
exit 1
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require "yaml"
|
|
2
|
+
|
|
3
|
+
module I18nLinterRb
|
|
4
|
+
class Linter
|
|
5
|
+
attr_reader :source_locale, :target_locale
|
|
6
|
+
|
|
7
|
+
def initialize(source_locale:, target_locale:)
|
|
8
|
+
@source_locale = source_locale
|
|
9
|
+
@target_locale = target_locale
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def missing_keys_in_target(source_path, target_path)
|
|
13
|
+
source_keys = locale_keys(source_path)
|
|
14
|
+
target_keys = locale_keys(target_path)
|
|
15
|
+
|
|
16
|
+
source_keys - target_keys
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def locale_keys(path)
|
|
22
|
+
data = YAML.load_file(path)
|
|
23
|
+
flatten_hash(root_data(data)).keys
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def root_data(data)
|
|
27
|
+
data.values.first || {}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def flatten_hash(hash, prefix = "")
|
|
31
|
+
result = {}
|
|
32
|
+
|
|
33
|
+
hash.each do |key, value|
|
|
34
|
+
if value.is_a?(Hash)
|
|
35
|
+
result.merge!(flatten_hash(value, "#{prefix}#{key}."))
|
|
36
|
+
else
|
|
37
|
+
result["#{prefix}#{key}"] = value
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
result
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: i18n-linter-rb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- MarceloM47
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-08-23 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rspec
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.13'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '3.13'
|
|
27
|
+
description: Detects missing translation keys across locale files. Works out of the
|
|
28
|
+
box with Rails config/locales and supports custom paths.
|
|
29
|
+
email:
|
|
30
|
+
executables:
|
|
31
|
+
- i18n-linter-rb
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- exe/i18n-linter-rb
|
|
36
|
+
- lib/i18n_linter_rb.rb
|
|
37
|
+
- lib/i18n_linter_rb/cli.rb
|
|
38
|
+
- lib/i18n_linter_rb/linter.rb
|
|
39
|
+
- lib/i18n_linter_rb/version.rb
|
|
40
|
+
homepage: https://github.com/marcelom47/i18n-linter-rb
|
|
41
|
+
licenses:
|
|
42
|
+
- MIT
|
|
43
|
+
metadata:
|
|
44
|
+
homepage_uri: https://github.com/marcelom47/i18n-linter-rb
|
|
45
|
+
source_code_uri: https://github.com/marcelom47/i18n-linter-rb
|
|
46
|
+
post_install_message:
|
|
47
|
+
rdoc_options: []
|
|
48
|
+
require_paths:
|
|
49
|
+
- lib
|
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.0'
|
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '0'
|
|
60
|
+
requirements: []
|
|
61
|
+
rubygems_version: 3.2.15
|
|
62
|
+
signing_key:
|
|
63
|
+
specification_version: 4
|
|
64
|
+
summary: Linter for YAML i18n locale files, built for Ruby and Rails projects
|
|
65
|
+
test_files: []
|