i18n-migrations 0.1.4 → 0.2.0

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: 1f368a8f95872f236f752ebee22e0af6d30f8205
4
- data.tar.gz: c6cf48397cd39f07d65be2207da0f83f0924af73
3
+ metadata.gz: 682ef4a62f20bcdffffa20b2f0172e8c9a6f8542
4
+ data.tar.gz: 4b6c731797c9894f2a8fb92e0566b0147f10e44c
5
5
  SHA512:
6
- metadata.gz: 78d56421cb1c62ca4f89b9d16c52e9c0f35ecc82d23f58e631bbe21bd14753d8773dcd90456925197fcfa92514efef6811125393c69744237a14abcef091c751
7
- data.tar.gz: c86f46c588c42c87ed44f60dabd637d9f4424224f0cc674ab9174e898a26bbba82caee996b837d31d234c2ad869d32c7ad11850e952a95a105d00aecde111588
6
+ metadata.gz: 3857c51decac0553515d94152aa141133be04f323244e99468aaccbcde7ef21c224bf13d491df9f2b7e579c083657662842f92b3c04e75ee512e0ef6dbd51702
7
+ data.tar.gz: c038a06ef1bdb0fe5fc9491ffb2f8f807110c57a531592d3e607b40aee3a8e374388c2baf5763de358a67386443e67fe3eade32465fd487ddd8d8f55a1716244
@@ -3,7 +3,7 @@ require 'rest-client'
3
3
  module I18n
4
4
  module Migrations
5
5
  class GoogleTranslateDictionary
6
- def initialize(from_locale, to_locale, key, do_not_translate)
6
+ def initialize(from_locale:, to_locale:, key:, do_not_translate:)
7
7
  @from_locale, @to_locale, @key, @do_not_translate = from_locale, to_locale, key, do_not_translate
8
8
  end
9
9
 
