wovnrb 2.2.0 → 2.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21db13334fd0ceefeba7a6d0f23a13c035d8ca2e97796f2c5342659369b4a5d9
4
- data.tar.gz: 6453345eb832513563decad6050d3b44d2f100c203c8e0f3f9cbbd8d6cc833b5
3
+ metadata.gz: b1d7702d09e87b697371b1c5609040910fa9383d55a05ebac5d1ae668b04013c
4
+ data.tar.gz: c18162741b2cbb82137687cd6b9a0176cc576cae8230c3720d4ebd19df065656
5
5
  SHA512:
6
- metadata.gz: a43841cb1cd9a2fcda906663b8c8a5d46e751e37d202591f42d7eea17603df6523e8eca82538c49b7db20e9d3b1d8fd51d5e64e482ee71422384f109f699eef3
7
- data.tar.gz: 6e87c0aa31e2b6853d295e600ba6fef63beb3cc5d0154a872e19a51cdc3a6d7828b1bc7ea21346dfee72c888576885256d11c84e1085608e2a5c55e693312359
6
+ metadata.gz: 3285cbeb773a4415e82fd8cc06b375d4e3e0adea37c2e026699f401cd2692a67972aef40513a209b1d39686fb52664bc3964d6d8be69088d716b960f9e8e1ef3
7
+ data.tar.gz: ea6c7b83a2a2b6c16c5d7d5310ec17e021a4e1b87524cc60de3794230890aeb8742205e7197ba9bbd74d492092523f59bcd48f576440729e6a014919d11f4313
data/README.md CHANGED
@@ -82,6 +82,7 @@ lang_param_name | | 'wovn'
82
82
  query | | []
83
83
  ignore_class | | []
84
84
  translate_fragment | | true
85
+ ignore_paths | | []
85
86
 
86
87
  ### 2.1. project_token
87
88
 
@@ -161,6 +162,17 @@ This option allows to disable translating partial HTML content. By default,
161
162
  partial HTML content is translated but no widget snippet is added. Set
162
163
  `translate_fragment` to `false` to prevent translating partial HTML content.
163
164
 
165
+ ### 2.9 ignore_paths
166
+
167
+ This parameter tells WOVN.rb to not localize content withing given directories.
168
+
169
+ The directories given will only be matched against the beginning of the URL path.
170
+
171
+ For instance, if you want to not localize the admin directory of your website, you should add the following to you WOVN.rb configuration.
172
+ ```
173
+ 'ignore_paths' => ['/admin/']
174
+ ```
175
+
164
176
  ## 3. Contributing
165
177
 
