rails_translation_manager 0.1.0 → 1.1.2
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 +4 -4
- data/.gitignore +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +20 -0
- data/Jenkinsfile +3 -1
- data/Rakefile +13 -7
- data/config/locales/plurals.rb +49 -0
- data/lib/rails_translation_manager/cleaner.rb +14 -0
- data/lib/rails_translation_manager/i18n_tasks_option_parser.rb +10 -0
- data/lib/rails_translation_manager/importer.rb +32 -14
- 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.rb +21 -3
- data/lib/tasks/translation.rake +43 -42
- data/rails_translation_manager.gemspec +6 -2
- 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/importer/hy_with_byte_order_mark.csv +4 -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 +93 -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 +127 -0
- data/test/rails_translation_manager/yaml_writer_test.rb +2 -0
- data/tmp/.gitkeep +0 -0
- metadata +117 -18
- data/lib/rails_translation_manager/stealer.rb +0 -85
- data/lib/rails_translation_manager/validator.rb +0 -92
- data/test/rails_translation_manager/importer_test.rb +0 -132
- data/test/rails_translation_manager/stealer_test.rb +0 -251
- data/test/rails_translation_manager/validator_test.rb +0 -51
data/lib/tasks/translation.rake
CHANGED
@@ -1,15 +1,9 @@
|
|
1
|
-
require "
|
1
|
+
require "i18n/tasks/cli"
|
2
|
+
require_relative "../rails_translation_manager"
|
3
|
+
require_relative "../rails_translation_manager/i18n_tasks_option_parser"
|
2
4
|
|
3
5
|
namespace :translation do
|
4
6
|
|
5
|
-
desc "Regenerate all locales from the EN locale - run this after adding keys"
|
6
|
-
task(:regenerate, [:directory] => [:environment]) do |t, args|
|
7
|
-
directory = args[:directory] || "tmp/locale_csv"
|
8
|
-
|
9
|
-
Rake::Task["translation:export:all"].invoke(directory)
|
10
|
-
Rake::Task["translation:import:all"].invoke(directory)
|
11
|
-
end
|
12
|
-
|
13
7
|
desc "Export a specific locale to CSV."
|
14
8
|
task :export, [:directory, :base_locale, :target_locale] => [:environment] do |t, args|
|
15
9
|
FileUtils.mkdir_p(args[:directory]) unless File.exist?(args[:directory])
|
@@ -36,51 +30,58 @@ namespace :translation do
|
|
36
30
|
end
|
37
31
|
|
38
32
|
desc "Import a specific locale CSV to YAML within the app."
|
39
|
-
task :import, [:
|
40
|
-
|
33
|
+
task :import, [:csv_path, :multiple_files_per_language] => [:environment] do |t, args|
|
34
|
+
import_dir = Rails.root.join("config", "locales")
|
35
|
+
csv_path = args[:csv_path]
|
36
|
+
|
37
|
+
importer = RailsTranslationManager::Importer.new(
|
38
|
+
locale: File.basename(args[:csv_path], ".csv"),
|
39
|
+
csv_path: csv_path,
|
40
|
+
import_directory: Rails.root.join("config", "locales"),
|
41
|
+
multiple_files_per_language: args[:multiple_files_per_language] || false
|
42
|
+
)
|
41
43
|
importer.import
|
44
|
+
|
45
|
+
puts "Imported CSV from: #{csv_path} to #{import_dir}"
|
42
46
|
end
|
43
47
|
|
44
48
|
namespace :import do
|
45
49
|
desc "Import all locale CSV files to YAML within the app."
|
46
|
-
task :all, [:
|
47
|
-
directory = args[:
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
task :all, [:csv_directory, :multiple_files_per_language] => [:environment] do |t, args|
|
51
|
+
directory = args[:csv_directory] || "tmp/locale_csv"
|
52
|
+
import_dir = Rails.root.join("config", "locales")
|
53
|
+
|
54
|
+
Dir[Rails.root.join(directory, "*.csv")].each do |csv_path|
|
55
|
+
importer = RailsTranslationManager::Importer.new(
|
56
|
+
locale: File.basename(csv_path, ".csv"),
|
57
|
+
csv_path: csv_path,
|
58
|
+
import_directory: import_dir,
|
59
|
+
multiple_files_per_language: args[:multiple_files_per_language] || false
|
60
|
+
)
|
51
61
|
importer.import
|
52
62
|
end
|
53
|
-
end
|
54
|
-
end
|
55
63
|
|
56
|
-
|
57
|
-
task :validate do
|
58
|
-
require 'rails_translation_manager/validator'
|
59
|
-
logger = Logger.new(STDOUT)
|
60
|
-
validator = RailsTranslationManager::Validator.new(Rails.root.join('config', 'locales'), logger)
|
61
|
-
errors = validator.check!
|
62
|
-
if errors.any?
|
63
|
-
puts "Found #{errors.size} errors:"
|
64
|
-
puts errors.map(&:to_s).join("\n")
|
65
|
-
else
|
66
|
-
puts "Success! No unexpected interpolation keys found."
|
64
|
+
puts "Imported all CSVs from: #{directory} to #{import_dir}"
|
67
65
|
end
|
68
66
|
end
|
69
67
|
|
70
|
-
desc "
|
71
|
-
task
|
72
|
-
|
73
|
-
|
74
|
-
|
68
|
+
desc "Add missing translations"
|
69
|
+
task(:add_missing, [:locale] => [:environment]) do |t, args|
|
70
|
+
option_parser = RailsTranslationManager::I18nTasksOptionParser.new(
|
71
|
+
["add-missing", "--nil-value"], args[:locale]
|
72
|
+
).with_optional_locale
|
75
73
|
|
76
|
-
|
77
|
-
|
78
|
-
task :all, [:source_app_path, :mapping_file_path] => [:environment] do |t, args|
|
79
|
-
I18n.available_locales.reject { |l| l == :en }.each do |locale|
|
80
|
-
stealer = RailsTranslationManager::Stealer.new(locale.to_s, args[:source_app_path], args[:mapping_file_path], Rails.root.join('config', 'locales'))
|
81
|
-
stealer.steal_locale
|
82
|
-
end
|
83
|
-
end
|
74
|
+
I18n::Tasks::CLI.start(option_parser)
|
75
|
+
RailsTranslationManager::Cleaner.new(Rails.root.join("config", "locales")).clean
|
84
76
|
end
|
85
77
|
|
78
|
+
desc "Normalize translations"
|
79
|
+
task(:normalize, [:locale] => [:environment]) do |t, args|
|
80
|
+
option_parser = RailsTranslationManager::I18nTasksOptionParser.new(
|
81
|
+
["normalize"], args[:locale]
|
82
|
+
).with_optional_locale
|
83
|
+
|
84
|
+
I18n::Tasks::CLI.start(option_parser)
|
85
|
+
RailsTranslationManager::Cleaner.new(Rails.root.join("config", "locales")).clean
|
86
|
+
end
|
86
87
|
end
|
@@ -18,10 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "rails-i18n"
|
22
21
|
spec.add_dependency "activesupport"
|
22
|
+
spec.add_dependency "csv", "~> 3.2"
|
23
|
+
spec.add_dependency "i18n-tasks"
|
24
|
+
spec.add_dependency "rails-i18n"
|
23
25
|
|
24
|
-
spec.add_development_dependency "bundler"
|
26
|
+
spec.add_development_dependency "bundler"
|
25
27
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
28
|
spec.add_development_dependency "minitest"
|
29
|
+
spec.add_development_dependency "rspec"
|
30
|
+
spec.add_development_dependency "byebug"
|
27
31
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
key,source,translation
|
2
|
+
world_location.type.country,Country,Pays
|
3
|
+
world_location.fruit,"[Apples, Bananas, Pears]","[Pommes, Bananes, Poires]"
|
4
|
+
world_location.things,nil,nil
|
5
|
+
world_location.sentiment,:whatever,:bof
|
6
|
+
shared.price,123,123
|
7
|
+
shared.key1,is true,true
|
8
|
+
shared.key2,is false,false
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe RailsTranslationManager::Cleaner do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
FileUtils.cp('spec/locales/cleaner/with_whitespace.yml', 'tmp/')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'removes whitespace at the end of the line' do
|
10
|
+
described_class.new('tmp').clean
|
11
|
+
expect(FileUtils.compare_file('tmp/with_whitespace.yml', 'spec/locales/cleaner/clean.yml')).to be_truthy
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "tmpdir"
|
3
|
+
|
4
|
+
RSpec.describe RailsTranslationManager::Importer do
|
5
|
+
let(:import_directory) { Dir.mktmpdir }
|
6
|
+
|
7
|
+
it "imports CSV containing a byte order mark" do
|
8
|
+
importer = described_class.new(
|
9
|
+
locale: "hy",
|
10
|
+
csv_path: "spec/locales/importer/hy_with_byte_order_mark.csv",
|
11
|
+
import_directory: import_directory,
|
12
|
+
multiple_files_per_language: false
|
13
|
+
)
|
14
|
+
importer.import
|
15
|
+
|
16
|
+
expect(File).to exist(import_directory + "/hy.yml")
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when there is one locale file per language" do
|
20
|
+
let(:yaml_translation_data) { YAML.load_file(import_directory + "/fr.yml")["fr"] }
|
21
|
+
|
22
|
+
before do
|
23
|
+
importer = described_class.new(
|
24
|
+
locale: "fr",
|
25
|
+
csv_path: "spec/locales/importer/fr.csv",
|
26
|
+
import_directory: import_directory,
|
27
|
+
multiple_files_per_language: false
|
28
|
+
)
|
29
|
+
importer.import
|
30
|
+
end
|
31
|
+
|
32
|
+
it "creates one YAML file per language" do
|
33
|
+
expect(File).to exist(import_directory + "/fr.yml")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "imports nested locales" do
|
37
|
+
expected = { "type" => { "country" => "Pays" } }
|
38
|
+
expect(yaml_translation_data).to include("world_location" => hash_including(expected))
|
39
|
+
end
|
40
|
+
|
41
|
+
it "imports arrays from CSV as arrays" do
|
42
|
+
expected = { "fruit" => ["Pommes", "Bananes", "Poires"] }
|
43
|
+
expect(yaml_translation_data).to include("world_location" => hash_including(expected))
|
44
|
+
end
|
45
|
+
|
46
|
+
it "imports string 'nil' as nil" do
|
47
|
+
expected = { "things" => nil }
|
48
|
+
expect(yaml_translation_data).to include("world_location" => hash_including(expected))
|
49
|
+
end
|
50
|
+
|
51
|
+
it "imports string ':thing' as symbol" do
|
52
|
+
expected = { "sentiment" => :bof }
|
53
|
+
expect(yaml_translation_data).to include("world_location" => hash_including(expected))
|
54
|
+
end
|
55
|
+
|
56
|
+
it "imports integer strings as integers" do
|
57
|
+
expected = { "price" => 123 }
|
58
|
+
expect(yaml_translation_data).to include("shared" => hash_including(expected))
|
59
|
+
end
|
60
|
+
|
61
|
+
it "imports boolean values as booleans, not strings" do
|
62
|
+
expected = { "key1" => true, "key2" => false }
|
63
|
+
expect(yaml_translation_data).to include("shared" => hash_including(expected))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when there are multiple files per locale" do
|
68
|
+
before do
|
69
|
+
importer = described_class.new(
|
70
|
+
locale: "fr",
|
71
|
+
csv_path: "spec/locales/importer/fr.csv",
|
72
|
+
import_directory: import_directory,
|
73
|
+
multiple_files_per_language: true
|
74
|
+
)
|
75
|
+
importer.import
|
76
|
+
end
|
77
|
+
|
78
|
+
it "creates multiple YAML files per language in the language's directory" do
|
79
|
+
expect(File).to exist(import_directory + "/fr/world_location.yml")
|
80
|
+
.and exist(import_directory + "/fr/shared.yml")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "imports only 'world_location' locales to the relevant file" do
|
84
|
+
yaml_translation_data = YAML.load_file(import_directory + "/fr/world_location.yml")["fr"]
|
85
|
+
expect(yaml_translation_data).to match("world_location" => anything)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "imports only 'shared' locales to the relevant file" do
|
89
|
+
yaml_translation_data = YAML.load_file(import_directory + "/fr/shared.yml")["fr"]
|
90
|
+
expect(yaml_translation_data).to match("shared" => anything)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe AllLocales do
|
6
|
+
context "when there are locale files" do
|
7
|
+
it "generates an array of hashes for all locales" do
|
8
|
+
expect(described_class.new("spec/locales/out_of_sync/*.yml").generate)
|
9
|
+
.to eq(
|
10
|
+
[
|
11
|
+
{ keys: %w[test wrong_plural wrong_plural.one wrong_plural.zero], locale: :en },
|
12
|
+
{ keys: %w[other_test], locale: :cy }
|
13
|
+
]
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when there aren't any locale files present" do
|
19
|
+
it "raises an error" do
|
20
|
+
expect { described_class.new("path/to/none/existant/locale/files").generate }
|
21
|
+
.to raise_error(AllLocales::NoLocaleFilesFound, 'No locale files found for the supplied path')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe IncompatiblePlurals do
|
6
|
+
context "when there are missing plurals" do
|
7
|
+
let(:all_locales) do
|
8
|
+
[
|
9
|
+
{
|
10
|
+
locale: :en,
|
11
|
+
keys: %w[browse.some_key.other browse.some_other_key.one]
|
12
|
+
}
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
allow(PluralForms).to receive(:all).and_return({ en: %i[one other] })
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns the missing plural forms" do
|
21
|
+
expect(described_class.new(all_locales).report)
|
22
|
+
.to eq(
|
23
|
+
<<~OUTPUT.chomp
|
24
|
+
\e[31m[ERROR]\e[0m Incompatible plural forms, for:
|
25
|
+
|
26
|
+
- 'en', with parent 'browse.some_key'. Expected: [:one, :other], actual: [:other]
|
27
|
+
|
28
|
+
- 'en', with parent 'browse.some_other_key'. Expected: [:one, :other], actual: [:one]
|
29
|
+
|
30
|
+
\e[1mIf the keys reported above are not plurals, rename them avoiding plural keywords: #{LocaleCheckerHelper::PLURAL_KEYS}\e[22m
|
31
|
+
OUTPUT
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when there aren't any missing plurals" do
|
37
|
+
let(:all_locales) do
|
38
|
+
[
|
39
|
+
{
|
40
|
+
locale: :en,
|
41
|
+
keys: %w[browse.some_key.other browse.some_key.one]
|
42
|
+
}
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
46
|
+
before do
|
47
|
+
allow(PluralForms).to receive(:all).and_return({ en: %i[one other] })
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns nil" do
|
51
|
+
expect(described_class.new(all_locales).report)
|
52
|
+
.to be_nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when plural forms aren't available for the locales" do
|
57
|
+
let(:all_locales) do
|
58
|
+
[
|
59
|
+
{
|
60
|
+
locale: :en,
|
61
|
+
keys: %w[browse.some_key.one browse.some_key.other]
|
62
|
+
},
|
63
|
+
{
|
64
|
+
locale: :cy,
|
65
|
+
keys: %w[browse.some_key.few
|
66
|
+
browse.some_key.many
|
67
|
+
browse.some_key.one
|
68
|
+
browse.some_key.other
|
69
|
+
browse.some_key.two
|
70
|
+
browse.some_key.zero]
|
71
|
+
}
|
72
|
+
]
|
73
|
+
end
|
74
|
+
|
75
|
+
before do
|
76
|
+
allow(PluralForms).to receive(:all).and_return({ cy: nil, en: nil })
|
77
|
+
end
|
78
|
+
|
79
|
+
it "outputs the missing plural forms" do
|
80
|
+
expect(described_class.new(all_locales).report)
|
81
|
+
.to eq(
|
82
|
+
<<~OUTPUT.chomp
|
83
|
+
\e[31m[ERROR]\e[0m Incompatible plural forms, for:
|
84
|
+
|
85
|
+
- \e[31m[ERROR]\e[0m Please add plural form for 'en' <link to future documentation>
|
86
|
+
|
87
|
+
- \e[31m[ERROR]\e[0m Please add plural form for 'cy' <link to future documentation>
|
88
|
+
|
89
|
+
\e[1mIf the keys reported above are not plurals, rename them avoiding plural keywords: #{LocaleCheckerHelper::PLURAL_KEYS}\e[22m
|
90
|
+
OUTPUT
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe LocaleCheckerHelper do
|
6
|
+
include LocaleCheckerHelper
|
7
|
+
|
8
|
+
describe "#exclude_plurals" do
|
9
|
+
it "excludes plural groups" do
|
10
|
+
expect(exclude_plurals(%w[key.one key.other]))
|
11
|
+
.to eq([])
|
12
|
+
end
|
13
|
+
|
14
|
+
it "doesn't exclude non-plurals" do
|
15
|
+
expect(exclude_plurals(%w[thing.bing red.blue]))
|
16
|
+
.to eq(%w[thing.bing red.blue])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#group_keys" do
|
21
|
+
it "groups locales by keys" do
|
22
|
+
keys = {
|
23
|
+
en: %w[key.first key.second],
|
24
|
+
fr: %w[key.first key.second],
|
25
|
+
es: %w[key.second]
|
26
|
+
}
|
27
|
+
|
28
|
+
expect(group_keys(keys))
|
29
|
+
.to eq(
|
30
|
+
{
|
31
|
+
%w[key.first key.second] => %i[en fr],
|
32
|
+
%w[key.second] => %i[es]
|
33
|
+
}
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#english_keys_excluding_plurals" do
|
39
|
+
it "returns english keys excluding plurals" do
|
40
|
+
keys = [
|
41
|
+
{ locale: :en, keys: %w[key.english plural.other] },
|
42
|
+
{ locale: :fr, keys: %w[key.french] }
|
43
|
+
]
|
44
|
+
|
45
|
+
expect(english_keys_excluding_plurals(keys))
|
46
|
+
.to eq(%w[key.english])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#key_is_plural?" do
|
51
|
+
it "returns true if key is a plural keyword" do
|
52
|
+
expect(key_is_plural?("other"))
|
53
|
+
.to eq(true)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns false if key isn't a plural keyword" do
|
57
|
+
expect(key_is_plural?("random"))
|
58
|
+
.to eq(false)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe MissingEnglishLocales do
|
6
|
+
context "where there are missing English locales" do
|
7
|
+
let(:all_locales) do
|
8
|
+
[
|
9
|
+
{
|
10
|
+
locale: :en,
|
11
|
+
keys: %w[browse.same_key]
|
12
|
+
},
|
13
|
+
{
|
14
|
+
locale: :cy,
|
15
|
+
keys: %w[browse.same_key browse.extra_key]
|
16
|
+
}
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "outputs the missing locales" do
|
21
|
+
expect(described_class.new(all_locales).report)
|
22
|
+
.to eq(
|
23
|
+
<<~OUTPUT.chomp
|
24
|
+
\e[31m[ERROR]\e[0m Missing English locales, either remove these keys from the foreign locales or add them to the English locales
|
25
|
+
|
26
|
+
\e[1mMissing English keys:\e[22m ["browse.extra_key"]
|
27
|
+
\e[1mFound in:\e[22m [:cy]
|
28
|
+
OUTPUT
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "where there aren't missing English locales" do
|
34
|
+
let(:all_locales) do
|
35
|
+
[
|
36
|
+
{
|
37
|
+
locale: :en,
|
38
|
+
keys: %w[browse.same_key]
|
39
|
+
},
|
40
|
+
{
|
41
|
+
locale: :cy,
|
42
|
+
keys: %w[browse.same_key]
|
43
|
+
}
|
44
|
+
]
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'outputs nil' do
|
48
|
+
expect(described_class.new(all_locales).report)
|
49
|
+
.to be_nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when there are plurals" do
|
54
|
+
let(:all_locales) do
|
55
|
+
[
|
56
|
+
{
|
57
|
+
locale: :en,
|
58
|
+
keys: []
|
59
|
+
},
|
60
|
+
{
|
61
|
+
locale: :cy,
|
62
|
+
keys: %w[browse.plurals.one browse.fake_plurals.other]
|
63
|
+
}
|
64
|
+
]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "doesn't include them in the report" do
|
68
|
+
expect(described_class.new(all_locales).report)
|
69
|
+
.to be_nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe MissingForeignLocales do
|
6
|
+
context "when there are missing foreign locales" do
|
7
|
+
let(:all_locales) do
|
8
|
+
[
|
9
|
+
{
|
10
|
+
locale: :en,
|
11
|
+
keys: %w[browse.same_key browse.extra_nested_key.nest]
|
12
|
+
},
|
13
|
+
{
|
14
|
+
locale: :cy,
|
15
|
+
keys: %w[browse.same_key]
|
16
|
+
},
|
17
|
+
{
|
18
|
+
locale: :fr,
|
19
|
+
keys: %w[browse.same_key]
|
20
|
+
}
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
before do
|
25
|
+
I18n.available_locales << %i[fr]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "outputs the missing locales and groups them by common keys" do
|
29
|
+
expect(described_class.new(all_locales).report)
|
30
|
+
.to eq(
|
31
|
+
<<~OUTPUT.chomp
|
32
|
+
\e[31m[ERROR]\e[0m Missing foreign locales, either add these keys to the foreign locales or remove them from the English locales\e[0m
|
33
|
+
|
34
|
+
\e[1mMissing foreign keys:\e[22m ["browse.extra_nested_key.nest"]
|
35
|
+
\e[1mAbsent from:\e[22m [:cy, :fr]
|
36
|
+
OUTPUT
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when there aren't missing foreign locales" do
|
42
|
+
let(:all_locales) do
|
43
|
+
[
|
44
|
+
{
|
45
|
+
locale: :en,
|
46
|
+
keys: %w[browse.same_key]
|
47
|
+
},
|
48
|
+
{
|
49
|
+
locale: :cy,
|
50
|
+
keys: %w[browse.same_key]
|
51
|
+
}
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
it "outputs nil" do
|
56
|
+
expect(described_class.new(all_locales).report)
|
57
|
+
.to be_nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when there are plurals" do
|
62
|
+
let(:all_locales) do
|
63
|
+
[
|
64
|
+
{
|
65
|
+
locale: :en,
|
66
|
+
keys: %w[browse.plurals.one browse.fake_plurals.other]
|
67
|
+
},
|
68
|
+
{
|
69
|
+
locale: :cy,
|
70
|
+
keys: []
|
71
|
+
}
|
72
|
+
]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "doesn't include them in the report" do
|
76
|
+
expect(described_class.new(all_locales).report)
|
77
|
+
.to be_nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe PluralForms do
|
6
|
+
it "returns plural forms" do
|
7
|
+
expect(described_class.all).to include(
|
8
|
+
{ cy: %i[few many one other two zero], en: %i[one other] }
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when there are missing plural forms" do
|
13
|
+
around do |example|
|
14
|
+
load_path = I18n.load_path
|
15
|
+
# strips I18n of all pluralization files (rules)
|
16
|
+
I18n.load_path = I18n.load_path.flatten.reject { |path| path =~ /plural/ }
|
17
|
+
|
18
|
+
example.run
|
19
|
+
|
20
|
+
I18n.load_path = load_path
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns nil for associated locales" do
|
24
|
+
expect(described_class.all).to include({ cy: nil, en: nil })
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|