exvo_globalize 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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