166
178
  1. Fork it ( https://github.com/WOVNio/wovnrb/fork )
@@ -32,14 +32,21 @@ module Wovnrb
32
32
 
33
33
  @env = env
34
34
  headers = Headers.new(env, @store.settings)
35
+ default_lang = @store.settings['default_lang']
35
36
  return @app.call(env) if @store.settings['test_mode'] && @store.settings['test_url'] != headers.url
36
37
 
37
38
  # redirect if the path is set to the default language (for SEO purposes)
38
- if headers.path_lang == @store.settings['default_lang']
39
- redirect_headers = headers.redirect(@store.settings['default_lang'])
39
+ if headers.path_lang == default_lang
40
+ redirect_headers = headers.redirect(default_lang)
40
41
  return [307, redirect_headers, ['']]
41
42
  end
42
43
 
44
+ # if path containing language code is ignored, do nothing
45
+ if headers.lang_code != default_lang && ignore_path?(headers.unmasked_pathname_without_trailing_slash)
46
+ status, res_headers, body = @app.call(env)
47
+
48
+ return output(headers, status, res_headers, body)
49
+ end
43
50
  # pass to application
44
51
  status, res_headers, body = @app.call(headers.request_out)
45
52
 
@@ -51,7 +58,7 @@ module Wovnrb
51
58
  return output(headers, status, res_headers, body) if request.params['wovn_disable'] == true
52
59
 
53
60
  @store.settings.update_dynamic_settings!(request.params)
54
- return output(headers, status, res_headers, body) if @store.settings['ignore_globs'].any? { |g| g.match?(headers.pathname) }
61
+ return output(headers, status, res_headers, body) if ignore_path?(headers.pathname)
55
62
 
56
63
  body = switch_lang(headers, body) unless status.to_s =~ /^1|302/
57
64
 
@@ -105,6 +112,10 @@ module Wovnrb
105
112
  !html_body.xpath('//html[@wovn-ignore]').empty?
106
113
  end
107
114
 
115
+ def ignore_path?(path)
116
+ @store.settings['ignore_globs'].ignore?(path)
117
+ end
118
+
108
119
  # Checks if a given HTML body is an Accelerated Mobile Page (AMP).
109
120
  # To do so, it looks at the required attributes for the HTML tag:
110
121
  # https://www.ampproject.org/docs/tutorials/create/basic_markup.
@@ -39,7 +39,6 @@ module Wovnrb
39
39
  else
40
40
  @env['HTTP_HOST']
41
41
  end
42
- @env['wovnrb.target_lang'] = lang_code
43
42
  @host = settings['url_pattern'] == 'subdomain' ? remove_lang(@host, lang_code) : @host
44
43
  @pathname, @query = @env['REQUEST_URI'].split('?')
45
44
  @pathname = settings['url_pattern'] == 'path' ? remove_lang(@pathname, lang_code) : @pathname
@@ -66,6 +65,10 @@ module Wovnrb
66
65
  @redis_url = "#{@host}#{@pathname}#{@query}"
67
66
  end
68
67
 
68
+ def unmasked_pathname_without_trailing_slash
69
+ @unmasked_pathname.chomp('/')
70
+ end
71
+
69
72
  # Get the language code of the current request
70
73
  #
71
74
  # @return [String] The lang code of the current page
@@ -150,6 +153,7 @@ module Wovnrb
150
153
  end
151
154
 
152
155
  def request_out(_def_lang = @settings['default_lang'])
156
+ @env['wovnrb.target_lang'] = lang_code
153
157
  case @settings['url_pattern']
154
158
  when 'query'
155
159
  @env['REQUEST_URI'] = remove_lang(@env['REQUEST_URI']) if @env.key?('REQUEST_URI')
@@ -203,19 +207,21 @@ module Wovnrb
203
207
  r = Regexp.new('//' + @host)
204
208
  lang_code = Store.instance.settings['custom_lang_aliases'][self.lang_code] || self.lang_code
205
209
  if lang_code != @settings['default_lang'] && headers.key?('Location') && headers['Location'] =~ r
206
- case @settings['url_pattern']
207
- when 'query'
208
- headers['Location'] += if headers['Location'] =~ /\?/
209
- '&'
210
- else
211
- '?'
212
- end
213
- headers['Location'] += "#{@settings['lang_param_name']}=#{lang_code}"
214
- when 'subdomain'
215
- headers['Location'] = headers['Location'].sub(/\/\/([^.]+)/, '//' + lang_code + '.\1')
216
- # when 'path'
217
- else
218
- headers['Location'] = headers['Location'].sub(/(\/\/[^\/]+)/, '\1/' + lang_code)
210
+ unless @settings['ignore_globs'].ignore?(headers['Location'])
211
+ case @settings['url_pattern']
212
+ when 'query'
213
+ headers['Location'] += if headers['Location'] =~ /\?/
214
+ '&'
215
+ else
216
+ '?'
217
+ end
218
+ headers['Location'] += "#{@settings['lang_param_name']}=#{lang_code}"
219
+ when 'subdomain'
220
+ headers['Location'] = headers['Location'].sub(/\/\/([^.]+)/, '//' + lang_code + '.\1')
221
+ # when 'path'
222
+ else
223
+ headers['Location'] = headers['Location'].sub(/(\/\/[^\/]+)/, '\1/' + lang_code)
224
+ end
219
225
  end
220
226
  end
221
227
  headers
@@ -7,7 +7,7 @@ module Wovnrb
7
7
 
8
8
  def [](key)
9
9
  return @dynamic_settings[key] if @dynamic_settings.key?(key)
10
- return ignore_globs if key == 'ignore_globs'
10
+ return IgnoreGlobsWrapper.new(ignore_globs) if key == 'ignore_globs'
11
11
 
12
12
  super(key)
13
13
  end
@@ -35,5 +35,13 @@ module Wovnrb
35
35
  'wovn_token' => 'project_token',
36
36
  'wovn_ignore_paths' => 'ignore_paths'
37
37
  }.freeze
38
+
39
+ class IgnoreGlobsWrapper < Array
40
+ def ignore?(uri)
41
+ path = Addressable::URI.parse(uri).path
42
+
43
+ any? { |glob| glob.match?(path) }
44
+ end
45
+ end
38
46
  end
