rails_translation_manager 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bcf654f074b115a7c80d173e821333d2b8b35b01
4
- data.tar.gz: 84cea8e22ca03313c47e7432be605cee30905391
3
+ metadata.gz: b5174ef0679b5689038dba575d7739d110109836
4
+ data.tar.gz: de386962792fc2d729e98183b7e4c962d41798c1
5
5
  SHA512:
6
- metadata.gz: 6823237f243a4127c4c14ece436ec69212c1e481a1d11d8329649cfbcdc61177bf73f0097c1978fed353c863c83949f9eee62f616c16086f28757ce6645b5f0b
7
- data.tar.gz: 2d8bc1c02272590a00a8bcbec3d002cec989f27c69e5025e65729ebf56c198089d0f29c8f7b87aaab5434642b28f2f11037a9596babdb1e096dd9ff8bda1a850
6
+ metadata.gz: 3e07bb3ed5ec4b2a4f73672f626d0b579240a63115e7ad39345e00b68912f0ecafadbc5666e28ed365aceef30011a24d6821f805b512e1d8c3a3685c38b5ea7c
7
+ data.tar.gz: 96aab0397474451f60f6de06dd2cff484851b493e7f6d5ebd4714aafab99546ebc1f34b8795d70c3282da03cf79a02f2721064ac696fd0c182dba5a2c3591482
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ ## 0.0.2
2
+
3
+ Added `steal` rake tasks to copy translations from another app.
4
+
5
+ ## 0.0.1
6
+
7
+ Initial release.
data/LICENSE.txt CHANGED
@@ -1,5 +1,5 @@
1
1
  The MIT License (MIT)
2
- Copyright (C) 2015 HM Government (Government Digital Service)
2
+ Copyright (C) 2015 Crown Copyright (Government Digital Service)
3
3
 
4
4
  MIT License
5
5
 
data/README.md CHANGED
@@ -124,6 +124,48 @@ $ rake translation:validate
124
124
  Success! No unexpected interpolation keys found.
125
125
  ```
126
126
 
127
+ ### Stealing translations from another app
128
+
129
+ A third feature is the ability to "steal" one or more locales from an existing
130
+ application. This functionality works by providing a mapping file, which defines
131
+ how the translation keys in the the source app's files map to those in the app
132
+ the gem is installed in.
133
+
134
+ For example, given a locale file like this in the app to "steal" from:
135
+
136
+ ```yaml
137
+ es:
138
+ document:
139
+ type:
140
+ case_study: Caso de estudio
141
+ consultation: Consulta
142
+ ```
143
+
144
+ and a mapping file like this:
145
+
146
+ ```yaml
147
+ document.type: content_item.format
148
+ ```
149
+
150
+ running `rake translation:steal[es,../other_app,mapping_file_path.yml]` will
151
+ result in the following locale file being created:
152
+
153
+ ```yaml
154
+ es:
155
+ content_item:
156
+ format:
157
+ case_study: Caso de estudio
158
+ consultation: Consulta
159
+ ```
160
+
161
+ The mapping file can live anywhere, as long as the full path (including filename)
162
+ is given in the rake task invocation.
163
+
164
+ The process will preserve data already in the output file if it is not
165
+ referenced in the mapping, but will always override data belonging to keys
166
+ that are in the mapping.
167
+
168
+
127
169
  ### Rake command reference
128
170
 
129
171
  #### Export a specific locale to CSV
@@ -150,6 +192,8 @@ rake translation:import[locale,path]
150
192
  rake translation:import:all[directory]
151
193
  ```
152
194
 
195
+ ####
196
+
153
197
  #### Regenerate all locales from the EN locale - run this after adding keys
154
198
 
155
199
  ```
@@ -162,6 +206,18 @@ rake translation:regenerate[directory]
162
206
  rake translation:validate
163
207
  ```
164
208
 
209
+ #### Steal a specific locale file from another app
210
+
211
+ ```
212
+ rake translation:steal[locale,source_app_path,mapping_file_path]
213
+ ```
214
+
215
+ #### Steal all locale files from another app
216
+
217
+ ```
218
+ rake translation:steal:all[source_app_path,mapping_file_path]
219
+ ```
220
+
165
221
  ### Running the test suite
166
222
 
167
223
  To run the test suite just run `bundle exec rake` from within the
data/Rakefile CHANGED
@@ -9,4 +9,10 @@ Rake::TestTask.new("test") do |t|
9
9
  t.verbose = true
10
10
  end
11
11
 
12
+ require "gem_publisher"
13
+ task :publish_gem do |t|
14
+ gem = GemPublisher.publish_if_updated("rails_translation_manager.gemspec", :rubygems)
15
+ puts "Published #{gem}" if gem
16
+ end
17
+
12
18
  task :default => :test
data/jenkins.sh ADDED
@@ -0,0 +1,9 @@
1
+ #!/bin/bash -x
2
+ set -e
3
+ rm -f Gemfile.lock
4
+ bundle install --path "${HOME}/bundles/${JOB_NAME}"
5
+ export GOVUK_APP_DOMAIN=dev.gov.uk
6
+ bundle exec rake test
7
+ if [[ -n "$PUBLISH_GEM" ]]; then
8
+ bundle exec rake publish_gem --trace
9
+ fi
@@ -5,4 +5,5 @@ require "rails-i18n"
5
5
  module RailsTranslationManager
6
6
  autoload :Exporter, "rails_translation_manager/exporter"
7
7
  autoload :Importer, "rails_translation_manager/importer"
8
+ autoload :Stealer, "rails_translation_manager/stealer"
8
9
  end
@@ -1,7 +1,10 @@
1
1
  require "yaml"
2
2
  require "csv"
3
+ require_relative "yaml_writer"
3
4
 
4
5
  class RailsTranslationManager::Importer
6
+ include YAMLWriter
7
+
5
8
  def initialize(locale, csv_path, import_directory)
6
9
  @csv_path = csv_path
7
10
  @locale = locale
@@ -25,12 +28,7 @@ class RailsTranslationManager::Importer
25
28
  end
26
29
  end
27
30
 
28
- File.open(import_yml_path, "w") do |f|
29
- yaml = {@locale.to_s => data}.to_yaml(separator: "")
30
- yaml_without_header = yaml.split("\n").map { |l| l.gsub(/\s+$/, '') }[1..-1].join("\n")
31
- f.write(yaml_without_header)
32
- f.puts
33
- end
31
+ write_yaml(import_yml_path, {@locale.to_s => data})
34
32
  end
35
33
 
36
34
  private
@@ -0,0 +1,85 @@
1
+ require "yaml"
2
+ require "i18n"
3
+ require_relative "yaml_writer"
4
+
5
+ class RailsTranslationManager::Stealer
6
+ include YAMLWriter
7
+
8
+ # locale is the locale name as a string.
9
+ # source_app_path is the path to the root of the app to steal from.
10
+ # mapping_file_path is the path to a YAML file mapping translation keys in
11
+ # the source app to those in the target app. For example:
12
+ # document.type: content_item.format
13
+ # document.published: content_item.metadata.published
14
+ # which will import everything under "document.type" and "document.published"
15
+ # in the source app, and write it to "content_item.format" and
16
+ # "content_item.metadata.published" in the target app.
17
+ # locales_path is the path to the locale files to output, which is usually
18
+ # Rails.root.join('config/locales').
19
+ # The process will preserve data already in the output file if it is not
20
+ # referenced in the mapping, but will always override data belonging to keys
21
+ # that are in the mapping.
22
+ def initialize(locale, source_app_path, mapping_file_path, locales_path)
23
+ @locale = locale
24
+ @source_app_path = source_app_path
25
+ @mapping_file_path = mapping_file_path
26
+ @locales_path = locales_path
27
+ end
28
+
29
+ def steal_locale
30
+ target_data = convert_locale(get_target_data)
31
+ write_yaml(target_locale_path, target_data)
32
+ end
33
+
34
+ def convert_locale(target_data)
35
+ mapping_data.each do |source, target|
36
+ data = source_data[@locale]
37
+ source.split('.').each { |key| data = data.fetch(key, {}) }
38
+ set_recursive(target_data[@locale], target.split("."), data)
39
+ end
40
+ target_data
41
+ end
42
+
43
+ private
44
+
45
+ def set_recursive(hash, keys, data)
46
+ if keys.empty?
47
+ data
48
+ else
49
+ key = keys.shift
50
+ hash.tap do |h|
51
+ h.merge!({ key => set_recursive(hash.fetch(key, {}), keys, data)})
52
+ end
53
+ end
54
+ end
55
+
56
+ def source_locale_path
57
+ File.join(@source_app_path, 'config', 'locales', "#{@locale}.yml")
58
+ end
59
+
60
+ def source_data
61
+ @source_data ||= YAML.load_file(source_locale_path)
62
+ end
63
+
64
+ def target_locale_path
65
+ File.join(@locales_path, "#{@locale}.yml")
66
+ end
67
+
68
+ def default_target_data
69
+ { @locale => {} }
70
+ end
71
+
72
+ def get_target_data
73
+ if File.exist?(target_locale_path)
74
+ YAML.load_file(target_locale_path) || default_target_data
75
+ else
76
+ default_target_data
77
+ end
78
+ end
79
+
80
+ def mapping_data
81
+ @mapping_data ||= YAML.load_file(@mapping_file_path)
82
+ end
83
+
84
+ end
85
+
@@ -1,3 +1,3 @@
1
1
  module RailsTranslationManager
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,17 @@
1
+ require 'yaml'
2
+
3
+ module YAMLWriter
4
+
5
+ # `to_yaml` outputs an initial '---\n', which is supposed to be a document
6
+ # separator. We don't want this in the written locale files, so we serialize
7
+ # to a string, remove the header and any trailing whitehspace, and write to
8
+ # the file.
9
+ def write_yaml(filepath, data)
10
+ File.open(filepath, "w") do |f|
11
+ yaml = data.to_yaml(separator: "")
12
+ yaml_without_header = yaml.split("\n").map { |l| l.gsub(/\s+$/, '') }[1..-1].join("\n")
13
+ f.write(yaml_without_header)
14
+ f.puts
15
+ end
16
+ end
17
+ end
@@ -67,4 +67,21 @@ namespace :translation do
67
67
  puts "Success! No unexpected interpolation keys found."
68
68
  end
69
69
  end
70
+
71
+ desc "Import and convert a locale file from another app."
72
+ task :steal, [:locale, :source_app_path, :mapping_file_path] do |t, args|
73
+ stealer = RailsTranslationManager::Stealer.new(args[:locale], args[:source_app_path], args[:mapping_file_path], Rails.root.join('config', 'locales'))
74
+ stealer.steal_locale
75
+ end
76
+
77
+ namespace :steal do
78
+ desc "Import and convert all locale files from another app."
79
+ task :all, [:source_app_path, :mapping_file_path] => [:environment] do |t, args|
80
+ I18n.available_locales.reject { |l| l == :en }.each do |locale|
81
+ stealer = RailsTranslationManager::Stealer.new(locale.to_s, args[:source_app_path], args[:mapping_file_path], Rails.root.join('config', 'locales'))
82
+ stealer.steal_locale
83
+ end
84
+ end
85
+ end
86
+
70
87
  end
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency "activesupport"
23
23
 
24
24
  spec.add_development_dependency "bundler", "~> 1.7"
25
+ spec.add_development_dependency 'gem_publisher', '~> 1.1.1'
25
26
  spec.add_development_dependency "rake", "~> 10.0"
26
27
  spec.add_development_dependency "minitest"
27
28
  end
@@ -32,40 +32,6 @@ module RailsTranslationManager
32
32
  assert_equal expected, yaml_translation_data
33
33
  end
34
34
 
35
- test 'outputs YAML without the header --- line for consistency with convention' do
36
- given_csv(:fr,
37
- [:key, :source, :translation],
38
- ["key", "value", "le value"],
39
- )
40
-
41
- Importer.new(:fr, csv_path(:fr), import_directory).import
42
-
43
- assert_equal "fr:", File.readlines(File.join(import_directory, "fr.yml")).first.strip
44
- end
45
-
46
- test 'outputs a newline at the end of the YAML for consistency with code editors' do
47
- given_csv(:fr,
48
- [:key, :source, :translation],
49
- ["key", "value", "le value"],
50
- )
51
-
52
- Importer.new(:fr, csv_path(:fr), import_directory).import
53
-
54
- assert_match /\n$/, File.readlines(File.join(import_directory, "fr.yml")).last
55
- end
56
-
57
- test 'strips whitespace from the end of lines for consistency with code editors' do
58
- given_csv(:fr,
59
- [:key, :source, :translation],
60
- ["key", "value", nil],
61
- )
62
-
63
- Importer.new(:fr, csv_path(:fr), import_directory).import
64
-
65
- lines = File.readlines(File.join(import_directory, "fr.yml"))
66
- refute lines.any? { |line| line =~ /\s\n$/ }
67
- end
68
-
69
35
  test 'imports arrays from CSV as arrays' do
