exvo_globalize 0.0.2 → 0.1.0

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Exvo Globalize
2
2
 
3
- This plugin lets you make use of the Globalize app (http://globalize.exvo.com/)
3
+ This gem lets you make use of the Globalize app (http://globalize.exvo.com/)
4
4
  to handle the translation of your Rails app into multiple languages.
5
5
 
6
6
 
@@ -31,7 +31,7 @@ $ rails generate exvo_globalize
31
31
  ```
32
32
 
33
33
 
34
- Is is advised to have your `/globalize/` actions behind an authorization barrier (besides `/globalize/translations.json`, which is by default publicly accessible).
34
+ It is advised to have your `/globalize/` actions behind an authorization barrier (besides `/globalize/translations.json`, which is by default publicly accessible).
35
35
  Create a `config/initializers/exvo_globalize.rb` file with similar contents:
36
36
 
37
37
  ```ruby
@@ -44,5 +44,27 @@ I18n::Backend::GlobalizeStore.authenticator = proc {
44
44
  `authenticate_user!` and `require_admin!` are just exemplary authorization actions.
45
45
 
46
46
 
47
+ ## Globalize integration
48
+
49
+ In order to fully integrate this gem with Globalize, after installing it you need to register your application (http://globalize.exvo.com/) and order some translations (Globalize should automatically detect the gem installation and should let you choose the JSON translations option).
50
+
51
+ By default a link between your application and Globalize is established by using `request.host` by the gem. If your application’s main DNS record is a CNAME (as is the common case when using Heroku), you can set your application’s domain in the `config/initializers/exvo_globalize.rb` file:
52
+
53
+ ```ruby
54
+ ENV['GLOBALIZE_REQUEST_HOST'] = 'yourawesomewebapp.com'
55
+ ```
56
+
57
+ Note that this host must be the same as the one you have used when registering your application at Globalize. Otherwise updating translations will not be possible.
58
+
59
+
60
+ When Globalize translations are ready, you need to manually update them at your application by going to this url:
61
+
62
+ ```
63
+ http://yourawesomewebapp.com/globalize/translations
64
+ ```
65
+
66
+ And pressing `Update translations`.
67
+
68
+
47
69
 
48
70
  Copyright © 2011 Exvo.com Development BV, released under the MIT license
@@ -1,28 +1,41 @@
1
1
  class GlobalizeTranslationsController < ApplicationController
2
2
 
3
- before_filter :globalize_translations_authenticator, :except => [:index]
3
+ before_filter :globalize_translations_authenticator
4
+ before_filter :set_globalize_app
4
5
 
5
- # get :index as JSON should not require authentication
6
- before_filter(:only => :index) do |controller|
7
- globalize_translations_authenticator unless controller.request.format.json?
8
- end
9
-
10
- layout false
6
+ layout 'exvo_globalize'
11
7
 
12
8
  respond_to :html, :json
13
9
 
14
- def index
10
+ def show
15
11
  # returns {"default_locale":"en","pl":{"hello.world":"Witaj \u015bwiecie","hello.earth":"Witaj ziemio"},"en":{"hello.world":"Hello world","hello.earth":"Hello Earth"}}
16
12
  @translations = I18n.backend.available_translations.merge({ :default_locale => I18n.default_locale })
17
13
  respond_with @translations
18
14
  end
19
15
 
16
+ def update
17
+ if I18n.backend.store_flatten_translations(@globalize_app.fetch_translations)
18
+ flash.now[:notice] = 'Translations updated'
19
+ else
20
+ flash.now[:alert] = 'There was a problem while updating translations'
21
+ end
22
+ render :show
23
+ end
24
+
20
25
  private
21
26
 
22
27
  def globalize_translations_authenticator
28
+ # get :show as JSON does not require authentication
29
+ return if params[:action].to_s == 'show' and request.format.json?
30
+
31
+ # call custom authenticator method if available
23
32
  if I18n::Backend::GlobalizeStore.authenticator && I18n::Backend::GlobalizeStore.authenticator.respond_to?(:call)
24
33
  I18n::Backend::GlobalizeStore.authenticator.bind(self).call
25
34
  end
26
35
  end
27
36
 
37
+ def set_globalize_app
38
+ @globalize_app ||= GlobalizeApp.new(ENV["GLOBALIZE_REQUEST_HOST"] || request.host)
39
+ end
40
+
28
41
  end
@@ -0,0 +1,5 @@
1
+ - if flash[:notice].present?
2
+ %p.notice= flash[:notice]
3
+
4
+ - if flash[:alert].present?
5
+ %p.alert= flash[:alert]
@@ -0,0 +1,7 @@
1
+ = render 'flash_messages'
2
+
3
+ - if @globalize_app.updated_translations_available?
4
+ %p Would you like to update the translations from Globalize?
5
+
6
+ = form_tag globalize_translations_path, :method => :put do
7
+ = submit_tag 'Update translations'
@@ -0,0 +1,7 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title= "Exvo Globalize translations"
5
+ %meta{ :name => "robots", :content => "noindex, nofollow" }
6
+ %body
7
+ = yield
data/config/routes.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  Rails.application.routes.draw do
2
2
  scope '/globalize' do
3
- resources :translations, :only => [:index], :as => 'globalize_translations', :controller => 'globalize_translations' do
4
- put :update_many, :on => :collection
3
+ resource :translations, :only => [:show, :update], :as => 'globalize_translations', :controller => 'globalize_translations' do
5
4
  end
6
5
  end
7
6
  end
@@ -21,6 +21,8 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_dependency 'rails', ['>= 3.0.0']
23
23
  s.add_dependency 'i18n', ['>= 0.5.0']
24
+ s.add_dependency 'haml', ['>= 3.0.0']
25
+ s.add_dependency 'httparty', ['>= 0.6.1']
24
26
  s.add_development_dependency 'guard', ['>= 0.5.0']
25
27
  s.add_development_dependency 'guard-rspec', ['>= 0.4.0']
26
28
  s.add_development_dependency 'sqlite3', ['>= 1.3']
@@ -28,5 +30,6 @@ Gem::Specification.new do |s|
28
30
  s.add_development_dependency 'rspec-rails', ['>= 2.6']
29
31
  s.add_development_dependency 'factory_girl_rails', ['>= 1.1.0']
30
32
  s.add_development_dependency 'shoulda-matchers', ['>= 1.0.0.beta3']
33
+ s.add_development_dependency 'capybara', ['>= 1.0.0']
31
34
  s.add_development_dependency 'json', ['>= 1.5.1']
32
35
  end
@@ -2,6 +2,9 @@ require "exvo_globalize/version"
2
2
  require "exvo_globalize/backend/chain"
3
3
  require "exvo_globalize/backend/globalize_store"
4
4
  require "exvo_globalize/backend/simple"
5
+ require 'exvo_globalize/globalize_app'
6
+ require 'haml'
7
+ require 'httparty'
5
8
 
6
9
  # Make it a Rails engine
7
10
  module ExvoGlobalize
@@ -20,8 +20,28 @@ module I18n
20
20
  translate_without_fallback(I18n.default_locale, key, default_options)
21
21
  end
22
22
  end
23
-
24
23
  alias_method_chain :translate, :fallback
24
+
25
+ # stores a whole Hash of flattened translations
26
+ def store_flatten_translations(translations_hash)
27
+ return false if translations_hash.blank?
28
+
29
+ translations_hash.reject { |key, value| key.to_sym == :default_locale }.each do |locale, translations|
30
+ next if translations.blank?
31
+
32
+ translations.each do |key, value|
33
+ store_flatten_translation(locale, key, value)
34
+ end
35
+ end
36
+ end
37
+
38
+ # pass-through for the `store_flatten_translation()` method to the GlobalizeStore
39
+ # so that I18n.backend.store_flatten_translation() works
40
+ def store_flatten_translation(*args)
41
+ backends.each do |backend|
42
+ return backend.send(:store_flatten_translation, *args) if backend.respond_to?(:store_flatten_translation)
43
+ end
44
+ end
25
45
  end
26
46
 
27
47
  include Implementation
@@ -0,0 +1,32 @@
1
+ class GlobalizeApp
2
+
3
+ def initialize(request_host)
4
+ @request_host = request_host
5
+ end
6
+
7
+ def updated_translations_available?
8
+ # TODO fetch_translations and sha1 compare them with database stored sha1 of previously fetched translations
9
+ true
10
+ end
11
+
12
+ # returns a Hash with translations: { "en" => { "intro" => "Introduction" } }
13
+ def fetch_translations
14
+ resp = HTTParty.get(translations_uri)
15
+ if resp.response.is_a?(Net::HTTPOK)
16
+ resp.parsed_response
17
+ else
18
+ {}
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def globalize_host
25
+ Rails.env.production? ? "globalize.exvo.com" : "globalize.exvo.co"
26
+ end
27
+
28
+ def translations_uri
29
+ "http://#{globalize_host}/translations.json?host=#{@request_host}"
30
+ end
31
+
32
+ end
@@ -1,3 +1,3 @@
1
1
  module ExvoGlobalize
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -7,11 +7,11 @@ describe GlobalizeTranslationsController do
7
7
 
8
8
  context "JSON" do
9
9
 
10
- describe "GET :index" do
10
+ describe "GET :show" do
11
11
 
12
12
  let(:translations) do
13
- i18n_title # needed so there is some data in the database before a call to get :index
14
- get :index, :format => :json
13
+ i18n_title # needed so there is some data in the database before a call to get :show
14
+ get :show, :format => :json
15
15
  JSON.parse(response.body)
16
16
  end
17
17
 
@@ -33,11 +33,11 @@ describe GlobalizeTranslationsController do
33
33
 
34
34
  context "HTML" do
35
35
 
36
- describe "GET :index" do
36
+ describe "GET :show" do
37
37
 
38
38
  context "without being logged in" do
39
39
  before do
40
- get :index, :format => :html
40
+ get :show, :format => :html
41
41
  end
42
42
 
43
43
  it { should respond_with(:forbidden) }
@@ -46,7 +46,7 @@ describe GlobalizeTranslationsController do
46
46
  context "when being logged in as admin" do
47
47
  before do
48
48
  controller.stub!(:require_admin).and_return(true)
49
- get :index, :format => :html
49
+ get :show, :format => :html
50
50
  end
51
51
 
52
52
  it { should respond_with(:success) }
@@ -54,6 +54,34 @@ describe GlobalizeTranslationsController do
54
54
 
55
55
  end
56
56
 
57
+ describe "PUT :update" do
58
+
59
+ let(:intro) { "Introduction" }
60
+ let(:translations) { { :en => { :intro => intro } } }
61
+
62
+ render_views
63
+ let(:page) { Capybara::Node::Simple.new(@response.body) }
64
+
65
+ before do
66
+ controller.stub!(:require_admin).and_return(true)
67
+ GlobalizeApp.any_instance.stub(:fetch_translations) { translations }
68
+ put :update, :format => :html
69
+ end
70
+
71
+ it "updates the translations" do
72
+ I18n.t(:intro).should eq(intro)
73
+ end
74
+
75
+ it "sets a flash notice" do
76
+ flash[:notice].should_not be_empty
77
+ end
78
+
79
+ it "displays a flash notice" do
80
+ page.should have_selector('p.notice')
81
+ end
82
+
83
+ end
84
+
57
85
  end
58
86
 
59
87
  end
@@ -23,17 +23,22 @@ describe ExvoGlobalize do
23
23
  context "translation storage" do
24
24
  let(:hello_world) { 'Hello world' }
25
25
  let(:hello_earth) { 'Hello Earth' }
26
- let(:globalize_store_backend) { I18n.backend.backends.detect { |backend| backend.is_a?(I18n::Backend::GlobalizeStore) } }
27
26
 
28
- it "stores nested translations in the GlobalizeStore backend" do
29
- globalize_store_backend.store_translations(I18n.locale, { :hello => { :world => hello_world} })
27
+ it "stores a flatten translations hash" do
28
+ I18n.backend.store_flatten_translations({ :en => { 'hello.world' => hello_world, 'hello.earth' => hello_earth } })
30
29
  I18n.translate('hello.world').should eql(hello_world)
30
+ I18n.translate('hello.earth').should eql(hello_earth)
31
31
  end
32
32
 
33
- it "stores flatten translation in the GlobalizeStore backend" do
34
- globalize_store_backend.store_flatten_translation(I18n.locale, 'hello.earth', hello_earth)
33
+ it "stores a flatten translation" do
34
+ I18n.backend.store_flatten_translation(I18n.locale, 'hello.earth', hello_earth)
35
35
  I18n.translate(:earth, :scope => [:hello]).should eql(hello_earth)
36
36
  end
37
+
38
+ it "stores a nested translation" do
39
+ I18n.backend.store_translations(I18n.locale, { :hello => { :world => hello_world } })
40
+ I18n.translate('hello.world').should eql(hello_world)
41
+ end
37
42
  end
38
43
 
39
44
  it "falls back to the YAML file if the translation is missing in the GlobalizeStore backend (db)" do
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 2
10
- version: 0.0.2
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Pawe\xC5\x82 Go\xC5\x9Bcicki"
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-04 00:00:00 +02:00
18
+ date: 2011-08-05 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -51,9 +51,41 @@ dependencies:
51
51
  type: :runtime
52
52
  version_requirements: *id002
53
53
  - !ruby/object:Gem::Dependency
54
- name: guard
54
+ name: haml
55
55
  prerelease: false
56
56
  requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 7
62
+ segments:
63
+ - 3
64
+ - 0
65
+ - 0
66
+ version: 3.0.0
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 5
78
+ segments:
79
+ - 0
80
+ - 6
81
+ - 1
82
+ version: 0.6.1
83
+ type: :runtime
84
+ version_requirements: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ name: guard
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
57
89
  none: false
58
90
  requirements:
59
91
  - - ">="
@@ -65,11 +97,11 @@ dependencies:
65
97
  - 0
66
98
  version: 0.5.0
67
99
  type: :development
68
- version_requirements: *id003
100
+ version_requirements: *id005
69
101
  - !ruby/object:Gem::Dependency
70
102
  name: guard-rspec
71
103
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
104
+ requirement: &id006 !ruby/object:Gem::Requirement
73
105
  none: false
74
106
  requirements:
75
107
  - - ">="
@@ -81,11 +113,11 @@ dependencies:
81
113
  - 0
82
114
  version: 0.4.0
83
115
  type: :development
84
- version_requirements: *id004
116
+ version_requirements: *id006
85
117
  - !ruby/object:Gem::Dependency
86
118
  name: sqlite3
87
119
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
120
+ requirement: &id007 !ruby/object:Gem::Requirement
89
121
  none: false
90
122
  requirements:
91
123
  - - ">="
@@ -96,11 +128,11 @@ dependencies:
96
128
  - 3
97
129
  version: "1.3"
98
130
  type: :development
99
- version_requirements: *id005
131
+ version_requirements: *id007
100
132
  - !ruby/object:Gem::Dependency
101
133
  name: rspec
102
134
  prerelease: false
103
- requirement: &id006 !ruby/object:Gem::Requirement
135
+ requirement: &id008 !ruby/object:Gem::Requirement
104
136
  none: false
105
137
  requirements:
106
138
  - - ">="
@@ -111,11 +143,11 @@ dependencies:
111
143
  - 6
112
144
  version: "2.6"
113
145
  type: :development
114
- version_requirements: *id006
146
+ version_requirements: *id008
115
147
  - !ruby/object:Gem::Dependency
116
148
  name: rspec-rails
117
149
  prerelease: false
118
- requirement: &id007 !ruby/object:Gem::Requirement
150
+ requirement: &id009 !ruby/object:Gem::Requirement
119
151
  none: false
120
152
  requirements:
121
153
  - - ">="
@@ -126,11 +158,11 @@ dependencies:
126
158
  - 6
127
159
  version: "2.6"
128
160
  type: :development
129
- version_requirements: *id007
161
+ version_requirements: *id009
130
162
  - !ruby/object:Gem::Dependency
131
163
  name: factory_girl_rails
132
164
  prerelease: false
133
- requirement: &id008 !ruby/object:Gem::Requirement
165
+ requirement: &id010 !ruby/object:Gem::Requirement
134
166
  none: false
135
167
  requirements:
136
168
  - - ">="
@@ -142,11 +174,11 @@ dependencies:
142
174
  - 0
143
175
  version: 1.1.0
144
176
  type: :development
145
- version_requirements: *id008
177
+ version_requirements: *id010
146
178
  - !ruby/object:Gem::Dependency
147
179
  name: shoulda-matchers
148
180
  prerelease: false
149
- requirement: &id009 !ruby/object:Gem::Requirement
181
+ requirement: &id011 !ruby/object:Gem::Requirement
150
182
  none: false
151
183
  requirements:
152
184
  - - ">="
@@ -160,11 +192,27 @@ dependencies:
160
192
  - 3
161
193
  version: 1.0.0.beta3
162
194
  type: :development
163
- version_requirements: *id009
195
+ version_requirements: *id011
196
+ - !ruby/object:Gem::Dependency
197
+ name: capybara
198
+ prerelease: false
199
+ requirement: &id012 !ruby/object:Gem::Requirement
200
+ none: false
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ hash: 23
205
+ segments:
206
+ - 1
207
+ - 0
208
+ - 0
209
+ version: 1.0.0
210
+ type: :development
211
+ version_requirements: *id012
164
212
  - !ruby/object:Gem::Dependency
165
213
  name: json
166
214
  prerelease: false
167
- requirement: &id010 !ruby/object:Gem::Requirement
215
+ requirement: &id013 !ruby/object:Gem::Requirement
168
216
  none: false
169
217
  requirements:
170
218
  - - ">="
@@ -176,7 +224,7 @@ dependencies:
176
224
  - 1
177
225
  version: 1.5.1
178
226
  type: :development
179
- version_requirements: *id010
227
+ version_requirements: *id013
180
228
  description: It exposes `/globalize/translations.json` with JSON of all translations in the app
181
229
  email:
182
230
  - pawel.goscicki@gmail.com
@@ -195,7 +243,9 @@ files:
195
243
  - Rakefile
196
244
  - app/controllers/globalize_translations_controller.rb
197
245
  - app/models/globalize_translation.rb
198
- - app/views/globalize_translations/index.html
246
+ - app/views/globalize_translations/_flash_messages.html.haml
247
+ - app/views/globalize_translations/show.html.haml
248
+ - app/views/layouts/exvo_globalize.html.haml
199
249
  - config/routes.rb
200
250
  - exvo_globalize.gemspec
201
251
  - lib/exvo_globalize.rb
@@ -203,6 +253,7 @@ files:
203
253
  - lib/exvo_globalize/backend/globalize_store.rb
204
254
  - lib/exvo_globalize/backend/simple.rb
205
255
  - lib/exvo_globalize/engine.rb
256
+ - lib/exvo_globalize/globalize_app.rb
206
257
  - lib/exvo_globalize/version.rb
207
258
  - lib/generators/exvo_globalize/exvo_globalize_generator.rb
208
259
  - lib/generators/exvo_globalize/templates/migration.rb
File without changes