39
47
  end
@@ -1,3 +1,3 @@
1
1
  module Wovnrb
2
- VERSION = '2.2.0'.freeze
2
+ VERSION = '2.2.1'.freeze
3
3
  end
@@ -279,6 +279,49 @@ module Wovnrb
279
279
  assert_equal('http://wovn.io/test', env['HTTP_REFERER'])
280
280
  end
281
281
 
282
+ def test_out_should_add_lang_code_to_redirection
283
+ sut = Wovnrb::Headers.new(
284
+ Wovnrb.get_env(
285
+ 'SERVER_NAME' => 'wovn.io',
286
+ 'REQUEST_URI' => '/ja/test',
287
+ 'HTTP_REFERER' => 'http://wovn.io/ja/test'
288
+ ),
289
+ Wovnrb.get_settings(
290
+ 'default_lang' => 'en',
291
+ 'supported_langs' => %w[en ja],
292
+ 'url_pattern' => 'path',
293
+ 'url_pattern_reg' => '/(?<lang>[^/.?]+)'
294
+ )
295
+ )
296
+ headers = {
297
+ 'Location' => 'http://wovn.io/'
298
+ }
299
+
300
+ assert_equal('http://wovn.io/ja/', sut.out(headers)['Location'])
301
+ end
302
+
303
+ def test_out_should_not_add_lang_code_to_ignored_redirection
304
+ sut = Wovnrb::Headers.new(
305
+ Wovnrb.get_env(
306
+ 'SERVER_NAME' => 'wovn.io',
307
+ 'REQUEST_URI' => '/ja/test',
308
+ 'HTTP_REFERER' => 'http://wovn.io/ja/test'
309
+ ),
310
+ Wovnrb.get_settings(
311
+ 'default_lang' => 'en',
312
+ 'supported_langs' => %w[en ja],
313
+ 'url_pattern' => 'path',
314
+ 'url_pattern_reg' => '/(?<lang>[^/.?]+)',
315
+ 'ignore_paths' => ['/static/']
316
+ )
317
+ )
318
+ headers = {
319
+ 'Location' => 'http://wovn.io/static/'
320
+ }
321
+
322
+ assert_equal('http://wovn.io/static/', sut.out(headers)['Location'])
323
+ end
324
+
282
325
  def test_out_http_referer_subdomain_with_custom_lang_code
283
326
  Store.instance.update_settings('custom_lang_aliases' => { 'ja' => 'staging-ja' })
