rails_translation_manager 0.0.1 → 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.
- checksums.yaml +5 -5
- data/.gitignore +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +23 -0
- data/Jenkinsfile +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +57 -1
- data/Rakefile +14 -9
- data/config/locales/plurals.rb +49 -0
- data/lib/rails_translation_manager/cleaner.rb +14 -0
- data/lib/rails_translation_manager/importer.rb +35 -19
- data/lib/rails_translation_manager/locale_checker/all_locales.rb +61 -0
- data/lib/rails_translation_manager/locale_checker/base_checker.rb +13 -0
- data/lib/rails_translation_manager/locale_checker/incompatible_plurals.rb +79 -0
- data/lib/rails_translation_manager/locale_checker/locale_checker_helper.rb +23 -0
- data/lib/rails_translation_manager/locale_checker/missing_english_locales.rb +31 -0
- data/lib/rails_translation_manager/locale_checker/missing_foreign_locales.rb +31 -0
- data/lib/rails_translation_manager/locale_checker/plural_forms.rb +16 -0
- data/lib/rails_translation_manager/locale_checker.rb +50 -0
- data/lib/rails_translation_manager/version.rb +1 -1
- data/lib/rails_translation_manager/yaml_writer.rb +17 -0
- data/lib/rails_translation_manager.rb +21 -2
- data/lib/tasks/translation.rake +37 -28
- data/lib/tasks/translation_helper.rb +11 -0
- data/rails_translation_manager.gemspec +4 -1
- data/spec/locales/cleaner/clean.yml +5 -0
- data/spec/locales/cleaner/with_whitespace.yml +5 -0
- data/spec/locales/importer/fr.csv +8 -0
- data/spec/locales/in_sync/cy/browse.yml +12 -0
- data/spec/locales/in_sync/en/browse.yml +8 -0
- data/spec/locales/out_of_sync/cy.yml +3 -0
- data/spec/locales/out_of_sync/en.yml +6 -0
- data/spec/rails_translation_manager/cleaner_spec.rb +13 -0
- data/spec/rails_translation_manager/importer_spec.rb +81 -0
- data/spec/rails_translation_manager/locale_checker/all_locales_spec.rb +24 -0
- data/spec/rails_translation_manager/locale_checker/incompatible_plurals_spec.rb +94 -0
- data/spec/rails_translation_manager/locale_checker/locale_checker_helper_spec.rb +61 -0
- data/spec/rails_translation_manager/locale_checker/missing_english_locales_spec.rb +72 -0
- data/spec/rails_translation_manager/locale_checker/missing_foreign_locales_spec.rb +80 -0
- data/spec/rails_translation_manager/locale_checker/plural_forms_spec.rb +27 -0
- data/spec/rails_translation_manager/locale_checker_spec.rb +68 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/support/tasks.rb +7 -0
- data/spec/tasks/translation_spec.rb +123 -0
- data/test/rails_translation_manager/yaml_writer_test.rb +60 -0
- data/tmp/.gitkeep +0 -0
- metadata +104 -13
- data/lib/rails_translation_manager/validator.rb +0 -92
- data/test/rails_translation_manager/importer_test.rb +0 -166
- data/test/rails_translation_manager/validator_test.rb +0 -51
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RailsTranslationManager::LocaleChecker do
|
6
|
+
context "when the locales are valid" do
|
7
|
+
it "calls each checker class" do
|
8
|
+
described_class::CHECKER_CLASSES.each do |checker|
|
9
|
+
expect_any_instance_of(checker).to receive(:report)
|
10
|
+
end
|
11
|
+
|
12
|
+
described_class.new("spec/locales/in_sync/**/*.yml").validate_locales
|
13
|
+
end
|
14
|
+
|
15
|
+
it "outputs a confirmation" do
|
16
|
+
expect { described_class.new("spec/locales/in_sync/**/*.yml").validate_locales }
|
17
|
+
.to output("Locale files are in sync, nice job!\n").to_stdout
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns true" do
|
21
|
+
expect(described_class.new("spec/locales/in_sync/**/*.yml").validate_locales)
|
22
|
+
.to eq(true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when the locales are not valid" do
|
27
|
+
it "calls each checker class" do
|
28
|
+
described_class::CHECKER_CLASSES.each do |checker|
|
29
|
+
expect_any_instance_of(checker).to receive(:report)
|
30
|
+
end
|
31
|
+
|
32
|
+
described_class.new("spec/locales/out_of_sync/*.yml").validate_locales
|
33
|
+
end
|
34
|
+
|
35
|
+
it "outputs the report" do
|
36
|
+
printed = capture_stdout do
|
37
|
+
described_class.new("spec/locales/out_of_sync/*.yml").validate_locales
|
38
|
+
end
|
39
|
+
|
40
|
+
expect(printed.scan(/\[ERROR\]/).count).to eq(3)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns false" do
|
44
|
+
expect(described_class.new("spec/locales/out_of_sync/*.yml").validate_locales)
|
45
|
+
.to eq(false)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when the locale path doesn't relate to any YAML files" do
|
50
|
+
it "doesn't call any checker classes" do
|
51
|
+
described_class::CHECKER_CLASSES.each do |checker|
|
52
|
+
expect_any_instance_of(checker).to_not receive(:report)
|
53
|
+
end
|
54
|
+
|
55
|
+
described_class.new("some/random/path").validate_locales
|
56
|
+
end
|
57
|
+
|
58
|
+
it "outputs an error message" do
|
59
|
+
expect { described_class.new("some/random/path").validate_locales }
|
60
|
+
.to output("No locale files found for the supplied path\n").to_stdout
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns false" do
|
64
|
+
expect(described_class.new("some/random/path").validate_locales)
|
65
|
+
.to eq(false)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails_translation_manager"
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.before do
|
7
|
+
I18n.available_locales = %i[en cy]
|
8
|
+
config.before { allow($stdout).to receive(:puts) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def capture_stdout(&blk)
|
12
|
+
old = $stdout
|
13
|
+
$stdout = fake = StringIO.new
|
14
|
+
blk.call
|
15
|
+
fake.string
|
16
|
+
ensure
|
17
|
+
$stdout = old
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../spec/support/tasks"
|
3
|
+
|
4
|
+
describe "rake tasks" do
|
5
|
+
before do
|
6
|
+
fake_rails = double()
|
7
|
+
fake_rails.stub(:root) { Pathname.new("spec") }
|
8
|
+
stub_const("Rails", fake_rails)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "translation:import", type: :task do
|
12
|
+
let(:task) { Rake::Task["translation:import"] }
|
13
|
+
let(:csv_path) { "path/to/import/fr.csv" }
|
14
|
+
let!(:importer_instance) { stub_importer }
|
15
|
+
|
16
|
+
it "outputs to stdout" do
|
17
|
+
expect { task.execute(csv_path: csv_path) }
|
18
|
+
.to output("Imported CSV from: #{csv_path} to #{Rails.root.join("config", "locales")}\n")
|
19
|
+
.to_stdout
|
20
|
+
end
|
21
|
+
|
22
|
+
it "calls the Importer class with the csv and import paths" do
|
23
|
+
task.execute(csv_path: csv_path)
|
24
|
+
|
25
|
+
expect(RailsTranslationManager::Importer)
|
26
|
+
.to have_received(:new)
|
27
|
+
.with(locale: "fr",
|
28
|
+
csv_path: csv_path,
|
29
|
+
import_directory: Rails.root.join("config", "locales"),
|
30
|
+
multiple_files_per_language: false)
|
31
|
+
expect(importer_instance).to have_received(:import)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "translation:import:all", type: :task do
|
36
|
+
let(:task) { Rake::Task["translation:import:all"] }
|
37
|
+
let(:csv_directory) { "locales/importer" }
|
38
|
+
let!(:importer_instance) { stub_importer }
|
39
|
+
|
40
|
+
it "outputs to stdout" do
|
41
|
+
expect { task.execute(csv_directory: csv_directory) }
|
42
|
+
.to output("Imported all CSVs from: #{csv_directory} to #{Rails.root.join("config", "locales")}\n")
|
43
|
+
.to_stdout
|
44
|
+
end
|
45
|
+
|
46
|
+
it "calls the importer class for each target path" do
|
47
|
+
task.execute(csv_directory: csv_directory, multiple_files_per_language: true)
|
48
|
+
|
49
|
+
expect(RailsTranslationManager::Importer)
|
50
|
+
.to have_received(:new)
|
51
|
+
.with(locale: "fr",
|
52
|
+
csv_path: "spec/locales/importer/fr.csv",
|
53
|
+
import_directory: Rails.root.join("config", "locales"),
|
54
|
+
multiple_files_per_language: true)
|
55
|
+
expect(importer_instance).to have_received(:import)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "translation:add_missing", type: :task do
|
60
|
+
let(:task) { Rake::Task["translation:add_missing"] }
|
61
|
+
let!(:cleaner_instance) { stub_cleaner }
|
62
|
+
|
63
|
+
before do
|
64
|
+
allow(I18n::Tasks::CLI).to receive(:start)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "triggers Cleaner and allows to receive the right arguments" do
|
68
|
+
task.execute
|
69
|
+
expect(RailsTranslationManager::Cleaner)
|
70
|
+
.to have_received(:new)
|
71
|
+
.with(Rails.root.join("config", "locales"))
|
72
|
+
expect(cleaner_instance).to have_received(:clean)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "triggers i18n task and allows to receive the right arguments" do
|
76
|
+
task.execute(locale: "fr")
|
77
|
+
expect(I18n::Tasks::CLI).to have_received(:start).with(
|
78
|
+
["add-missing", "--nil-value", ["-l", "fr"]]
|
79
|
+
)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "translation:normalize", type: :task do
|
84
|
+
let(:task) { Rake::Task["translation:normalize"] }
|
85
|
+
let!(:cleaner_instance) { stub_cleaner }
|
86
|
+
|
87
|
+
before do
|
88
|
+
allow(I18n::Tasks::CLI).to receive(:start)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "triggers Cleaner and allows to receive the right arguments" do
|
92
|
+
task.execute(locale_directory: "config/locales")
|
93
|
+
expect(RailsTranslationManager::Cleaner)
|
94
|
+
.to have_received(:new)
|
95
|
+
.with(Rails.root.join("config", "locales"))
|
96
|
+
expect(cleaner_instance).to have_received(:clean)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "triggers i18n task and allows to receive the right arguments" do
|
100
|
+
task.execute
|
101
|
+
expect(I18n::Tasks::CLI).to have_received(:start).with(["normalize"])
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def stub_importer
|
106
|
+
importer_instance = instance_double(RailsTranslationManager::Importer)
|
107
|
+
allow(RailsTranslationManager::Importer).to receive(:new)
|
108
|
+
.and_return(importer_instance)
|
109
|
+
allow(importer_instance).to receive(:import)
|
110
|
+
|
111
|
+
importer_instance
|
112
|
+
end
|
113
|
+
|
114
|
+
def stub_cleaner
|
115
|
+
cleaner_instance = instance_double(RailsTranslationManager::Cleaner)
|
116
|
+
allow(RailsTranslationManager::Cleaner)
|
117
|
+
.to receive(:new)
|
118
|
+
.and_return(cleaner_instance)
|
119
|
+
allow(cleaner_instance).to receive(:clean)
|
120
|
+
|
121
|
+
cleaner_instance
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "rails_translation_manager/yaml_writer"
|
3
|
+
module RailsTranslationManager
|
4
|
+
class DummyWriter
|
5
|
+
include YAMLWriter
|
6
|
+
end
|
7
|
+
|
8
|
+
class WriterTest < Minitest::Test
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@output_file = Tempfile.new('fr')
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
@output_file.close
|
16
|
+
@output_file.unlink
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'outputs YAML without the header --- line for consistency with convention' do
|
20
|
+
data = {"fr" => {
|
21
|
+
key1: [:source, :translation],
|
22
|
+
"key2" => ["value", "le value"],
|
23
|
+
}}
|
24
|
+
|
25
|
+
DummyWriter.new.write_yaml(output_file, data)
|
26
|
+
|
27
|
+
assert_equal "fr:", File.readlines(output_file).first.strip
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'outputs a newline at the end of the YAML for consistency with code editors' do
|
31
|
+
data = {"fr" => {
|
32
|
+
key1: [:source, :translation],
|
33
|
+
"key2" => ["value", "le value"],
|
34
|
+
}}
|
35
|
+
|
36
|
+
DummyWriter.new.write_yaml(output_file, data)
|
37
|
+
|
38
|
+
assert_match /\n$/, File.readlines(output_file).last
|
39
|
+
end
|
40
|
+
|
41
|
+
test 'strips whitespace from the end of lines for consistency with code editors' do
|
42
|
+
data = {fr: {
|
43
|
+
key1: [:source, :translation],
|
44
|
+
"key2" => ["value", nil],
|
45
|
+
}}
|
46
|
+
|
47
|
+
DummyWriter.new.write_yaml(output_file, data)
|
48
|
+
|
49
|
+
lines = File.readlines(output_file)
|
50
|
+
refute lines.any? { |line| line =~ /\s\n$/ }
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def output_file
|
56
|
+
@output_file.path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
data/tmp/.gitkeep
ADDED
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_translation_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edd Sowden
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails-i18n
|
@@ -38,20 +38,34 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: i18n-tasks
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- - "
|
59
|
+
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- - "
|
66
|
+
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,34 @@ dependencies:
|
|
80
94
|
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: byebug
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
83
125
|
description: ''
|
84
126
|
email:
|
85
127
|
- edd.sowden@digital.cabinet-office.gov.uk
|
@@ -90,23 +132,55 @@ files:
|
|
90
132
|
- ".gitignore"
|
91
133
|
- ".ruby-version"
|
92
134
|
- ".travis.yml"
|
135
|
+
- CHANGELOG.md
|
93
136
|
- CONTRIBUTING.md
|
94
137
|
- Gemfile
|
138
|
+
- Jenkinsfile
|
95
139
|
- LICENSE.txt
|
96
140
|
- README.md
|
97
141
|
- Rakefile
|
142
|
+
- config/locales/plurals.rb
|
98
143
|
- lib/rails_translation_manager.rb
|
144
|
+
- lib/rails_translation_manager/cleaner.rb
|
99
145
|
- lib/rails_translation_manager/exporter.rb
|
100
146
|
- lib/rails_translation_manager/importer.rb
|
147
|
+
- lib/rails_translation_manager/locale_checker.rb
|
148
|
+
- lib/rails_translation_manager/locale_checker/all_locales.rb
|
149
|
+
- lib/rails_translation_manager/locale_checker/base_checker.rb
|
150
|
+
- lib/rails_translation_manager/locale_checker/incompatible_plurals.rb
|
151
|
+
- lib/rails_translation_manager/locale_checker/locale_checker_helper.rb
|
152
|
+
- lib/rails_translation_manager/locale_checker/missing_english_locales.rb
|
153
|
+
- lib/rails_translation_manager/locale_checker/missing_foreign_locales.rb
|
154
|
+
- lib/rails_translation_manager/locale_checker/plural_forms.rb
|
101
155
|
- lib/rails_translation_manager/railtie.rb
|
102
|
-
- lib/rails_translation_manager/validator.rb
|
103
156
|
- lib/rails_translation_manager/version.rb
|
157
|
+
- lib/rails_translation_manager/yaml_writer.rb
|
104
158
|
- lib/tasks/translation.rake
|
159
|
+
- lib/tasks/translation_helper.rb
|
105
160
|
- rails_translation_manager.gemspec
|
161
|
+
- spec/locales/cleaner/clean.yml
|
162
|
+
- spec/locales/cleaner/with_whitespace.yml
|
163
|
+
- spec/locales/importer/fr.csv
|
164
|
+
- spec/locales/in_sync/cy/browse.yml
|
165
|
+
- spec/locales/in_sync/en/browse.yml
|
166
|
+
- spec/locales/out_of_sync/cy.yml
|
167
|
+
- spec/locales/out_of_sync/en.yml
|
168
|
+
- spec/rails_translation_manager/cleaner_spec.rb
|
169
|
+
- spec/rails_translation_manager/importer_spec.rb
|
170
|
+
- spec/rails_translation_manager/locale_checker/all_locales_spec.rb
|
171
|
+
- spec/rails_translation_manager/locale_checker/incompatible_plurals_spec.rb
|
172
|
+
- spec/rails_translation_manager/locale_checker/locale_checker_helper_spec.rb
|
173
|
+
- spec/rails_translation_manager/locale_checker/missing_english_locales_spec.rb
|
174
|
+
- spec/rails_translation_manager/locale_checker/missing_foreign_locales_spec.rb
|
175
|
+
- spec/rails_translation_manager/locale_checker/plural_forms_spec.rb
|
176
|
+
- spec/rails_translation_manager/locale_checker_spec.rb
|
177
|
+
- spec/spec_helper.rb
|
178
|
+
- spec/support/tasks.rb
|
179
|
+
- spec/tasks/translation_spec.rb
|
106
180
|
- test/rails_translation_manager/exporter_test.rb
|
107
|
-
- test/rails_translation_manager/
|
108
|
-
- test/rails_translation_manager/validator_test.rb
|
181
|
+
- test/rails_translation_manager/yaml_writer_test.rb
|
109
182
|
- test/test_helper.rb
|
183
|
+
- tmp/.gitkeep
|
110
184
|
homepage: ''
|
111
185
|
licenses:
|
112
186
|
- MIT
|
@@ -126,13 +200,30 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
200
|
- !ruby/object:Gem::Version
|
127
201
|
version: '0'
|
128
202
|
requirements: []
|
129
|
-
|
130
|
-
rubygems_version: 2.2.2
|
203
|
+
rubygems_version: 3.0.3
|
131
204
|
signing_key:
|
132
205
|
specification_version: 4
|
133
206
|
summary: Tasks to manage translation files
|
134
207
|
test_files:
|
208
|
+
- spec/locales/cleaner/clean.yml
|
209
|
+
- spec/locales/cleaner/with_whitespace.yml
|
210
|
+
- spec/locales/importer/fr.csv
|
211
|
+
- spec/locales/in_sync/cy/browse.yml
|
212
|
+
- spec/locales/in_sync/en/browse.yml
|
213
|
+
- spec/locales/out_of_sync/cy.yml
|
214
|
+
- spec/locales/out_of_sync/en.yml
|
215
|
+
- spec/rails_translation_manager/cleaner_spec.rb
|
216
|
+
- spec/rails_translation_manager/importer_spec.rb
|
217
|
+
- spec/rails_translation_manager/locale_checker/all_locales_spec.rb
|
218
|
+
- spec/rails_translation_manager/locale_checker/incompatible_plurals_spec.rb
|
219
|
+
- spec/rails_translation_manager/locale_checker/locale_checker_helper_spec.rb
|
220
|
+
- spec/rails_translation_manager/locale_checker/missing_english_locales_spec.rb
|
221
|
+
- spec/rails_translation_manager/locale_checker/missing_foreign_locales_spec.rb
|
222
|
+
- spec/rails_translation_manager/locale_checker/plural_forms_spec.rb
|
223
|
+
- spec/rails_translation_manager/locale_checker_spec.rb
|
224
|
+
- spec/spec_helper.rb
|
225
|
+
- spec/support/tasks.rb
|
226
|
+
- spec/tasks/translation_spec.rb
|
135
227
|
- test/rails_translation_manager/exporter_test.rb
|
136
|
-
- test/rails_translation_manager/
|
137
|
-
- test/rails_translation_manager/validator_test.rb
|
228
|
+
- test/rails_translation_manager/yaml_writer_test.rb
|
138
229
|
- test/test_helper.rb
|
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'logger'
|
3
|
-
|
4
|
-
class RailsTranslationManager::Validator
|
5
|
-
def initialize(translation_file_path, logger = Logger.new(nil))
|
6
|
-
@translation_file_path = translation_file_path
|
7
|
-
@logger = logger
|
8
|
-
end
|
9
|
-
|
10
|
-
def check!
|
11
|
-
@logger.info "Checking translation files in '#{@translation_file_path}' for unexpected interpolation keys"
|
12
|
-
@logger.info "Loading reference file (#{reference_file_name})"
|
13
|
-
@logger.info "Checking..."
|
14
|
-
reference = load_translation_file("#{@translation_file_path}/#{reference_file_name}")
|
15
|
-
Dir["#{@translation_file_path}/*.yml"].reject do |entry|
|
16
|
-
File.basename(entry) == reference_file_name
|
17
|
-
end.inject([]) do |errors, entry|
|
18
|
-
translation_file = load_translation_file(entry)
|
19
|
-
errors + unexpected_substitution_keys(reference, translation_file)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def unexpected_substitution_keys(reference, translation_file)
|
24
|
-
reference_substitutions = substitutions_in(reference)
|
25
|
-
target_substitutions = substitutions_in(translation_file)
|
26
|
-
|
27
|
-
targets_by_path = target_substitutions.each_with_object({}) do |target, hash|
|
28
|
-
hash[exclude_locale_from_path(target.path)] = target
|
29
|
-
end
|
30
|
-
|
31
|
-
reference_substitutions.each_with_object([]) do |reference, unexpected_substitutions|
|
32
|
-
target = targets_by_path[exclude_locale_from_path(reference.path)]
|
33
|
-
next if target.nil? || reference.has_all_substitutions?(target)
|
34
|
-
unexpected_substitutions << UnexpectedSubstition.new(target, reference)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def substitutions_in(translation_file)
|
39
|
-
flatten(translation_file).reject do |translation|
|
40
|
-
translation.substitutions.empty?
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class TranslationEntry < Struct.new(:path, :value)
|
45
|
-
def substitutions
|
46
|
-
@substitutions ||= self.value.scan(/%{([^}]*)}/)
|
47
|
-
end
|
48
|
-
|
49
|
-
def has_all_substitutions?(other)
|
50
|
-
(other.substitutions - self.substitutions).empty?
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
class UnexpectedSubstition < Struct.new(:target, :reference)
|
55
|
-
def to_s
|
56
|
-
missing = (self.reference.substitutions - self.target.substitutions)
|
57
|
-
extras = (self.target.substitutions - self.reference.substitutions)
|
58
|
-
message = %Q{Key "#{target.path.join('.')}":}
|
59
|
-
if extras.any?
|
60
|
-
message << %Q{ Extra substitutions: ["#{extras.join('", "')}"].}
|
61
|
-
end
|
62
|
-
if missing.any?
|
63
|
-
message << %Q{ Missing substitutions: ["#{missing.join('", "')}"].}
|
64
|
-
end
|
65
|
-
message
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def flatten(translation_file, path = [])
|
70
|
-
translation_file.map do |key, value|
|
71
|
-
case value
|
72
|
-
when Hash
|
73
|
-
flatten(value, path + [key])
|
74
|
-
else
|
75
|
-
TranslationEntry.new(path + [key], value || "")
|
76
|
-
end
|
77
|
-
end.flatten
|
78
|
-
end
|
79
|
-
|
80
|
-
def load_translation_file(filename)
|
81
|
-
YAML.load_file(filename)
|
82
|
-
end
|
83
|
-
|
84
|
-
def reference_file_name
|
85
|
-
"en.yml"
|
86
|
-
end
|
87
|
-
|
88
|
-
private
|
89
|
-
def exclude_locale_from_path(path)
|
90
|
-
path[1..-1]
|
91
|
-
end
|
92
|
-
end
|