localeapp 0.6.2 → 0.6.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.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # Version 0.6.3
2
+
3
+ * Pulling translations now completely replaces the contents of the yaml
4
+ files instead of selectively updating certain translations.
5
+
1
6
  # Version 0.6.2
2
7
 
3
8
  * Fix bug updating synchronization files that caused polling_interval to be ignored
@@ -16,8 +16,8 @@ When /^I have a valid project on localeapp\.com but an incorrect api key "([^"]*
16
16
  end
17
17
 
18
18
  When /^I have a translations on localeapp\.com for the project with api key "([^"]*)"$/ do |api_key|
19
- uri = "https://api.localeapp.com/v1/projects/#{api_key}/translations.yml"
20
- body = valid_translation_data.to_yaml
19
+ uri = "https://api.localeapp.com/v1/projects/#{api_key}/translations/all.yml"
20
+ body = valid_export_data.to_yaml
21
21
  add_fake_web_uri(:get, uri, ['200', 'OK'], body)
22
22
  end
23
23
 
@@ -8,7 +8,7 @@ module Localeapp
8
8
  @output.puts ""
9
9
 
10
10
  @output.puts "Fetching translations:"
11
- api_call :translations,
11
+ api_call :export,
12
12
  :success => :update_backend,
13
13
  :failure => :report_failure,
14
14
  :max_connection_attempts => 3
@@ -17,7 +17,7 @@ module Localeapp
17
17
  def update_backend(response)
18
18
  @output.puts "Success!"
19
19
  @output.puts "Updating backend:"
20
- Localeapp.updater.update(Localeapp.load_yaml(response))
20
+ Localeapp.updater.dump(Localeapp.load_yaml(response))
21
21
  @output.puts "Success!"
22
22
  Localeapp.poller.write_synchronization_data!(Time.now.to_i, Time.now.to_i)
23
23
  end
@@ -26,6 +26,17 @@ module Localeapp
26
26
  [:post, translations_url(options)]
27
27
  end
28
28
 
29
+ def export_endpoint(options = {})
30
+ [:get, export_url(options)]
31
+ end
32
+
33
+ def export_url(options = {})
34
+ options[:format] ||= 'yml'
35
+ url = http_scheme.build(base_options.merge(:path => export_path(options[:format])))
36
+ url.query = options[:query].map { |k,v| "#{k}=#{v}" }.join('&') if options[:query]
37
+ url.to_s
38
+ end
39
+
29
40
  def missing_translations_endpoint(options = {})
30
41
  [:post, missing_translations_url(options)]
31
42
  end
@@ -74,6 +85,12 @@ module Localeapp
74
85
  path
75
86
  end
76
87
 
88
+ def export_path(format = nil)
89
+ path = project_path << '/translations/all'
90
+ path << ".#{format}" if format
91
+ path
92
+ end
93
+
77
94
  def missing_translations_path(format = nil)
78
95
  path = project_path << '/translations/missing'
79
96
  path << ".#{format}" if format
@@ -31,6 +31,15 @@ module Localeapp
31
31
  end
32
32
  end
33
33
 
34
+ def dump(data)
35
+ data.each do |locale, translations|
36
+ filename = File.join(Localeapp.configuration.translation_data_directory, "#{locale}.yml")
37
+ atomic_write(filename) do |file|
38
+ file.write generate_yaml({locale => translations})
39
+ end
40
+ end
41
+ end
42
+
34
43
  private
35
44
 
36
45
  def generate_yaml(translations)
@@ -1,3 +1,3 @@
1
1
  module Localeapp
2
- VERSION = "0.6.2"
2
+ VERSION = "0.6.3"
3
3
  end
@@ -10,7 +10,7 @@ describe Localeapp::CLI::Pull, "#execute" do
10
10
  it "makes the api call to the translations endpoint" do
11
11
  with_configuration do
12
12
  @puller.should_receive(:api_call).with(
13
- :translations,
13
+ :export,
14
14
  :success => :update_backend,
15
15
  :failure => :report_failure,
16
16
  :max_connection_attempts => 3
@@ -30,14 +30,14 @@ describe Localeapp::CLI::Pull, "#update_backend(response)" do
30
30
  it "calls the updater" do
31
31
  with_configuration do
32
32
  Localeapp.poller.stub!(:write_synchronization_data!)
33
- Localeapp.updater.should_receive(:update).with(['test data'])
33
+ Localeapp.updater.should_receive(:dump).with(['test data'])
34
34
  @puller.update_backend(@test_data)
35
35
  end
36
36
  end
37
37
 
38
38
  it "writes the synchronization data" do
39
39
  with_configuration do
40
- Localeapp.updater.stub!(:update)
40
+ Localeapp.updater.stub!(:dump)
41
41
  Localeapp.poller.should_receive(:write_synchronization_data!)
42
42
  @puller.update_backend(@test_data)
43
43
  end
@@ -82,6 +82,38 @@ describe Localeapp::Routes do
82
82
  end
83
83
  end
84
84
 
85
+ describe "#export_url" do
86
+ it "it extends the project_url and defaults to yml" do
87
+ with_configuration(@config) do
88
+ @routes.export_url.should == "https://test.host/v1/projects/API_KEY/translations/all.yml"
89
+ end
90
+ end
91
+
92
+ it "adds query parameters on to the url" do
93
+ with_configuration(@config) do
94
+ url = @routes.export_url(:query => {:updated_at => '2011-04-19', :foo => :bar})
95
+ url.should match(/\?.*updated_at=2011-04-19/)
96
+ url.should match(/\?.*foo=bar/)
97
+ end
98
+ end
99
+
100
+ it "can be changed to another content type" do
101
+ with_configuration(@config) do
102
+ @routes.export_url(:format => :json).should == 'https://test.host/v1/projects/API_KEY/translations/all.json'
103
+ end
104
+ end
105
+ end
106
+
107
+ describe "#export_endpoint(options = {})" do
108
+ it "returns :get and the export url for the options" do
109
+ with_configuration(@config) do
110
+ options = { :foo => :bar }
111
+ @routes.should_receive(:export_url).with(options).and_return('url')
112
+ @routes.export_endpoint(options).should == [:get, 'url']
113
+ end
114
+ end
115
+ end
116
+
85
117
  describe "#missing_translations_endpoint(options = {})" do
86
118
  it "returns :post and the missing_translations url for the options" do
87
119
  with_configuration(@config) do
@@ -182,3 +182,65 @@ JA
182
182
  mode.to_s(8)[3, 3].should == "644"
183
183
  end
184
184
  end
185
+
186
+ describe Localeapp::Updater, ".dump(data)" do
187
+ before(:each) do
188
+ @yml_dir = Dir.mktmpdir
189
+ Dir.glob(File.join(File.dirname(__FILE__), '..', 'fixtures', '*.yml')).each { |f| FileUtils.cp f, @yml_dir }
190
+ with_configuration(:translation_data_directory => @yml_dir) do
191
+ @updater = Localeapp::Updater.new
192
+ end
193
+ end
194
+
195
+ after(:each) do
196
+ FileUtils.rm_rf @yml_dir
197
+ end
198
+
199
+ def do_dump(data)
200
+ @updater.dump(data)
201
+ end
202
+
203
+ it "replaces the content of an existing yml file" do
204
+ filepath = File.join(@yml_dir, 'en.yml')
205
+ content = lambda { File.read(filepath) }
206
+ if defined? Psych
207
+ expect { do_dump({'en' => {'updated' => 'content'}}) }.to change(content, :call).to <<-EN
208
+ en:
209
+ updated: content
210
+ EN
211
+ else
212
+ expect { do_dump({'en' => {'updated' => 'content'}}) }.to change(content, :call).to <<-EN
213
+ en:
214
+ updated: content
215
+ EN
216
+ end
217
+ end
218
+
219
+ it "creates a new yml file if an unknown locale is passed" do
220
+ do_dump({'ja' => { 'foo' => 'bar'} })
221
+ if defined? Psych
222
+ File.read(File.join(@yml_dir, 'ja.yml')).should == <<-JA
223
+ ja:
224
+ foo: bar
225
+ JA
226
+ else
227
+ File.read(File.join(@yml_dir, 'ja.yml')).should == <<-JA
228
+ ja:
229
+ foo: bar
230
+ JA
231
+ end
232
+ end
233
+
234
+ it "doesn't change a yml file's permissions" do
235
+ filepath = File.join(@yml_dir, 'en.yml')
236
+ File.chmod(0777, filepath)
237
+ permissions = lambda { File.stat(filepath).mode.to_s(8) }
238
+ expect { do_dump({'en' => { 'foo' => 'bar'} }) }.to_not change(permissions, :call)
239
+ end
240
+
241
+ it "creates new yml files chmodded with 644" do
242
+ do_dump({'ja' => { 'foo' => 'bar'} })
243
+ mode = File.stat(File.join(@yml_dir, 'ja.yml')).mode # octal
244
+ mode.to_s(8)[3, 3].should == "644"
245
+ end
246
+ end
@@ -30,4 +30,14 @@ module LocaleappIntegrationData
30
30
  'locales' => %w{en es}
31
31
  }
32
32
  end
33
+
34
+ def valid_export_data
35
+ { 'en' => {
36
+ 'foo' => {'monkey' => 'hello', 'night' => 'night'}
37
+ },
38
+ 'es' => {
39
+ 'foo' => {'monkey' => 'hola', 'night' => 'noche'}
40
+ }
41
+ }
42
+ end
33
43
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: localeapp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
4
+ hash: 1
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 2
10
- version: 0.6.2
9
+ - 3
10
+ version: 0.6.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Christopher Dell
@@ -16,12 +16,13 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2012-10-15 00:00:00 Z
19
+ date: 2012-10-19 00:00:00 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: i18n
23
+ type: :runtime
23
24
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
26
  none: false
26
27
  requirements:
27
28
  - - ">="
@@ -30,12 +31,12 @@ dependencies:
30
31
  segments:
31
32
  - 0
32
33
  version: "0"
33
- type: :runtime
34
- version_requirements: *id001
34
+ requirement: *id001
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: json
37
+ type: :runtime
37
38
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
39
40
  none: false
40
41
  requirements:
41
42
  - - ">="
@@ -44,12 +45,12 @@ dependencies:
44
45
  segments:
45
46
  - 0
46
47
  version: "0"
47
- type: :runtime
48
- version_requirements: *id002
48
+ requirement: *id002
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: rest-client
51
+ type: :runtime
51
52
  prerelease: false
52
- requirement: &id003 !ruby/object:Gem::Requirement
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
53
54
  none: false
54
55
  requirements:
55
56
  - - ">="
@@ -58,12 +59,12 @@ dependencies:
58
59
  segments:
59
60
  - 0
60
61
  version: "0"
61
- type: :runtime
62
- version_requirements: *id003
62
+ requirement: *id003
63
63
  - !ruby/object:Gem::Dependency
64
64
  name: ya2yaml
65
+ type: :runtime
65
66
  prerelease: false
66
- requirement: &id004 !ruby/object:Gem::Requirement
67
+ version_requirements: &id004 !ruby/object:Gem::Requirement
67
68
  none: false
68
69
  requirements:
69
70
  - - ">="
@@ -72,12 +73,12 @@ dependencies:
72
73
  segments:
73
74
  - 0
74
75
  version: "0"
75
- type: :runtime
76
- version_requirements: *id004
76
+ requirement: *id004
77
77
  - !ruby/object:Gem::Dependency
78
78
  name: gli
79
+ type: :runtime
79
80
  prerelease: false
80
- requirement: &id005 !ruby/object:Gem::Requirement
81
+ version_requirements: &id005 !ruby/object:Gem::Requirement
81
82
  none: false
82
83
  requirements:
83
84
  - - ">="