284
327
  h = Wovnrb::Headers.new(
@@ -108,8 +108,119 @@ HTML
108
108
  assert_switch_lang('en', 'ja', body, body, false)
109
109
  end
110
110
 
111
+ def test_call_without_path_ignored_should_change_environment
112
+ settings = {
113
+ 'project_token' => '123456',
114
+ 'url_pattern' => 'path',
115
+ 'default_lang' => 'ja',
116
+ 'supported_langs' => %w[ja en],
117
+ 'ignore_paths' => ['/en/ignored']
118
+ }
119
+ env = {
120
+ 'rack.input' => '',
121
+ 'rack.request.query_string' => '',
122
+ 'rack.request.query_hash' => {},
123
+ 'HTTP_HOST' => 'test.com',
124
+ 'REQUEST_URI' => '/en/not_ignored',
125
+ 'PATH_INFO' => '/en/not_ignored'
126
+ }
127
+
128
+ assert_call_affects_env(settings, env, mock_api: true, affected: true)
129
+ end
130
+
131
+ def test_call_with_path_ignored_with_language_code_should_change_environment
132
+ settings = {
133
+ 'project_token' => '123456',
134
+ 'url_pattern' => 'path',
135
+ 'default_lang' => 'ja',
136
+ 'supported_langs' => %w[ja en],
137
+ 'ignore_paths' => ['/en/ignored']
138
+ }
139
+ env = {
140
+ 'rack.input' => '',
141
+ 'rack.request.query_string' => '',
142
+ 'rack.request.query_hash' => {},
143
+ 'HTTP_HOST' => 'test.com',
144
+ 'REQUEST_URI' => '/ignored',
145
+ 'PATH_INFO' => '/ignored'
146
+ }
147
+
148
+ assert_call_affects_env(settings, env, mock_api: false, affected: true)
149
+ end
150
+
151
+ def test_call_with_path_ignored_without_language_code_should_change_environment
152
+ settings = {
153
+ 'project_token' => '123456',
154
+ 'url_pattern' => 'path',
155
+ 'default_lang' => 'ja',
156
+ 'supported_langs' => %w[ja en],
157
+ 'ignore_paths' => ['/ignored']
158
+ }
159
+ env = {
160
+ 'rack.input' => '',
161
+ 'rack.request.query_string' => '',
162
+ 'rack.request.query_hash' => {},
163
+ 'HTTP_HOST' => 'test.com',
164
+ 'REQUEST_URI' => '/en/ignored',
165
+ 'PATH_INFO' => '/en/ignored'
166
+ }
167
+
168
+ assert_call_affects_env(settings, env, mock_api: false, affected: true)
169
+ end
170
+
171
+ def test_call_with_path_ignored_without_language_code_in_original_language_should_change_environment
172
+ settings = {
173
+ 'project_token' => '123456',
174
+ 'url_pattern' => 'path',
175
+ 'default_lang' => 'ja',
176
+ 'supported_langs' => %w[ja en],
177
+ 'ignore_paths' => ['/ignored']
178
+ }
179
+ env = {
180
+ 'rack.input' => '',
181
+ 'rack.request.query_string' => '',
182
+ 'rack.request.query_hash' => {},
183
+ 'HTTP_HOST' => 'test.com',
184
+ 'REQUEST_URI' => '/ignored',
185
+ 'PATH_INFO' => '/ignored'
186
+ }
187
+
188
+ assert_call_affects_env(settings, env, mock_api: false, affected: true)
189
+ end
190
+
191
+ def test_call_with_path_ignored_should_not_change_environment
192
+ settings = {
193
+ 'project_token' => '123456',
194
+ 'url_pattern' => 'path',
195
+ 'default_lang' => 'ja',
196
+ 'supported_langs' => %w[ja en],
197
+ 'ignore_paths' => ['/en/ignored']
198
+ }
199
+ env = {
200
+ 'rack.input' => '',
201
+ 'rack.request.query_string' => '',
202
+ 'rack.request.query_hash' => {},
203
+ 'HTTP_HOST' => 'test.com',
204
+ 'REQUEST_URI' => '/en/ignored',
205
+ 'PATH_INFO' => '/en/ignored'
206
+ }
207
+
208
+ assert_call_affects_env(settings, env, mock_api: false, affected: false)
209
+ end
210
+
111
211
  private
112
212
 
213
+ def assert_call_affects_env(settings, env, mock_api:, affected:)
214
+ app_mock = get_app
215
+ sut = Wovnrb::Interceptor.new(app_mock, settings)
216
+ unaffected_env = env
217
+
218
+ mock_translation_api_response('', '') if mock_api
219
+ sut.call(env.clone)
220
+
221
+ assert_equal(unaffected_env != app_mock.env, affected)
222
+ end
223
+
113
224
  def assert_switch_lang(original_lang, target_lang, body, expected_body, api_expected = true)
114
225
  subdomain = target_lang == original_lang ? '' : "#{target_lang}."
115
226
  interceptor = Wovnrb::Interceptor.new(get_app)
@@ -160,7 +271,7 @@ HTML
160
271
  end
161
272
 
162
273
  class RackMock
163
- attr_accessor :params
274
+ attr_accessor :params, :env
164
275
 
165
276
  def initialize(opts = {})
166
277
  @params = {}
@@ -59,7 +59,8 @@ module Wovnrb
59
59
  end
60
60
 
61
61
  def get_settings(options = {})
62
- settings = {}
62
+ settings = Wovnrb::Store.default_settings
63
+
63
64
  settings['project_token'] = 'OHYx9'
64
65
  settings['url_pattern'] = 'path'
65
66
  settings['url_pattern_reg'] = '/(?<lang>[^/.?]+)'
@@ -68,7 +69,8 @@ module Wovnrb
68
69
  settings['api_url'] = 'http://localhost/v0/values'
69
70
  settings['default_lang'] = 'en'
70
71
  settings['supported_langs'] = %w[en ja]
71
- settings.merge(options)
72
+
73
+ Wovnrb::Settings.new.merge(settings.merge(options))
72
74
  end
73
75
 
74
76
  def get_env(options = {})
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wovnrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Sandford
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-07-11 00:00:00.000000000 Z
12
+ date: 2019-10-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport