interpret 0.1.2 → 0.1.3

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.
@@ -23,7 +23,7 @@ module Interpret
23
23
  tree = LazyHash.build_hash
24
24
  all_trans = all_trans.map{|x| x.key.split(".")[0..-2].join(".")}.uniq
25
25
  all_trans.each do |x|
26
- LazyHash.lazy_add(tree, x, {})
26
+ LazyHash.add(tree, x, {})
27
27
  end
28
28
 
29
29
  # Generate a new clean hash without the proc's from LazyHash.
@@ -38,7 +38,7 @@ module Interpret
38
38
  res = LazyHash.build_hash
39
39
 
40
40
  translations.each do |e|
41
- LazyHash.lazy_add(res, "#{e.locale}.#{e.key}", e.value)
41
+ LazyHash.add(res, "#{e.locale}.#{e.key}", e.value)
42
42
  end
43
43
  if res.keys.size != 1
44
44
  raise IndexError, "Generated hash must have only one root key. Your translation data in datrabase may be corrupted."
@@ -61,26 +61,20 @@ module Interpret
61
61
  raise ArgumentError, "the YAML file must contain an unique first key representing the locale" unless hash.keys.count == 1
62
62
 
63
63
  lang = hash.keys.first
64
- to_remove = locale(lang).all
65
- to_remove.each do |x|
66
- x.destroy
67
- end
64
+ delete_all(:locale => lang)
65
+
68
66
  records = parse_hash(hash.first[1], lang)
69
67
  # TODO: Replace with activerecord-import bulk inserts
70
68
  transaction do
71
- records.each {|x| x.save!}
69
+ records.each do |x|
70
+ x.save!
71
+ end
72
72
  end
73
73
  end
74
74
 
75
75
  # Dump all contents from *.yml locale files into the database.
76
76
  # CAUTION: All existing data will be erased!
77
77
  #
78
- # It will create a "#{locale}.yml.backup" file into config/locales
79
- # for each language present in the database, in case you want to
80
- # recover some of your just-erased translations.
81
- # If you don't want backups, set:
82
- #
83
- # Interpret.options[:dump_without_backup] = true
84
78
  def dump
85
79
  files = Dir[Rails.root.join("config", "locales", "*.yml").to_s]
86
80
  delete_all
@@ -139,18 +133,23 @@ module Interpret
139
133
  #
140
134
  # - First of all, get the locale keys for the main language from yml files.
141
135
  # - For all of these locale keys, do:
142
- # - If a key is present in the db, but not in the new ones, remove
143
- # it. You have removed it from the new content layout, so it's no longer
144
- # needed.
145
136
  # - If the key is not present in the db, it's new. So, create a new
146
- # entry for that key in each language. Look if a translation for that
147
- # key exists in yml files for each language, if it exists, use it. If
148
- # not, left it empty.
137
+ # entry for that key in the main language. If the key also exists in
138
+ # some other languages in yml files, also create the entry for that
139
+ # languages. But, do not create entries for the languages that does
140
+ # not have this key. Later you will be notified about that missing
141
+ # translations.
149
142
  # - If the key already exists in the db, do nothing. Maybe somone has
150
143
  # changed that content in production, and you don't want to lose
151
144
  # that. Or maybe you do want to change that content, because you
152
145
  # just added the correct sentence in the yml files. It's up to you to
153
146
  # do the right thing.
147
+ # Also, if the key is missing in other languages in database but
148
+ # present in yml files, create the new entry for that language.
149
+ # - If a key is present in the db, but not in the new ones, remove
150
+ # it. You have removed it from the new content layout, so it's no longer
151
+ # needed.
152
+ #
154
153
  def update
155
154
  files = Dir[Rails.root.join("config", "locales", "*.yml").to_s]
156
155
 
@@ -165,8 +164,7 @@ module Interpret
165
164
  end
166
165
  end
167
166
 
168
- @main = @languages[I18n.default_locale.to_s].clone
169
- sync(@main)
167
+ sync(@languages[I18n.default_locale.to_s])
170
168
  end
171
169
 
172
170
  private
@@ -178,16 +176,15 @@ module Interpret
178
176
  end
179
177
 
180
178
  hash.keys.each do |x|
181
- existing.delete(x)
182
-
183
179
  if hash[x].kind_of?(Hash)
184
180
  sync(hash[x], "#{prefix}#{x}.", existing[x])
185
181
  else
182
+ existing.delete(x)
186
183
  old = locale(I18n.default_locale).find_by_key("#{prefix}#{x}")
187
184
 
188
185
  unless old
189
186
  # Creates the new entry
190
- create_new_translation("#{prefix}#{x}")
187
+ create_new_translation("#{prefix}#{x}", hash[x])
191
188
  else
192
189
  # Check if the entry exists in the other languages
193
190
  check_in_other_langs("#{prefix}#{x}")
@@ -200,37 +197,33 @@ module Interpret
200
197
  end
201
198
  end
202
199
 
203
- # Check if the the given key exists in all languages except @main. If
204
- # not, create an entry.
200
+ # Check if the given key exists in @languages for locales other than
201
+ # I18n.default_locale. Create the existing ones.
205
202
  def check_in_other_langs(key)
206
203
  (@languages.keys - [I18n.default_locale]).each do |lang|
207
204
  trans = locale(lang).find_by_key(key)
208
205
  if trans.nil?
209
- create! :locale => lang,
210
- :key => key,
211
- :value => "untranslated"
212
- Interpret.logger.info "Created inexistent key [#{key}] for lang [#{lang}]"
206
+ if value = get_value_from_hash(@languages[lang], key)
207
+ create! :locale => lang, :key => key, :value => value
208
+ Interpret.logger.info "New key created [#{key}] for language [#{lang}]"
209
+ end
213
210
  end
214
211
  end
215
212
  end
216
213
 
217
- def create_new_translation(missing_key)
218
- @languages.keys.each do |lang|
219
- origin_hash = @languages[lang].clone
220
- value = nil
221
- missing_key.split(".")[0..-2].each do |key|
222
- if origin_hash[key].nil?
223
- value = "untranslated"
224
- break
225
- end
226
- origin_hash = origin_hash[key]
227
- end
228
- value ||= origin_hash[missing_key.split(".").last]
229
- create! :locale => lang,
230
- :key => missing_key,
231
- :value => value
214
+ def get_value_from_hash(hash, key)
215
+ key.split(".")[0..-2].each do |k|
216
+ break if hash.nil?
217
+ hash = hash[k]
232
218
  end
233
- Interpret.logger.info "New key created [#{missing_key}] for languages #{@languages.keys.inspect}"
219
+ hash.nil? ? nil : hash[key.split(".").last]
220
+ end
221
+
222
+ def create_new_translation(missing_key, main_value)
223
+ create! :locale => I18n.default_locale, :key => missing_key, :value => main_value
224
+ Interpret.logger.info "New key created [#{missing_key}] for language [#{I18n.default_locale}]"
225
+
226
+ check_in_other_langs(missing_key)
234
227
  end
235
228
 
236
229
  def remove_unused_keys(hash, prefix = "")
data/interpret.gemspec CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
25
25
  s.add_dependency "ya2yaml", ">= 0.30.0"
26
26
  s.add_dependency "will_paginate", ">= 3.0.pre2"
27
27
  s.add_dependency "best_in_place", ">= 0.1.7"
28
+ s.add_dependency "lazyhash", ">= 0.1.1"
28
29
 
29
30
  s.add_development_dependency "rspec-rails", "~> 2.5"
30
31
  end
data/lib/interpret.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'best_in_place'
2
2
  require 'will_paginate'
3
- require 'interpret/lazy_hash'
3
+ require 'lazyhash'
4
4
 
5
5
  module Interpret
6
6
  mattr_accessor :backend
@@ -1,3 +1,3 @@
1
1
  module Interpret
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'spec_helper'
2
3
 
3
4
  describe Interpret::Translation do
@@ -7,6 +8,7 @@ en:
7
8
  p1: Hello world!
8
9
  folder1:
9
10
  pr1: Hi
11
+ content: Some large text content
10
12
  folder2:
11
13
  pr1: Some other text here
12
14
  folder3:
@@ -20,19 +22,93 @@ en:
20
22
  """
21
23
  }
22
24
 
25
+ let(:es_yml) {"""
26
+ es:
27
+ folder2:
28
+ pr1: Algun otro texto aqui
29
+ content: Un largo parrafo con contenido
30
+ folder3:
31
+ pr1: Mas frases aleatorias
32
+ sub:
33
+ name: Esta es una subcarpeta de segundo nivel
34
+ subsub:
35
+ name: Con otra carpeta anidada en su interior
36
+ other:
37
+ name: carpeta
38
+ """
39
+ }
40
+
41
+ let(:new_en_yml) {"""
42
+ en:
43
+ p1: Hello modified world! This new translation should not be copied into database
44
+ new_key: This new key should be created with this english text
45
+ new_key_in_en: This new key that only exists in english should be created only in english
46
+
47
+ folder1:
48
+ pr1: Hi
49
+ folder2:
50
+ pr1: Some other text here
51
+ folder3:
52
+ pr1: More phrases
53
+ sub:
54
+ name: This is a 2 level subfolder
55
+ subsub:
56
+ name: With another nested folder inside
57
+ other:
58
+ name: folder
59
+ """
60
+ }
61
+
62
+ let(:new_es_yml) {"""
63
+ es:
64
+ p1: Hola mon! Esta nueva traduccion al español deberia copiarse en base de datos porque no existe previamente en :es, aunque si en :en
65
+ new_key: Esta nueva clave debe crearse con este texto en español
66
+
67
+ folder1:
68
+ pr1: Nueva traduccion que tambien debe copiarse
69
+ folder2:
70
+ pr1: Algun otro texto aqui
71
+ content: Un largo parrafo con contenido
72
+ folder3:
73
+ pr1: Mas frases aleatorias
74
+ sub:
75
+ name: Esta es una subcarpeta de segundo nivel
76
+ subsub:
77
+ name: Con otra carpeta anidada en su interior
78
+ other:
79
+ name: carpeta
80
+ """
81
+ }
82
+
83
+ # Convert a locale file into database translations
23
84
  def file2db(string_file)
24
- hash = YAML.load string_file
85
+ def parse_hash(dict, locale, prefix = "")
86
+ res = []
87
+ dict.keys.each do |x|
88
+ if dict[x].kind_of?(Hash)
89
+ res += parse_hash(dict[x], locale, "#{prefix}#{x}.")
90
+ else
91
+ res << Interpret::Translation.new(:locale => locale, :key => "#{prefix}#{x}", :value => dict[x])
92
+ end
93
+ end
94
+ res
95
+ end
25
96
 
97
+ hash = YAML.load string_file
26
98
  lang = hash.keys.first
27
- records = Interpret::Translation.send(:parse_hash, hash.first[1], lang)
28
99
  Interpret::Translation.transaction do
29
- records.each {|x| x.save!}
100
+ parse_hash(hash.first[1], lang).map{|x| x.save!}
30
101
  end
31
102
  end
32
103
 
104
+ before do
105
+ I18n.stub!(:default_locale).and_return('en')
106
+ end
107
+
33
108
  describe ".get_tree" do
34
109
  it "should return a hash representing a tree folder structure of the i18n keys" do
35
110
  file2db(en_yml)
111
+
36
112
  Interpret::Translation.get_tree('en').should == {'index' => {
37
113
  'folder1' => {},
38
114
  'folder2' => {},
@@ -49,20 +125,114 @@ en:
49
125
  describe ".export" do
50
126
  it "should return a hash representing the yml locale file for the given translations" do
51
127
  file2db(en_yml)
128
+
52
129
  translations = Interpret::Translation.all
53
130
  Interpret::Translation.export(translations).should == YAML.load(en_yml)
54
131
  end
55
132
  end
56
133
 
57
- describe ".import" do
58
- pending
134
+ describe ".update" do
135
+ before(:all) do
136
+ # Supose the database has the default contents, look at the top of this
137
+ # file for en_yml simulated locale file
138
+ file2db(en_yml)
139
+ file2db(es_yml)
140
+ end
141
+
142
+ before do
143
+ Dir.stub!(:"[]").and_return(['/path/to/en.yml', '/path/to/es.yml'])
144
+ YAML.should_receive(:load_file).twice.and_return(YAML.load(new_en_yml), YAML.load(new_es_yml))
145
+ end
146
+
147
+ context "when a key exists in database but not in yml files [for I18n.default_locale]" do
148
+ it "should remove that key from database for I18n.default_locale" do
149
+ Interpret::Translation.update
150
+ Interpret::Translation.locale('en').find_by_key("folder1.content").should be_nil
151
+ end
152
+
153
+ it "should remove that key if it exists for any other language in database" do
154
+ Interpret::Translation.update
155
+ Interpret::Translation.locale('es').find_by_key("folder1.content").should be_nil
156
+ end
157
+ end
158
+
159
+ context "when a key exists in yml files but not in database [for I18.default_locale]" do
160
+ it "should create the key for I18n.default_locale with the value from yml files" do
161
+ Interpret::Translation.update
162
+ translation = Interpret::Translation.locale('en').find_by_key("new_key")
163
+ translation.value.should == "This new key should be created with this english text"
164
+ end
165
+
166
+ it "should not create an entry for a key in a language that do not have it" do
167
+ Interpret::Translation.update
168
+ Interpret::Translation.locale('es').find_by_key("new_key_in_en").should be_nil
169
+ end
170
+
171
+ it "should look for that key in other languages from yml files and create the existing ones." do
172
+ Interpret::Translation.update
173
+ translation = Interpret::Translation.locale('es').find_by_key("new_key")
174
+ translation.value.should == "Esta nueva clave debe crearse con este texto en español"
175
+ end
176
+ end
177
+
178
+ context "when a key exists in both yml files and database [for I18n.default_locale]" do
179
+ it "should not override the contents of the existing database translations" do
180
+ Interpret::Translation.update
181
+ translation = Interpret::Translation.locale('en').find_by_key("p1")
182
+ translation.value.should == "Hello world!"
183
+ end
184
+
185
+ it "should check if there is a language (other than I18n.default_locale) for which that key is new, and create the entry." do
186
+ Interpret::Translation.update
187
+ translation = Interpret::Translation.locale('es').find_by_key("p1").should_not be_nil
188
+ end
189
+ end
59
190
  end
60
191
 
61
192
  describe ".dump" do
62
- pending
193
+ it "should dump all contents from yml files into database" do
194
+ # Initial database state
195
+ file2db(en_yml)
196
+ file2db(es_yml)
197
+
198
+ Dir.stub!(:"[]").and_return(['/path/to/en.yml', '/path/to/es.yml'])
199
+ YAML.should_receive(:load_file).twice.and_return(YAML.load(new_en_yml), YAML.load(new_es_yml))
200
+ Interpret::Translation.dump
201
+
202
+ # We use export to check for the existing database contents, which is
203
+ # also tested in this spec file
204
+ en_trans = Interpret::Translation.locale('en').all
205
+ Interpret::Translation.export(en_trans).should == YAML.load(new_en_yml)
206
+
207
+ es_trans = Interpret::Translation.locale('es').all
208
+ Interpret::Translation.export(es_trans).should == YAML.load(new_es_yml)
209
+ end
63
210
  end
64
211
 
65
- describe ".update" do
66
- pending
212
+ describe ".import" do
213
+ before do
214
+ @file = new_en_yml
215
+ end
216
+
217
+ it "should dump the contents for the given file into database" do
218
+ file2db(en_yml)
219
+ @file.stub!(:content_type).and_return("text/plain")
220
+ Interpret::Translation.import(@file)
221
+
222
+ en_trans = Interpret::Translation.locale('en').all
223
+ Interpret::Translation.export(en_trans).should == YAML.load(new_en_yml)
224
+ end
225
+
226
+ it "should not modify the database contents for other languages" do
227
+ Interpret::Translation.delete_all
228
+ file2db(en_yml)
229
+ file2db(es_yml)
230
+
231
+ @file.stub!(:content_type).and_return("text/plain")
232
+ Interpret::Translation.import(@file)
233
+
234
+ es_trans = Interpret::Translation.locale('es').all
235
+ Interpret::Translation.export(es_trans).should == YAML.load(es_yml)
236
+ end
67
237
  end
68
238
  end
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interpret
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 1
8
- - 2
9
- version: 0.1.2
4
+ prerelease:
5
+ version: 0.1.3
10
6
  platform: ruby
11
7
  authors:
12
8
  - Roger Campos
@@ -14,7 +10,7 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2011-02-15 00:00:00 +01:00
13
+ date: 2011-02-18 00:00:00 +01:00
18
14
  default_executable:
19
15
  dependencies:
20
16
  - !ruby/object:Gem::Dependency
@@ -25,10 +21,6 @@ dependencies:
25
21
  requirements:
26
22
  - - ~>
27
23
  - !ruby/object:Gem::Version
28
- segments:
29
- - 3
30
- - 0
31
- - 3
32
24
  version: 3.0.3
33
25
  type: :runtime
34
26
  version_requirements: *id001
@@ -40,10 +32,6 @@ dependencies:
40
32
  requirements:
41
33
  - - ~>
42
34
  - !ruby/object:Gem::Version
43
- segments:
44
- - 0
45
- - 5
46
- - 0
47
35
  version: 0.5.0
48
36
  type: :runtime
49
37
  version_requirements: *id002
@@ -55,8 +43,6 @@ dependencies:
55
43
  requirements:
56
44
  - - ">="
57
45
  - !ruby/object:Gem::Version
58
- segments:
59
- - 0
60
46
  version: "0"
61
47
  type: :runtime
62
48
  version_requirements: *id003
@@ -68,10 +54,6 @@ dependencies:
68
54
  requirements:
69
55
  - - ">="
70
56
  - !ruby/object:Gem::Version
71
- segments:
72
- - 0
73
- - 30
74
- - 0
75
57
  version: 0.30.0
76
58
  type: :runtime
77
59
  version_requirements: *id004
@@ -83,10 +65,6 @@ dependencies:
83
65
  requirements:
84
66
  - - ">="
85
67
  - !ruby/object:Gem::Version
86
- segments:
87
- - 3
88
- - 0
89
- - pre2
90
68
  version: 3.0.pre2
91
69
  type: :runtime
92
70
  version_requirements: *id005
@@ -98,27 +76,31 @@ dependencies:
98
76
  requirements:
99
77
  - - ">="
100
78
  - !ruby/object:Gem::Version
101
- segments:
102
- - 0
103
- - 1
104
- - 7
105
79
  version: 0.1.7
106
80
  type: :runtime
107
81
  version_requirements: *id006
108
82
  - !ruby/object:Gem::Dependency
109
- name: rspec-rails
83
+ name: lazyhash
110
84
  prerelease: false
111
85
  requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 0.1.1
91
+ type: :runtime
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
94
+ name: rspec-rails
95
+ prerelease: false
96
+ requirement: &id008 !ruby/object:Gem::Requirement
112
97
  none: false
113
98
  requirements:
114
99
  - - ~>
115
100
  - !ruby/object:Gem::Version
116
- segments:
117
- - 2
118
- - 5
119
101
  version: "2.5"
120
102
  type: :development
121
- version_requirements: *id007
103
+ version_requirements: *id008
122
104
  description: Manage your app translations with an i18n active_record backend
123
105
  email:
124
106
  - roger@itnig.net
@@ -157,7 +139,6 @@ files:
157
139
  - lib/interpret/capistrano.rb
158
140
  - lib/interpret/engine.rb
159
141
  - lib/interpret/helpers.rb
160
- - lib/interpret/lazy_hash.rb
161
142
  - lib/interpret/logger.rb
162
143
  - lib/interpret/version.rb
163
144
  - lib/tasks/interpret.rake
@@ -235,21 +216,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
235
216
  requirements:
236
217
  - - ">="
237
218
  - !ruby/object:Gem::Version
238
- segments:
239
- - 0
240
219
  version: "0"
241
220
  required_rubygems_version: !ruby/object:Gem::Requirement
242
221
  none: false
243
222
  requirements:
244
223
  - - ">="
245
224
  - !ruby/object:Gem::Version
246
- segments:
247
- - 0
248
225
  version: "0"
249
226
  requirements: []
250
227
 
251
228
  rubyforge_project: interpret
252
- rubygems_version: 1.3.7
229
+ rubygems_version: 1.5.2
253
230
  signing_key:
254
231
  specification_version: 3
255
232
  summary: Manage your app translations with an i18n active_record backend
@@ -1,21 +0,0 @@
1
- # Gist from: https://gist.github.com/745617
2
- module LazyHash
3
- class << self
4
- def lazy_add(hash, key, value, pre = nil)
5
- skeys = key.split(".")
6
- f = skeys.shift
7
- if skeys.empty?
8
- pre.nil? ? hash.send("[]=", f, value) : pre.send("[]=", f, value)
9
- else
10
- pre = pre.nil? ? hash.send("[]", f) : pre.send("[]", f)
11
- lazy_add(hash, skeys.join("."), value, pre)
12
- end
13
- end
14
-
15
- def build_hash
16
- lazy = lambda { |h,k| h[k] = Hash.new(&lazy) }
17
- Hash.new(&lazy)
18
- end
19
- end
20
- end
21
-