@@ -0,0 +1,249 @@
1
+ require 'fileutils'
2
+ require 'yaml'
3
+ require 'active_support/inflector'
4
+ require 'active_support/core_ext/object'
5
+ require 'colorize'
6
+
7
+ # this class does all the work, but doesn't hold config or do more than one locale
8
+ module I18n
9
+ module Migrations
10
+ class Locale
11
+ attr_reader :name
12
+ attr_reader :migrations
13
+
14
+ def initialize(name, locales_dir:, main_locale_name:, migrations:, dictionary:)
15
+ @name, @locales_dir, @main_locale_name, @migrations, @dictionary =
16
+ name, locales_dir, main_locale_name, migrations, dictionary
17
+ end
18
+
19
+ def validate(data, notes)
20
+ main_data = main_locale.read_data
21
+ main_data.each do |key, main_term|
22
+ old_term = data[key]
23
+ new_term, errors = @dictionary.fix(main_term, old_term)
24
+ if new_term != old_term
25
+ data[key] = new_term
26
+ puts "#{"Fix".green} #{key.green}:"
27
+ puts "#{@main_locale_name}: #{main_term}"
28
+ puts "#{@name} (old): #{old_term}"
29
+ puts "#{@name} (new): #{new_term}"
30
+ puts
31
+ end
32
+ replace_errors_in_notes(notes, key, errors)
33
+ if errors.length > 0
34
+ puts "Error #{errors.join(', ').red} #{key.yellow}"
35
+ puts "#{@main_locale_name.bold}: #{main_term}"
36
+ puts "#{@name.bold}: #{old_term}"
37
+ puts
38
+ end
39
+ end
40
+ end
41
+
42
+ def update_info
43
+ data, notes = read_data_and_notes
44
+ yield data, notes
45
+ write_data_and_notes(data, notes)
46
+ end
47
+
48
+ def migrate(data, notes)
49
+ missing_versions = (@migrations.all_versions - read_versions(data)).sort
50
+ if missing_versions.empty?
51
+ puts "#{@name}: up-to-date"
52
+ return
53
+ end
54
+ puts "#{@name}: Migrating #{missing_versions.join(', ')}"
55
+ missing_versions.each do |version|
56
+ migrate_to_version(data, notes, version, :up)
57
+ end
58
+ end
59
+
60
+ def rollback(data, notes)
61
+ last_version = read_versions(data).last
62
+ if last_version == nil
63
+ puts "#{@name}: no more migrations to roll back"
64
+ return
65
+ end
66
+ puts "#{@name}: Rolling back #{last_version}"
67
+ raise "Can't find #{last_version}.rb to rollback" unless @migrations.all_versions.include?(last_version)
68
+
69
+ migrate_to_version(data, notes, last_version, :down)
70
+ end
71
+
72
+ def pull(sheet)
73
+ puts "Pulling #{@name}"
74
+ data = {}
75
+ notes = {}
76
+ count = 0
77
+
78
+ (2..sheet.num_rows).each do |row|
79
+ key, value, note = sheet[row, 1], sheet[row, 3], sheet[row, 4]
80
+ if key.present?
81
+ assign_complex_key(data, key.split('.'), value.present? ? value : '')
82
+ if note.present?
83
+ assign_complex_key(notes, key.split('.'), note)
84
+ end
85
+ count += 1
86
+ print '.'
87
+ end
88
+ end
89
+
90
+ write_data_and_notes(data, notes)
91
+ write_remote_version(data)
92
+
93
+ puts "\n#{count} keys"
94
+ end
95
+
96
+ def push(sheet)
97
+ main_data = main_locale.read_data
98
+ data, notes = read_data_and_notes
99
+ row = 2
100
+
101
+ puts "Pushing #{@name}"
102
+
103
+ main_data.each do |key, value|
104
+ sheet[row, 1] = key
105
+ sheet[row, 2] = value
106
+ sheet[row, 3] = data[key]
107
+ sheet[row, 4] = notes[key]
108
+ row += 1
109
+ print '.'
110
+ end
111
+
112
+ sheet.synchronize
113
+ write_remote_version(data)
114
+
115
+ puts "\n#{main_data.keys.length} keys"
116
+ end
117
+
118
+ def create(limit = nil)
119
+ new_data, new_notes = {}, {}
120
+ count = 0
121
+ main_data = main_locale.read_data
122
+ main_data.each do |key, term|
123
+ new_data[key], new_notes[key] = @dictionary.lookup(term)
124
+ print '.'.green
125
+ break if limit && limit < (count += 1)
126
+ end
127
+ new_data['VERSION'] = main_data['VERSION']
128
+ puts
129
+ write_data_and_notes(new_data, new_notes)
130
+ end
131
+
132
+ def main_locale?
133
+ @name == @main_locale_name
134
+ end
135
+
136
+ def last_version
137
+ read_versions(read_data).last
138
+ end
139
+
140
+ private
141
+
142
+ def main_locale
143
+ Locale.new(@main_locale_name,
144
+ locales_dir: @locales_dir,
145
+ main_locale_name: @main_locale_name,
146
+ migrations: @migrations,
147
+ dictionary: null) # should not use dictionary on main locale
148
+ end
149
+
150
+ def replace_errors_in_notes(all_notes, key, errors)
151
+ return if all_notes[key].blank? && errors.empty?
152
+
153
+ notes = all_notes[key]
154
+ notes = notes.present? ? notes.split("\n") : []
155
+ notes = notes.reject { |n| n.start_with?("[error:") }
156
+ all_notes[key] = (errors.map { |e| "[error: #{e}]" } + notes).join("\n")
157
+ end
158
+
159
+ def read_data_and_notes
160
+ data = read_data
161
+ notes = main_locale? ? {} : read_from_file("../#{@name}_notes.yml")
162
+ [data, notes]
163
+ end
164
+
165
+ def read_data
166
+ read_from_file("#{@name}.yml")
167
+ end
168
+
169
+ def write_data_and_notes(data, notes)
170
+ write_to_file("#{@name}.yml", data)
171
+ write_to_file("../#{@name}_notes.yml", notes) unless main_locale?
172
+ end
173
+
174
+
175
+ def write_remote_version(data)
176
+ write_to_file("../#{@name}_remote_version.yml",
177
+ { 'VERSION' => read_versions(data) })
178
+ end
179
+
180
+
181
+ def migrate_to_version(data, notes, version, direction)
182
+ migrations.play_migration(version: version,
183
+ locale: @name,
184
+ data: data,
185
+ notes: notes,
186
+ dictionary: @dictionary,
187
+ direction: direction)
188
+
189
+ if direction == :up
190
+ data['VERSION'] = (read_versions(data) + [version]).join("\n")
191
+ else
192
+ data['VERSION'] = (read_versions(data) - [version]).join("\n")
193
+ end
194
+ end
195
+
196
+ def read_versions(data)
197
+ (data['VERSION'] && data['VERSION'].split("\n")) || []
198
+ end
199
+
200
+ def read_from_file(filename)
201
+ filename = File.join(@locales_dir, filename)
202
+ begin
203
+ hash = {}
204
+ add_to_hash(hash, YAML.load(File.read(filename))[@name.to_s])
205
+ hash
206
+ rescue
207
+ puts "Error loading #{filename}"
208
+ raise
209
+ end
210
+ end
211
+
212
+ def write_to_file(filename, hash)
213
+ # we have to go from flat keys -> values to a hash that contains other hashes
214
+ complex_hash = {}
215
+ hash.keys.sort.each do |key|
216
+ value = hash[key]
217
+ assign_complex_key(complex_hash, key.split('.'), value.present? ? value : '')
218
+ end
219
+ File.open(File.join(@locales_dir, filename), 'w') do |file|
220
+ file << { @name => complex_hash }.to_yaml
221
+ end
222
+ end
223
+
224
+ def assign_complex_key(hash, key, value)
225
+ if key.length == 0
226
+ # should never get here
227
+ elsif key.length == 1
228
+ hash[key[0]] = value
229
+ else
230
+ hash[key[0]] ||= {}
231
+ assign_complex_key(hash[key[0]], key[1..-1], value)
232
+ end
233
+ end
234
+
235
+ # flattens new_hash and adds it to hash
236
+ def add_to_hash(hash, new_hash, prefix = [])
237
+ return unless new_hash
238
+
239
+ new_hash.each do |key, value|
240
+ if value.is_a?(Hash)
241
+ add_to_hash(hash, value, prefix + [key])
242
+ else
243
+ hash[(prefix + [key]).join('.')] = value
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,29 @@
1
+ require 'active_support/inflector'
2
+
3
+ module I18n
4
+ module Migrations
5
+ class MigrationFactory
6
+ def initialize(migration_dir)
7
+ @migration_dir = migration_dir
8
+ end
9
+
10
+ def all_versions
11
+ Dir[@migration_dir + '/*.rb'].map { |name| File.basename(name).gsub('.rb', '') }
12
+ end
13
+
14
+ def play_migration(version:, locale:, data:, notes:, dictionary:, direction:)
15
+ filename = File.join(@migration_dir, "#{version}.rb")
16
+ require filename
17
+ migration_class_name = version.gsub(/^\d{12}_/, '').camelcase
18
+
19
+ migration = begin
20
+ migration_class_name.constantize.new(locale, data, notes, dictionary, direction)
21
+ rescue
22
+ raise "Couldn't load migration #{migration_class_name} in #{filename}"
23
+ end
24
+
25
+ migration.change
26
+ end
27
+ end
28
+ end
29
+ end
@@ -8,14 +8,31 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
8
  require 'google_translate_dictionary'