@@ -86,12 +87,12 @@ dependencies:
86
87
  segments:
87
88
  - 0
88
89
  version: "0"
89
- type: :runtime
90
- version_requirements: *id005
90
+ requirement: *id005
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rake
93
+ type: :development
93
94
  prerelease: false
94
- requirement: &id006 !ruby/object:Gem::Requirement
95
+ version_requirements: &id006 !ruby/object:Gem::Requirement
95
96
  none: false
96
97
  requirements:
97
98
  - - ">="
@@ -100,12 +101,12 @@ dependencies:
100
101
  segments:
101
102
  - 0
102
103
  version: "0"
103
- type: :development
104
- version_requirements: *id006
104
+ requirement: *id006
105
105
  - !ruby/object:Gem::Dependency
106
106
  name: rspec
107
+ type: :development
107
108
  prerelease: false
108
- requirement: &id007 !ruby/object:Gem::Requirement
109
+ version_requirements: &id007 !ruby/object:Gem::Requirement
109
110
  none: false
110
111
  requirements:
111
112
  - - "="
@@ -116,12 +117,12 @@ dependencies:
116
117
  - 11
117
118
  - 0
118
119
  version: 2.11.0
119
- type: :development
120
- version_requirements: *id007
120
+ requirement: *id007
121
121
  - !ruby/object:Gem::Dependency
122
122
  name: yard
123
+ type: :development
123
124
  prerelease: false
124
- requirement: &id008 !ruby/object:Gem::Requirement
125
+ version_requirements: &id008 !ruby/object:Gem::Requirement
125
126
  none: false
126
127
  requirements:
127
128
  - - "="
@@ -132,12 +133,12 @@ dependencies:
132
133
  - 6
133
134
  - 7
134
135
  version: 0.6.7
135
- type: :development
136
- version_requirements: *id008
136
+ requirement: *id008
137
137
  - !ruby/object:Gem::Dependency
138
138
  name: RedCloth
139
+ type: :development
139
140
  prerelease: false
140
- requirement: &id009 !ruby/object:Gem::Requirement
141
+ version_requirements: &id009 !ruby/object:Gem::Requirement
141
142
  none: false
142
143
  requirements:
143
144
  - - "="
@@ -148,12 +149,12 @@ dependencies:
148
149
  - 2
149
150
  - 9
150
151
  version: 4.2.9
151
- type: :development
152
- version_requirements: *id009
152
+ requirement: *id009
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: aruba
155
+ type: :development
155
156
  prerelease: false
156
- requirement: &id010 !ruby/object:Gem::Requirement
157
+ version_requirements: &id010 !ruby/object:Gem::Requirement
157
158
  none: false
158
159
  requirements:
159
160
  - - "="
@@ -164,12 +165,12 @@ dependencies:
164
165
  - 4
165
166
  - 11
166
167
  version: 0.4.11
167
- type: :development
168
- version_requirements: *id010
168
+ requirement: *id010
169
169
  - !ruby/object:Gem::Dependency
170
170
  name: fakeweb
171
+ type: :development
171
172
  prerelease: false
172
- requirement: &id011 !ruby/object:Gem::Requirement
173
+ version_requirements: &id011 !ruby/object:Gem::Requirement
173
174
  none: false
174
175
  requirements:
175
176
  - - "="
@@ -180,8 +181,7 @@ dependencies:
180
181
  - 3
181
182
  - 0
182
183
  version: 1.3.0
183
- type: :development
184
- version_requirements: *id011
184
+ requirement: *id011
185
185
  description: Synchronizes i18n translation keys and content with localeapp.com so you don't have to manage translations by hand.
186
186
  email:
187
187
  - chris@tigrish.com
@@ -300,7 +300,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
300
300
  requirements: []
301
301
 
302
302
  rubyforge_project: localeapp
303
- rubygems_version: 1.8.24
303
+ rubygems_version: 1.8.6
304
304
  signing_key:
305
305
  specification_version: 3
306
306
  summary: Easy i18n translation management with localeapp.com