70
36
  given_csv(:fr,
71
37
  [:key, :source, :translation],
@@ -0,0 +1,251 @@
1
+ require "test_helper"
2
+
3
+ require "rails_translation_manager/stealer"
4
+ require "fileutils"
5
+ require "tmpdir"
6
+ require "csv"
7
+ require "i18n"
8
+
9
+ module RailsTranslationManager
10
+ class StealerTest < Minitest::Test
11
+
12
+ test "converts subtree of items to the same depth" do
13
+
14
+ original = {
15
+ "fr" => {
16
+ "document" => {
17
+ "type" => {
18
+ "type1" => 'premier genre',
19
+ "type2" => 'deuxième genre',
20
+ "type3" => 'troisième genre'
21
+ }
22
+ }
23
+ }
24
+ }
25
+
26
+ conversion_mapping = {
27
+ "document.type" => "content_item.format",
28
+ }
29
+
30
+ expected = {
31
+ "fr" => {
32
+ "content_item" => {
33
+ "format" => {
34
+ "type1" => 'premier genre',
35
+ "type2" => 'deuxième genre',
36
+ "type3" => 'troisième genre'
37
+ }
38
+ }
39
+ }
40
+ }
41
+ stealer_test(original, conversion_mapping, expected)
42
+ end
43
+
44
+ test "converts a subtree of items to a different depth" do
45
+ original = {
46
+ "fr" => {
47
+ "document" => {
48
+ "published" => 'publiée',
49
+ }
50
+ }
51
+ }
52
+ conversion_mapping = {
53
+ "document.published" => "content_item.metadata.published"
54
+ }
55
+
56
+ expected = {
57
+ "fr" => {
58
+ "content_item" => {
59
+ "metadata" => {
60
+ "published" => 'publiée'
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ stealer_test(original, conversion_mapping, expected)
67
+ end
68
+
69
+ test "combines multiple mappings" do
70
+ original = {
71
+ "fr" => {
72
+ "document" => {
73
+ "type" => {
74
+ "type1" => 'premier genre',
75
+ },
76
+ "published" => 'publiée',
77
+ }
78
+ }
79
+ }
80
+
81
+ conversion_mapping = {
82
+ "document.type" => "content_item.format",
83
+ "document.published" => "content_item.metadata.published"
84
+ }
85
+ expected = {
86
+ "fr" => {
87
+ "content_item" => {
88
+ "format" => {
89
+ "type1" => 'premier genre',
90
+ },
91
+ "metadata" => {
92
+ "published" => 'publiée',
93
+ }
94
+ }
95
+ }
96
+ }
97
+ stealer_test(original, conversion_mapping, expected)
98
+ end
99
+
100
+ test "does not copy over keys with no mapping" do
101
+ original = {
102
+ "fr" => {
103
+ "document" => {
104
+ "published" => 'publiée',
105
+ "do_not_want" => 'non voulu'
106
+ }
107
+ }
108
+ }
109
+ conversion_mapping = {
110
+ "document.published" => "content_item.metadata.published"
111
+ }
112
+
113
+ expected = {
114
+ "fr" => {
115
+ "content_item" => {
116
+ "metadata" => {
117
+ "published" => 'publiée'
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ stealer_test(original, conversion_mapping, expected)
124
+ end
125
+
126
+ test "overrides existing translations present in mapping" do
127
+ original = {
128
+ "fr" => {
129
+ "document" => {
130
+ "published" => 'publiée',
131
+ "updated" => 'mise au jour',
132
+ }
133
+ }
134
+ }
135
+
136
+ conversion_mapping = {
137
+ "document.published" => "content_item.metadata.published",
138
+ "document.updated" => "content_item.metadata.updated"
139
+ }
140
+
141
+ existing = {
142
+ "fr" => {
143
+ "content_item" => {
144
+ "metadata" => {
145
+ "updated" => 'mauvaise traduction'
146
+ }
147
+ }
148
+ }
149
+ }
150
+
151
+ expected = {
152
+ "fr" => {
153
+ "content_item" => {
154
+ "metadata" => {
155
+ "published" => 'publiée',
156
+ "updated" => 'mise au jour',
157
+ }
158
+ }
159
+ }
160
+ }
161
+ stealer_test(original, conversion_mapping, expected, existing)
162
+ end
163
+
164
+ test "does not override existing translations not in mapping" do
165
+ original = {
166
+ "fr" => {
167
+ "document" => {
168
+ "published" => 'publiée',
169
+ }
170
+ }
171
+ }
172
+
173
+ conversion_mapping = {
174
+ "document.published" => "content_item.metadata.published"
175
+ }
176
+
177
+ existing = {
178
+ "fr" => {
179
+ "content_item" => {
180
+ "metadata" => {
181
+ "updated" => 'mise au jour',
182
+ }
183
+ }
184
+ }
185
+ }
186
+
187
+ expected = {
188
+ "fr" => {
189
+ "content_item" => {
190
+ "metadata" => {
191
+ "published" => 'publiée',
192
+ "updated" => 'mise au jour',
193
+ }
194
+ }
195
+ }
196
+ }
197
+ stealer_test(original, conversion_mapping, expected, existing)
198
+ end
199
+
200
+ private
201
+
202
+ def stealer_test(original, mapping, expected, existing=nil)
203
+ write_source_data(original)
204
+ write_converter_data(mapping)
205
+
206
+ if existing.present?
207
+ File.open(locale_file, 'w') do |f|
208
+ f.puts(existing.to_yaml)
209
+ end
210
+ end
211
+
212
+ stealer = RailsTranslationManager::Stealer.new("fr", source_dir, converter_path, locales_dir)
213
+ stealer.steal_locale
214
+
215
+ assert_equal expected, YAML.load_file(locale_file)
216
+ end
217
+
218
+ def source_dir
219
+ @source_dir ||= Dir.mktmpdir
220
+ end
221
+
222
+ def source_locale_path
223
+ File.join(source_dir, 'config/locales')
224
+ end
225
+
226
+ def write_source_data(data)
227
+ FileUtils.mkdir_p(source_locale_path)
228
+ File.open(File.join(source_locale_path, 'fr.yml'), 'w') do |f|
229
+ f.puts(data.to_yaml)
230
+ end
231
+ end
232
+
233
+ def write_converter_data(data)
234
+ File.open(converter_path, 'w') do |f|
235
+ f.puts(data.to_yaml)
236
+ end
237
+ end
238
+
239
+ def converter_path
240
+ @converter_path ||= Tempfile.new('fr').path
241
+ end
242
+
243
+ def locales_dir
244
+ @locales_dir ||= Dir.mktmpdir
245
+ end
246
+
247
+ def locale_file
248
+ File.join(locales_dir, 'fr.yml')
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,58 @@
1
+ module RailsTranslationManager
2
+ class DummyWriter
3
+ include YAMLWriter
4
+ end
5
+
6
+ class WriterTest < Minitest::Test
7
+
8
+ def setup
9
+ @output_file = Tempfile.new('fr')
10
+ end
11
+
12
+ def teardown
13
+ @output_file.close
14
+ @output_file.unlink
15
+ end
16
+
17
+ test 'outputs YAML without the header --- line for consistency with convention' do
18
+ data = {"fr" => {
19
+ key1: [:source, :translation],
20
+ "key2" => ["value", "le value"],
21
+ }}
22
+
23
+ DummyWriter.new.write_yaml(output_file, data)
24
+
25
+ assert_equal "fr:", File.readlines(output_file).first.strip
26
+ end
27
+
28
+ test 'outputs a newline at the end of the YAML for consistency with code editors' do
29
+ data = {"fr" => {
30
+ key1: [:source, :translation],
31
+ "key2" => ["value", "le value"],
32
+ }}
33
+
34
+ DummyWriter.new.write_yaml(output_file, data)
35
+
36
+ assert_match /\n$/, File.readlines(output_file).last
37
+ end
38
+
39
+ test 'strips whitespace from the end of lines for consistency with code editors' do
40
+ data = {fr: {
41
+ key1: [:source, :translation],
42
+ "key2" => ["value", nil],
43
+ }}
44
+
45
+ DummyWriter.new.write_yaml(output_file, data)
46
+
47
+ lines = File.readlines(output_file)
48
+ refute lines.any? { |line| line =~ /\s\n$/ }
49
+ end
50
+
51
+ private
52
+
53
+ def output_file
54
+ @output_file.path
55
+ end
56
+ end
57
+ end
58
+
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: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edd Sowden
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-09 00:00:00.000000000 Z
11
+ date: 2015-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails-i18n
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: gem_publisher
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.1.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.1.1
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -90,22 +104,28 @@ files:
90
104
  - ".gitignore"
91
105
  - ".ruby-version"
92
106
  - ".travis.yml"
107
+ - CHANGELOG.md
93
108
  - CONTRIBUTING.md
94
109
  - Gemfile
95
110
  - LICENSE.txt
96
111
  - README.md
97
112
  - Rakefile
113
+ - jenkins.sh
98
114
  - lib/rails_translation_manager.rb
99
115
  - lib/rails_translation_manager/exporter.rb
100
116
  - lib/rails_translation_manager/importer.rb
101
117
  - lib/rails_translation_manager/railtie.rb
118
+ - lib/rails_translation_manager/stealer.rb
102
119
  - lib/rails_translation_manager/validator.rb
103
120
  - lib/rails_translation_manager/version.rb
121
+ - lib/rails_translation_manager/yaml_writer.rb
104
122
  - lib/tasks/translation.rake
105
123
  - rails_translation_manager.gemspec
106
124
  - test/rails_translation_manager/exporter_test.rb
107
125
  - test/rails_translation_manager/importer_test.rb
126
+ - test/rails_translation_manager/stealer_test.rb
108
127
  - test/rails_translation_manager/validator_test.rb
128
+ - test/rails_translation_manager/yaml_writer_test.rb
109
129
  - test/test_helper.rb
110
130
  homepage: ''
111
131
  licenses:
@@ -134,5 +154,7 @@ summary: Tasks to manage translation files
134
154
  test_files:
135
155
  - test/rails_translation_manager/exporter_test.rb
136
156
  - test/rails_translation_manager/importer_test.rb
157
+ - test/rails_translation_manager/stealer_test.rb
137
158
  - test/rails_translation_manager/validator_test.rb
159
+ - test/rails_translation_manager/yaml_writer_test.rb
138
160
  - test/test_helper.rb