9
9
  require 'google_spreadsheet'
10
10
  require 'config'
11
+ require 'locale'
12
+ require 'migration_factory'
11
13
 
14
+ # this class knows how to do all the things the cli needs done.
15
+ # it mostly delegates to locale to do it, often asking multiple locales to do the same thing
12
16
  module I18n
13
17
  module Migrations
14
18
  class Migrator
19
+ def locale_for(name)
20
+ Locale.new(name,
21
+ locales_dir: config.locales_dir,
22
+ main_locale_name: config.main_locale,
23
+ migrations: MigrationFactory.new(config.migration_dir),
24
+ dictionary: new_dictionary(name))
25
+ end
26
+
15
27
  def config
16
28
  @config ||= Config.new.read!
17
29
  end
18
30
 
31
+ # for testing
32
+ def config=(config)
33
+ @config = config
34
+ end
35
+
19
36
  def new_migration(name)
20
37
  name = name.parameterize(separator: '_')
21
38
  file_name = "#{Time.now.strftime('%Y%m%d%H%M')}_#{name.downcase.gsub(' ', '_')}.rb"
@@ -39,299 +56,84 @@ end
39
56
 
40
57
  def migrate(locale_or_all = 'all')
41
58
  each_locale(locale_or_all) do |locale|
42
- update_locale_info(locale) do |data, notes|
43
- migrate_locale(locale, data, notes)
59
+ locale.update_info do |data, notes|
60
+ locale.migrate(data, notes)
44
61
  end
45
62
  end
46
63
  end
47
64
 
48
65
  def rollback(locale_or_all)
49
66
  each_locale(locale_or_all) do |locale|
50
- update_locale_info(locale) do |data, notes|
51
- rollback_locale(locale, data, notes)
67
+ locale.update_info do |data, notes|
68
+ locale.rollback(data, notes)
52
69
  end
53
70
  end
54
71
  end
55
72
 
56
73
  def pull(locale_or_all)
57
74
  each_locale(locale_or_all) do |locale|
58
- next if locale == config.main_locale
59
- sheet = get_google_spreadsheet(locale)
60
- pull_locale(locale, sheet)
61
- migrate(locale)
75
+ next if locale.main_locale?
76
+ sheet = get_google_spreadsheet(locale.name)
77
+ locale.pull(sheet)
78
+ migrate(locale.name)
62
79
  end
63
80
  end
64
81
 
65
82
  def push(locale_or_all, force = false)
66
83
  each_locale(locale_or_all) do |locale|
67
- next if locale == config.main_locale
84
+ next if locale.main_locale?
68
85
  sheet = get_google_spreadsheet(locale)
69
86
  unless force
70
- pull_locale(locale, sheet)
71
- migrate(locale)
87
+ locale.pull(sheet)
88
+ migrate(locale.name)
72
89
  end
73
- push_locale(locale, sheet)
90
+ locale.push(sheet)
74
91
  end
75
92
  end
76
93
 
77
94
  def new_locale(new_locale, limit = nil)
78
- dictionary = new_dictionary(new_locale)
79
- new_data, new_notes = {}, {}
80
- count = 0
81
- main_data = read_locale_data(config.main_locale)
82
- main_data.each do |key, term|
83
- new_data[key], new_notes[key] = dictionary.lookup(term)
84
- print '.'.green
85
- break if limit && limit < count += 1
86
- end
87
- new_data['VERSION'] = main_data['VERSION']
88
- puts
89
- write_locale_data_and_notes(new_locale, new_data, new_notes)
95
+ locale_for(new_locale).create
90
96
  end
91
97
 
92
98
  def version
93
99
  each_locale do |locale|
94
- puts "#{locale}: #{locale_versions(read_locale_data(locale)).last}"
100
+ puts "#{locale.name}: #{locale.last_version}"
95
101
  end
96
102
  end
97
103
 
98
104
  def validate(locale_or_all)
99
105
  each_locale(locale_or_all) do |locale|
100
- next if locale == config.main_locale
101
- update_locale_info(locale) do |data, notes|
102
- validate_locale(locale, data, notes)
106
+ next if locale.main_locale?
107
+ locale.update_info do |data, notes|
108
+ locale.validate(data, notes)
103
109
  end
104
110
  end
105
111
  end
106
112
 
107
113
  private
108
114
 
109
- def validate_locale(locale, data, notes)
110
- main_data = read_locale_data(config.main_locale)
111
- dict = new_dictionary(locale)
112
- main_data.each do |key, main_term|
113
- old_term = data[key]
114
- new_term, errors = dict.fix(main_term, old_term)
115
- if new_term != old_term
116
- data[key] = new_term
117
- puts "#{"Fix".green} #{key.green}:"
118
- puts "#{config.main_locale}: #{main_term}"
119
- puts "#{locale} (old): #{old_term}"
120
- puts "#{locale} (new): #{new_term}"
121
- puts
122
- end
123
- replace_errors_in_notes(notes, key, errors)
124
- if errors.length > 0
125
- puts "Error #{errors.join(', ').red} #{key.yellow}"
126
- puts "#{config.main_locale.bold}: #{main_term}"
127
- puts "#{locale.bold}: #{old_term}"
128
- puts
129
- end
130
- end
131
- end
132
-
133
- def replace_errors_in_notes(all_notes, key, errors)
134
- return if all_notes[key].blank? && errors.empty?
135
-
136
- notes = all_notes[key]
137
- notes = notes.present? ? notes.split("\n") : []
138
- notes = notes.reject { |n| n.start_with?("[error:") }
139
- all_notes[key] = (errors.map{|e| "[error: #{e}]"} + notes).join("\n")
140
- end
141
-
142
- def update_locale_info(locale)
143
- data, notes = read_locale_data_and_notes(locale)
144
- yield data, notes
145
- write_locale_data_and_notes(locale, data, notes)
146
- end
147
-
148
- def read_locale_data_and_notes(locale)
149
- data = read_locale_data(locale)
150
- notes = locale == config.main_locale ? {} : read_locale_from_file(locale, "../#{locale}_notes.yml")
151
- [data, notes]
152
- end
153
-
154
- def read_locale_data(locale)
155
- read_locale_from_file(locale, "#{locale}.yml")
156
- end
157
-
158
- def write_locale_data_and_notes(locale, data, notes)
159
- write_locale_to_file(locale, "#{locale}.yml", data)
160
- write_locale_to_file(locale, "../#{locale}_notes.yml", notes) unless locale == config.main_locale
161
- end
162
-
163
- def pull_locale(locale, sheet)
164
- puts "Pulling #{locale}"
165
- data = {}
166
- notes = {}
167
- count = 0
168
-
169
- (2..sheet.num_rows).each do |row|
170
- key, value, note = sheet[row, 1], sheet[row, 3], sheet[row, 4]
171
- if key.present?
172
- assign_complex_key(data, key.split('.'), value.present? ? value : '')
173
- if note.present?
174
- assign_complex_key(notes, key.split('.'), note)
175
- end
176
- count += 1
177
- print '.'
178
- end
179
- end
180
-
181
- write_locale_data_and_notes(locale, data, notes)
182
- write_locale_remote_version(locale, data)
183
-
184
- puts "\n#{count} keys"
185
- end
186
-
187
- def write_locale_remote_version(locale, data)
188
- write_locale_to_file(locale,
189
- "../#{locale}_remote_version.yml",
190
- { 'VERSION' => locale_versions(data) })
191
- end
192
-
193
- def push_locale(locale, sheet)
194
- main_data = read_locale_data(config.main_locale)
195
- data, notes = read_locale_data_and_notes(locale)
196
- row = 2
197
-
198
- puts "Pushing #{locale}"
199
-
200
- main_data.each do |key, value|
201
- sheet[row, 1] = key
202
- sheet[row, 2] = value
203
- sheet[row, 3] = data[key]
204
- sheet[row, 4] = notes[key]
205
- row += 1
206
- print '.'
207
- end
208
-
209
- sheet.synchronize
210
- write_locale_remote_version(locale, data)
211
-
212
- puts "\n#{main_data.keys.length} keys"
213
- end
214
-
215
- def migrate_locale(locale, data, notes)
216
- missing_versions = (all_versions - locale_versions(data)).sort
217
- if missing_versions.empty?
218
- puts "#{locale}: up-to-date"
219
- return
220
- end
221
- puts "#{locale}: Migrating #{missing_versions.join(', ')}"
222
- missing_versions.each do |version|
223
- migrate_locale_to_version(locale, data, notes, version, :up)
224
- end
225
- end
226
-
227
- def rollback_locale(locale, data, notes)
228
- last_version = locale_versions(data).last
229
- if last_version == nil
230
- puts "#{locale}: no more migrations to roll back"
231
- return
232
- end
233
- puts "#{locale}: Rolling back #{last_version}"
234
- raise "Can't find #{last_version}.rb to rollback" unless all_versions.include?(last_version)
235
-
236
- migrate_locale_to_version(locale, data, notes, last_version, :down)
237
- end
238
-
239
- def migrate_locale_to_version(locale, data, notes, version, direction)
240
- filename = File.join(config.migration_dir, "#{version}.rb")
241
- require filename
242
- migration_class_name = version.gsub(/^\d{12}_/, '').camelcase
243
- dictionary = new_dictionary(locale)
244
-
245
- migration = begin
246
- migration_class_name.constantize.new(locale, data, notes, dictionary, direction)
247
- rescue
248
- raise "Couldn't load migration #{migration_class_name} in #{filename}"
249
- end
250
-
251
- migration.change
252
-
253
- if direction == :up
254
- data['VERSION'] = (locale_versions(data) + [version]).join("\n")
255
- else
256
- data['VERSION'] = (locale_versions(data) - [version]).join("\n")
257
- end
258
- end
259
-
260
- def locale_versions(data)
261
- (data['VERSION'] && data['VERSION'].split("\n")) || []
262
- end
263
-
264
- def read_locale_from_file(locale, filename)
265
- filename = File.join(config.locales_dir, filename)
266
- begin
267
- hash = {}
268
- add_to_hash(hash, YAML.load(File.read(filename))[locale.to_s])
269
- hash
270
- rescue
271
- puts "Error loading #{filename}"
272
- raise
273
- end
274
- end
275
-
276
- def write_locale_to_file(locale, filename, hash)
277
- # we have to go from flat keys -> values to a hash that contains other hashes
278
- complex_hash = {}
279
- hash.keys.sort.each do |key|
280
- value = hash[key]
281
- assign_complex_key(complex_hash, key.split('.'), value.present? ? value : '')
282
- end
283
- File.open(File.join(config.locales_dir, filename), 'w') do |file|
284
- file << { locale => complex_hash }.to_yaml
115
+ def each_locale(name = 'all')
116
+ (name == 'all' ? all_locale_names : [name]).each do |l|
117
+ yield locale_for(l)
285
118
  end
286
119
  end
287
120
 
288
- def assign_complex_key(hash, key, value)
289
- if key.length == 0
290
- # should never get here
291
- elsif key.length == 1
292
- hash[key[0]] = value
293
- else
294
- hash[key[0]] ||= {}
295
- assign_complex_key(hash[key[0]], key[1..-1], value)
296
- end
297
- end
298
-
299
- # flattens new_hash and adds it to hash
300
- def add_to_hash(hash, new_hash, prefix = [])
301
- return unless new_hash
302
-
303
- new_hash.each do |key, value|
304
- if value.is_a?(Hash)
305
- add_to_hash(hash, value, prefix + [key])
306
- else
307
- hash[(prefix + [key]).join('.')] = value
308
- end
309
- end
310
- end
311
-
312
- def each_locale(locale = 'all')
313
- (locale == 'all' ? all_locales : [locale]).each do |l|
314
- yield l
315
- end
316
- end
317
-
318
- def all_locales
121
+ def all_locale_names
319
122
  [config.main_locale] + config.other_locales
320
123
  end
321
124
 
322
- def all_versions
323
- Dir[config.migration_dir + '/*.rb'].map { |name| File.basename(name).gsub('.rb', '') }
324
- end
325
-
326
- def new_dictionary(locale)
327
- GoogleTranslateDictionary.new(config.main_locale, locale, config.google_translate_api_key, config.do_not_translate)
328
- end
329
-
330
125
  def get_google_spreadsheet(locale)
331
126
  GoogleSpreadsheet.new(locale,
332
127
  config.google_spreadsheets[locale],
333
128
  config.google_service_account_key_path).sheet
334
129
  end
130
+
131
+ def new_dictionary(locale)
132
+ GoogleTranslateDictionary.new(from_locale: config.main_locale,
133
+ to_locale: locale,
134
+ key: config.google_translate_api_key,
135
+ do_not_translate: config.do_not_translate)
136
+ end
335
137
  end
336
138
  end
337
139
  end
@@ -1,5 +1,5 @@
1
1
  module I18n
2
2
  module Migrations
3
- VERSION = "0.1.4"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Lightsmith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-03 00:00:00.000000000 Z
11
+ date: 2018-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,7 +122,9 @@ files:
122
122
  - lib/i18n/migrations/config.rb
123
123
  - lib/i18n/migrations/google_spreadsheet.rb
124
124
  - lib/i18n/migrations/google_translate_dictionary.rb
125
+ - lib/i18n/migrations/locale.rb
125
126
  - lib/i18n/migrations/migration.rb
127
+ - lib/i18n/migrations/migration_factory.rb
126
128
  - lib/i18n/migrations/migrator.rb
127
129
  - lib/i18n/migrations/version.rb
128
130
  homepage: https://github.com/transparentclassroom/i18n-migrations