wovnrb 3.8.0 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 315ed96f41cbfa7d479fe520e53fe2e740ac5a597b51a30326d9ed24c4da40c1
4
- data.tar.gz: 51d39551f5594c266c33f84613235cf1f8ac88c351ea1468601dd0f73b257bdd
3
+ metadata.gz: a0283acd73cab4171aefb1bb183832a0536a2c88fd4c62ac3fef0befee06a2a2
4
+ data.tar.gz: b8eebae5190864b55c02f53c30e166ec955ce08c19fd7866185a7ec50df54c3c
5
5
  SHA512:
6
- metadata.gz: 649285b3c4a0ed37c842315f21f3fe73d8fe2b097296ff4df5d0a74479982db526a3b41428b32a568a7b0b987deeeda3c9230b3421b302d3f6a2999caec978d9
7
- data.tar.gz: 75157d25a342cd57d6eb917774177774521b6a34db62049be1da8350459677121091bccbfd9a79672b475a8a6f560ac4b9282178e33a2204654177a50d3f3e0f
6
+ metadata.gz: c1b6e6f940f60e059d0b2527108660f43e17d82ca6b57ec7a4f2ec127062482494bc684e7c01bd86453d776dbe53159f19f2984a59a373e3b95920bfd1c78ee0
7
+ data.tar.gz: 9851f866c7df91b312f99790b165407432e6d77f6fa95774cee4016ef3ec35f7e7e0d291396dd20c48a420aaa6771d8196e53641eef53fc3abdd24cb96aa80f8
data/README.en.md CHANGED
@@ -90,6 +90,7 @@ compress_api_requests | | true
90
90
  api_timeout_seconds | | 1.0
91
91
  api_timeout_search_engine_bots | | 5.0
92
92
  translate_canonical_tag | | true
93
+ custom_domain_langs | | {}
93
94
 
94
95
  ### 2.1. project_token
95
96
 
@@ -123,19 +124,20 @@ Japanese, then you should use the following setting:
123
124
 
124
125
  ### 2.4. url_pattern
125
126
 
126
- The Library works in the Ruby Application by adding new URLs to be translated. You can set the type of url with the `url_pattern` parameter. There are 3 types that can be set.
127
+ The Library works in the Ruby Application by adding new URLs to be translated. You can set the type of url with the `url_pattern` parameter. There are 4 types that can be set.
127
128
 
128
- parameters | Translated page's URL | Notes
129
- ----------- | ------------------------------- | -------
130
- 'path' | https://wovn.io/ja/contact | Default Value. If no settings have been set, url_pattern defaults to this value.
131
- 'subdomain' | https://ja.wovn.io/contact | DNS settings must be set.
132
- 'query' | https://wovn.io/contact?wovn=ja | The least amount of changes to the application required to complete setup.
129
+ parameters | Translated page's URL | Notes
130
+ --------------- | -------------------------------- | -------
131
+ 'path' | https://wovn.io/ja/contact | Default Value. If no settings have been set, url_pattern defaults to this value.
132
+ 'subdomain' | https://ja.wovn.io/contact | DNS settings must be set.
133
+ 'query' | https://wovn.io/contact?wovn=ja | The least amount of changes to the application required to complete setup.
134
+ 'custom_domain' | Depends on `custom_domain_langs` | See [Section 2.15.](#215-custom_domain_langs).
133
135
 
134
136
  ※ The following is an example of a URL that has been translated by the library using the above URLs.
135
137
 
136
138
  https://wovn.io/contact
137
139
 
138
- ### 2.5 lang_param_name
140
+ ### 2.5. lang_param_name
139
141
  This parameter is only valid for when `url_pattern` is set to `'query'`.
140
142
 
141
143
  It allows you to set the query parameter name for declaring the language of the
@@ -169,7 +171,7 @@ This option allows to disable translating partial HTML content. By default,
169
171
  partial HTML content is translated but no widget snippet is added. Set
170
172
  `translate_fragment` to `false` to prevent translating partial HTML content.
171
173
 
172
- ### 2.9 ignore_paths
174
+ ### 2.9. ignore_paths
173
175
 
174
176
  This parameter tells WOVN.rb to not localize content withing given directories.
175
177
 
@@ -180,7 +182,7 @@ For instance, if you want to not localize the admin directory of your website, y
180
182
  'ignore_paths' => ['/admin/']
181
183
  ```
182
184
 
183
- ### 2.10 install_middleware
185
+ ### 2.10. install_middleware
184
186
 
185
187
  When using WOVN.rb in a Rails environment, this parameter controls whether the WOVN.rb middleware will be automatically installed or not.
186
188
 
@@ -201,20 +203,47 @@ WOVN.rb needs to be added after any compression middleware.
201
203
  }
202
204
  ```
203
205
 
204
- ### 2.11 compress_api_requests
206
+ ### 2.11. compress_api_requests
205
207
 
206
208
  By default, requests to the translation API will be sent with gzip compression. Set to false to disable compression.
207
209
 
208
- ### 2.12 api_timeout_seconds
209
- Configures the amount of time in seconds wovnrb will wait for the translation API for a response before the
210
+ ### 2.12. api_timeout_seconds
211
+ Configures the amount of time in seconds wovnrb will wait for the translation API for a response before the
210
212
  request is considered timed-out. This setting defaults to `1.0`.
211
213
 
212
- ### 2.13 api_timeout_search_engine_bots
214
+ ### 2.13. api_timeout_search_engine_bots
213
215
  Similar to `api_timeout_seconds`, this timeout setting is applied when handling requests made by search engine bots.
214
216
  Currently, bots from Google, Yahoo, Bing, Yandex, DuckDuckGo and Baidu are supported. This setting
215
217
  defaults to `5.0`.
216
218
 
217
- ### 2.14 translate_canonical_tag
219
+ ### 2.14. translate_canonical_tag
218
220
  Configures if wovnrb should automatically translate existing canonical tag in the HTML. When set to `true`, wovnrb
219
221
  will translate the canonical URL with the current language code according to your `url_pattern` setting.
220
- This setting defaults to `true`.
222
+ This setting defaults to `true`.
223
+
224
+ ### 2.15. custom_domain_langs
225
+ This parameter is valid and required, when `url_pattern` is `custom_domain`.
226
+ Set `custom_domain_langs` for all languages declared in `supported_langs`.
227
+
228
+ ```ruby
229
+ config.wovnrb = {
230
+ # ...
231
+ :custom_domain_langs => {
232
+ 'en' => { 'url' => 'wovn.io/en' },
233
+ 'ja' => { 'url' => 'ja.wovn.io' },
234
+ 'fr' => { 'url' => 'fr.wovn.co.jp' }
235
+ }
236
+ }
237
+ ```
238
+
239
+ For the example above, all request URLs that match `wovn.io/en/*` will be considered as requests in English language.
240
+ All request URLs other than the above that match `ja.wovn.io/*` will be considered as requests in Japanese langauge.
241
+ And, request URLs that match `fr.wovn.co.jp/*` will be considered as requests in French langauge.
242
+ With the above example configuration, the page `http://ja.wovn.io/about.html` in Japanese language will have the URL `http://wovn.io/en/about.html` as English language.
243
+
244
+ `custom_domain_langs` setting may only be used together with the `url_pattern = custom_domain` setting.
245
+
246
+ If this setting is used, each language declared in `supported_langs` must be given a custom domain.
247
+
248
+ The path declared for your original language must match the structure of the actual web server.
249
+ In other words, you cannot use this setting to change the request path of your content in original language.
data/README.ja.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  For English users: [English](README.en.md)
4
4
 
5
- WOVN.io Rubyライブラリは、翻訳を提供するためにWOVN.ioを利用したライブラリです。
5
+ WOVN.io Rubyライブラリは、翻訳を提供するためにWOVN.ioを利用したライブラリです。
6
6
  WOVN.io Ruby ライブラリは Rack Middleware としてパッケージ化されています。
7
7
 
8
8
  このドキュメントでは、WOVN.io Rubyをインストールするまでの手順や、セットアップ・設定の流れを説明しています。
@@ -11,7 +11,7 @@ WOVN.io Ruby ライブラリは Rack Middleware としてパッケージ化さ
11
11
 
12
12
  ### 1.1. WOVN.ioアカウントを作成
13
13
 
14
- WOVN.io Ruby Libraryを利用するには、WOVN.ioのアカウントが必要です。
14
+ WOVN.io Ruby Libraryを利用するには、WOVN.ioのアカウントが必要です。
15
15
  アカウントをお持ちでない方は、まずはWOVN.ioに登録してください。
16
16
 
17
17
  ### 1.2. ページ追加
@@ -20,7 +20,7 @@ WOVN.ioにログイン後、翻訳したいページを追加します。
20
20
 
21
21
  ### 1.3. Rubyアプリケーションの設定
22
22
 
23
- WOVN.io Ruby ライブラリを使用するには、以下の行を Ruby アプリケーションの Gemfile に挿入します。
23
+ WOVN.io Ruby ライブラリを使用するには、以下の行を Ruby アプリケーションの Gemfile に挿入します。
24
24
  WOVN.ioは現在、バージョン2.0.1以上をサポートしています。
25
25
 
26
26
  ```ruby
@@ -88,6 +88,7 @@ query | | []
88
88
  ignore_class | | []
89
89
  translate_fragment | | true
90
90
  ignore_paths | | []
91
+ custom_domain_langs| | {}
91
92
 
92
93
  ### 2.1. project_token
93
94
 
@@ -97,7 +98,7 @@ WOVN.ioアカウントのプロジェクトトークンを設定します。こ
97
98
 
98
99
  これはRubyアプリケーションのデフォルト言語を設定します。デフォルト値は英語('en')です。
99
100
 
100
- リクエストされたページで、デフォルトの言語パラメータが URL に含まれている場合、リクエストは翻訳前にリダイレクトされます。
101
+ リクエストされたページで、デフォルトの言語パラメータが URL に含まれている場合、リクエストは翻訳前にリダイレクトされます。
101
102
  このために `default_lang` パラメータを使用します。
102
103
 
103
104
  `default_lang` が 'en' に設定されている時に、以下のURLへのリクエストを受信した場合。
@@ -110,7 +111,7 @@ WOVN.ioアカウントのプロジェクトトークンを設定します。こ
110
111
 
111
112
  ### 2.3. supported_langs
112
113
 
113
- これは、ウェブサイトで使用されている言語(翻訳元を含む)をライブラリに伝えます。
114
+ これは、ウェブサイトで使用されている言語(翻訳元を含む)をライブラリに伝えます。
114
115
  この設定では、SEO(検索エンジン最適化)に必要なメタデータを挿入することができます。
115
116
 
116
117
  ウェブサイトが英語で、WOVN.ioを使って日本語にローカライズしている場合は、以下の設定にしてください。
@@ -121,32 +122,33 @@ WOVN.ioアカウントのプロジェクトトークンを設定します。こ
121
122
 
122
123
  ### 2.4. url_pattern
123
124
 
124
- ライブラリはRubyアプリケーションの中で、翻訳されるURLを新たに追加することで動作します。
125
- urlの種類は `url_pattern` パラメータで設定できます。設定できるタイプは3種類。
125
+ ライブラリはRubyアプリケーションの中で、翻訳されるURLを新たに追加することで動作します。
126
+ urlの種類は `url_pattern` パラメータで設定できます。設定できるタイプは4種類。
126
127
 
127
128
 
128
- パラメータ | 翻訳されたページのURL | 備考
129
- ----------- | ------------------------------- | -------
130
- 'path' | https://wovn.io/ja/contact | デフォルト値、何も設定されていない場合、 `url_pattern` のデフォルト値はこの値になります
131
- 'subdomain' | https://ja.wovn.io/contact | DNSの設定が必要です
132
- 'query' | https://wovn.io/contact?wovn=ja | セットアップを完了するために必要なアプリケーションへの変更の最小量
129
+ パラメータ | 翻訳されたページのURL | 備考
130
+ --------------- | ------------------------------- | -------
131
+ 'path' | https://wovn.io/ja/contact | デフォルト値、何も設定されていない場合、 `url_pattern` のデフォルト値はこの値になります
132
+ 'subdomain' | https://ja.wovn.io/contact | DNSの設定が必要です
133
+ 'query' | https://wovn.io/contact?wovn=ja | セットアップを完了するために必要なアプリケーションへの変更の最小量
134
+ 'custom_domain' | `custom_domain_langs`に設定された値 | [2.10.項](#210-custom_domain_langs)を参照してください。
133
135
 
134
136
  ※ 上記は、以下のURLを使用してライブラリが翻訳したURLの例です。
135
137
 
136
138
  https://wovn.io/contact
137
139
 
138
- ### 2.5 lang_param_name
140
+ ### 2.5. lang_param_name
139
141
 
140
142
  このパラメータは `url_pattern` が `query` に設定されている場合のみ有効です。
141
143
 
142
144
  ページの言語を指定するためのクエリパラメータ名を設定することができます。
143
145
 
144
- この設定のデフォルト値は `wovn` であり、翻訳された英語のページのURLが `https://my-website.com/index.php?wovn=en` という形式になります。
146
+ この設定のデフォルト値は `wovn` であり、翻訳された英語のページのURLが `https://my-website.com/index.php?wovn=en` という形式になります。
145
147
  代わりに `lang` に値を設定すると、URLの例は `https://my-website.com/index.php?lang=en` という形式になります。
146
148
 
147
149
  ### 2.6. query
148
150
 
149
- WOVN.ioは翻訳されたページを検索する際にクエリパラメータを無視します。
151
+ WOVN.ioは翻訳されたページを検索する際にクエリパラメータを無視します。
150
152
  翻訳ページのURLにクエリパラメータを追加したい場合は、`query` パラメータを設定する必要があります。(WOVN.ioも設定する必要があります)
151
153
 
152
154
  https://wovn.io/ja/contact?os=mac&keyboard=us
@@ -165,16 +167,45 @@ WOVN.ioは翻訳されたページを検索する際にクエリパラメータ
165
167
 
166
168
  ### 2.8. translate_fragment
167
169
 
168
- このオプションでは、部分的なHTMLコンテンツの翻訳を無効にすることができます。
169
- デフォルトでは、部分的なHTMLコンテンツは翻訳されますが、ウィジェットのスニペットは追加されません。
170
+ このオプションでは、部分的なHTMLコンテンツの翻訳を無効にすることができます。
171
+ デフォルトでは、部分的なHTMLコンテンツは翻訳されますが、ウィジェットのスニペットは追加されません。
170
172
  `translate_fragment` を `false` に設定すると、HTMLの一部が翻訳されないようになります。
171
173
 
172
- ### 2.9 ignore_paths
174
+ ### 2.9. ignore_paths
173
175
 
174
- このパラメータは、WOVN.rbが指定されたディレクトリ内のコンテンツをローカライズしないように指示します。
175
- 指定されたディレクトリは、URLパスの先頭にのみマッチします。
176
+ このパラメータは、WOVN.rbが指定されたディレクトリ内のコンテンツをローカライズしないように指示します。
177
+ 指定されたディレクトリは、URLパスの先頭にのみマッチします。
176
178
  例えば、ウェブサイトの管理者ディレクトリをローカライズしたくない場合は、WOVN.rbの設定に次のように追加します。
177
179
 
178
180
  ```
179
181
  'ignore_paths' => ['/admin/']
180
182
  ```
183
+
184
+ ### 2.10. custom_domain_langs
185
+
186
+ このパラメータは、カスタムドメイン言語パターンの場合(`url_pattern = custom_domain` が設定されている場合)のみ有効です。
187
+ カスタムドメイン言語パターン使用時は必須パラメータです。
188
+ `supported_langs` で設定した全ての言語と元言語に、必ず `custom_domain_langs` を設定してください。
189
+
190
+ ```ruby
191
+ config.wovnrb = {
192
+ # ...
193
+ :custom_domain_langs => {
194
+ 'en' => { 'url' => 'wovn.io/en' },
195
+ 'ja' => { 'url' => 'ja.wovn.io' },
196
+ 'fr' => { 'url' => 'fr.wovn.co.jp' }
197
+ }
198
+ }
199
+ ```
200
+
201
+ 上記の例では、 `wovn.io/en/*` にマッチするリクエストは英語のリクエストとして扱われます。
202
+ それ以外の `ja.wovn.io/*` にマッチするリクエストは日本語のリクエストとして扱われます。
203
+ また、 `fr.wovn.co.jp/*` にマッチするリクエストはフランス語のリクエストとして扱われます。
204
+ 例えば、`http://ja.wovn.io/about.html` の日本語ページは、`http://wovn.io/en/about.html` という英語ページのURLを持つことになります。
205
+
206
+ 必ず `url_pattern = custom_domain`と`custom_domain_langs` は一緒に使用してください。
207
+
208
+ `supported_langs` で宣言された各言語に `custom_domain_langs` を与えなければなりません。
209
+
210
+ オリジナル言語のために宣言されたパスは、実際のウェブサーバーの構造と一致していなければなりません。
211
+ この設定を使用して、オリジナル言語のリクエストパスを変更することはできません。
data/README.md CHANGED
@@ -1 +1 @@
1
- ./README.ja.md
1
+ README.ja.md
@@ -118,6 +118,7 @@ module Wovnrb
118
118
  }
119
119
 
120
120
  result['custom_lang_aliases'] = JSON.dump(custom_lang_aliases) unless custom_lang_aliases.empty?
121
+ result['custom_domain_langs'] = JSON.dump(custom_domain_langs) unless custom_domain_langs.empty?
121
122
 
122
123
  result
123
124
  end
@@ -162,6 +163,10 @@ module Wovnrb
162
163
  @store.settings['translate_canonical_tag']
163
164
  end
164
165
 
166
+ def custom_domain_langs
167
+ @store.custom_domain_langs.to_html_swapper_hash
168
+ end
169
+
165
170
  def page_url
166
171
  "#{@headers.protocol}://#{@headers.url}"
167
172
  end
@@ -0,0 +1,31 @@
1
+ module Wovnrb
2
+ # Represents a custom domain for a given language
3
+ class CustomDomainLang
4
+ attr_accessor :host, :path, :lang
5
+
6
+ def initialize(host, path, lang)
7
+ @host = host
8
+ @path = path.end_with?('/') ? path : "#{path}/"
9
+ @lang = lang
10
+ end
11
+
12
+ # @param uri [Addressable::URI]
13
+ def match?(parsed_uri)
14
+ @host.casecmp?(parsed_uri.host) && path_is_equal_or_subset_of?(@path, parsed_uri.path)
15
+ end
16
+
17
+ def host_and_path_without_trailing_slash
18
+ host_and_path = @host + @path
19
+ host_and_path.end_with?('/') ? host_and_path.delete_suffix('/') : host_and_path
20
+ end
21
+
22
+ private
23
+
24
+ def path_is_equal_or_subset_of?(path1, path2)
25
+ path1_segments = path1.split('/').reject(&:empty?)
26
+ path2_segments = path2.split('/').reject(&:empty?)
27
+
28
+ path1_segments == path2_segments.slice(0, path1_segments.length)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ require 'wovnrb/custom_domain/custom_domain_lang'
2
+
3
+ module Wovnrb
4
+ # Helper class for transforming actual domains to user-defined custom domains
5
+ class CustomDomainLangUrlHandler
6
+ class << self
7
+ def add_custom_domain_lang_to_absolute_url(absolute_url, target_lang, custom_domain_langs)
8
+ current_custom_domain = custom_domain_langs.custom_domain_lang_by_url(absolute_url)
9
+ new_lang_custom_domain = custom_domain_langs.custom_domain_lang_by_lang(target_lang)
10
+ change_to_new_custom_domain_lang(absolute_url, current_custom_domain, new_lang_custom_domain)
11
+ end
12
+
13
+ def change_to_new_custom_domain_lang(absolute_url, current_custom_domain, new_lang_custom_domain)
14
+ return absolute_url unless current_custom_domain.present? && new_lang_custom_domain.present?
15
+
16
+ current_host_and_path = current_custom_domain.host_and_path_without_trailing_slash
17
+ new_host_and_path = new_lang_custom_domain.host_and_path_without_trailing_slash
18
+
19
+ # ^(.*://|//)? 1: schema, e.g. https://
20
+ # (#{current_host_and_path}) 2: host and path, e.g. wovn.io/foo
21
+ # ((?:/|\?|#).*)?$ 3: other / query params, e.g. ?hello=world
22
+ regex = %r{^(.*://|//)?(#{current_host_and_path})((?:/|\?|#).*)?$}
23
+ absolute_url.gsub(regex) { "#{Regexp.last_match(1)}#{new_host_and_path}#{Regexp.last_match(3)}" }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,40 @@
1
+ require 'wovnrb/custom_domain/custom_domain_lang'
2
+
3
+ module Wovnrb
4
+ # Represents a list of custom domains with corresponding languages
5
+ class CustomDomainLangs
6
+ def initialize(setting)
7
+ @custom_domain_langs = setting.map do |lang_code, config|
8
+ parsed_uri = Addressable::URI.parse(add_protocol_if_needed(config['url']))
9
+ CustomDomainLang.new(parsed_uri.host, parsed_uri.path, lang_code)
10
+ end
11
+ end
12
+
13
+ def custom_domain_lang_by_lang(lang_code)
14
+ @custom_domain_langs.find { |c| c.lang == lang_code }
15
+ end
16
+
17
+ def custom_domain_lang_by_url(uri)
18
+ parsed_uri = Addressable::URI.parse(add_protocol_if_needed(uri))
19
+
20
+ # "/" path will naturally match every URL, so by comparing longest paths first we will get the best match
21
+ @custom_domain_langs
22
+ .sort_by { |c| -c.path.length }
23
+ .find { |c| c.match?(parsed_uri) }
24
+ end
25
+
26
+ def to_html_swapper_hash
27
+ result = {}
28
+ @custom_domain_langs.each do |custom_domain_lang|
29
+ result[custom_domain_lang.host_and_path_without_trailing_slash] = custom_domain_lang.lang
30
+ end
31
+ result
32
+ end
33
+
34
+ private
35
+
36
+ def add_protocol_if_needed(url)
37
+ url.match?(%r{https?://}) ? url : "http://#{url}"
38
+ end
39
+ end
40
+ end
@@ -1,3 +1,5 @@
1
+ require 'wovnrb/custom_domain/custom_domain_lang_url_handler'
2
+
1
3
  module Wovnrb
2
4
  class Headers
3
5
  attr_reader :unmasked_url, :url, :protocol, :unmasked_host, :host, :unmasked_pathname, :pathname, :pathname_with_trailing_slash_if_present
@@ -31,9 +33,9 @@ module Wovnrb
31
33
  else
32
34
  @env['HTTP_HOST']
33
35
  end
34
- @host = settings['url_pattern'] == 'subdomain' ? @url_lang_switcher.remove_lang_from_uri_component(@host, lang_code) : @host
36
+ @host = %w[subdomain custom_domain].include?(settings['url_pattern']) ? @url_lang_switcher.remove_lang_from_uri_component(@host, lang_code, self) : @host
35
37
  @pathname, @query = @env['REQUEST_URI'].split('?')
36
- @pathname = settings['url_pattern'] == 'path' ? @url_lang_switcher.remove_lang_from_uri_component(@pathname, lang_code) : @pathname
38
+ @pathname = %w[path custom_domain].include?(settings['url_pattern']) ? @url_lang_switcher.remove_lang_from_uri_component(@pathname, lang_code, self) : @pathname
37
39
  @query ||= ''
38
40
  @url = "#{@host}#{@pathname}#{(@query.empty? ? '' : '?') + @url_lang_switcher.remove_lang_from_uri_component(@query, lang_code)}"
39
41
  if settings['query'].empty?
@@ -68,7 +70,7 @@ module Wovnrb
68
70
  #
69
71
  # @return [String] The lang code of the current page
70
72
  def lang_code
71
- path_lang && !path_lang.empty? ? path_lang : @settings['default_lang']
73
+ url_language && !url_language.empty? ? url_language : @settings['default_lang']
72
74
  end
73
75
 
74
76
  # picks up language code from requested URL by using url_pattern_reg setting.
@@ -76,21 +78,27 @@ module Wovnrb
76
78
  # if you want examples, please see test/lib/headers_test.rb.
77
79
  #
78
80
  # @return [String] language code in requrested URL.
79
- def path_lang
80
- if @path_lang.nil?
81
- rp = Regexp.new(@settings['url_pattern_reg'])
82
- match = if @settings['use_proxy'] && @env.key?('HTTP_X_FORWARDED_HOST')
83
- "#{@env['HTTP_X_FORWARDED_HOST']}#{@env['REQUEST_URI']}".match(rp)
84
- else
85
- "#{@env['SERVER_NAME']}#{@env['REQUEST_URI']}".match(rp)
86
- end
87
- @path_lang = if match && match[:lang] && Lang.get_lang(match[:lang])
88
- Lang.get_code(match[:lang])
89
- else
90
- ''
91
- end
81
+ def url_language
82
+ if @url_language.nil?
83
+ full_url = if @settings['use_proxy'] && @env.key?('HTTP_X_FORWARDED_HOST')
84
+ "#{@env['HTTP_X_FORWARDED_HOST']}#{@env['REQUEST_URI']}"
85
+ else
86
+ "#{@env['SERVER_NAME']}#{@env['REQUEST_URI']}"
87
+ end
88
+
89
+ new_lang_code = nil
90
+ if @settings['url_pattern'] == 'custom_domain'
91
+ custom_domain_langs = Store.instance.custom_domain_langs
92
+ custom_domain = custom_domain_langs.custom_domain_lang_by_url(full_url)
93
+ new_lang_code = custom_domain.lang if custom_domain.present?
94
+ else
95
+ rp = Regexp.new(@settings['url_pattern_reg'])
96
+ match = full_url.match(rp)
97
+ new_lang_code = Lang.get_code(match[:lang]) if match && match[:lang] && Lang.get_lang(match[:lang])
98
+ end
99
+ @url_language = new_lang_code.presence || ''
92
100
  end
93
- @path_lang
101
+ @url_language
94
102
  end
95
103
 
96
104
  def redirect(lang)
@@ -109,51 +117,28 @@ module Wovnrb
109
117
  @url_lang_switcher.add_lang_code(url_with_scheme, lang, self)
110
118
  end
111
119
 
112
- def request_out(_def_lang = @settings['default_lang'])
120
+ def request_out
113
121
  @env['wovnrb.target_lang'] = lang_code
114
122
  case @settings['url_pattern']
115
123
  when 'query'
116
- @env['REQUEST_URI'] = @url_lang_switcher.remove_lang_from_uri_component(@env['REQUEST_URI'], lang_code) if @env.key?('REQUEST_URI')
117
- @env['QUERY_STRING'] = @url_lang_switcher.remove_lang_from_uri_component(@env['QUERY_STRING'], lang_code) if @env.key?('QUERY_STRING')
118
- @env['ORIGINAL_FULLPATH'] = @url_lang_switcher.remove_lang_from_uri_component(@env['ORIGINAL_FULLPATH'], lang_code) if @env.key?('ORIGINAL_FULLPATH')
124
+ remove_lang_from_query
119
125
  when 'subdomain'
120
- if @settings['use_proxy'] && @env.key?('HTTP_X_FORWARDED_HOST')
121
- @env['HTTP_X_FORWARDED_HOST'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_X_FORWARDED_HOST'], lang_code)
122
- else
123
- @env['HTTP_HOST'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_HOST'], lang_code)
124
- @env['SERVER_NAME'] = @url_lang_switcher.remove_lang_from_uri_component(@env['SERVER_NAME'], lang_code)
125
- end
126
- @env['HTTP_REFERER'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_REFERER'], lang_code) if @env.key?('HTTP_REFERER')
127
- # when 'path'
126
+ remove_lang_from_host
127
+ when 'custom_domain'
128
+ remove_lang_from_host
129
+ remove_lang_from_path
130
+ # when 'path'
128
131
  else
129
- @env['REQUEST_URI'] = @url_lang_switcher.remove_lang_from_uri_component(@env['REQUEST_URI'], lang_code)
130
- @env['REQUEST_PATH'] = @url_lang_switcher.remove_lang_from_uri_component(@env['REQUEST_PATH'], lang_code) if @env.key?('REQUEST_PATH')
131
- @env['PATH_INFO'] = @url_lang_switcher.remove_lang_from_uri_component(@env['PATH_INFO'], lang_code)
132
- @env['ORIGINAL_FULLPATH'] = @url_lang_switcher.remove_lang_from_uri_component(@env['ORIGINAL_FULLPATH'], lang_code) if @env.key?('ORIGINAL_FULLPATH')
133
- @env['HTTP_REFERER'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_REFERER'], lang_code) if @env.key?('HTTP_REFERER')
132
+ remove_lang_from_path
134
133
  end
135
134
  @env
136
135
  end
137
136
 
138
137
  def out(headers)
139
- r = Regexp.new("//#{@host}")
140
138
  lang_code = Store.instance.settings['custom_lang_aliases'][self.lang_code] || self.lang_code
141
- if lang_code != @settings['default_lang'] && headers.key?('Location') && headers['Location'] =~ r && !@settings['ignore_globs'].ignore?(headers['Location'])
142
- case @settings['url_pattern']
143
- when 'query'
144
- headers['Location'] += if /\?/.match?(headers['Location'])
145
- '&'
146
- else
147
- '?'
148
- end
149
- headers['Location'] += "#{@settings['lang_param_name']}=#{lang_code}"
150
- when 'subdomain'
151
- headers['Location'] = headers['Location'].sub(/\/\/([^.]+)/, "//#{lang_code}.\\1")
152
- # when 'path'
153
- else
154
- headers['Location'] = headers['Location'].sub(/(\/\/[^\/]+)/, "\\1/#{lang_code}")
155
- end
156
- end
139
+ should_add_lang_code = lang_code != @settings['default_lang'] && headers.key?('Location') && !@settings['ignore_globs'].ignore?(headers['Location'])
140
+
141
+ headers['Location'] = @url_lang_switcher.add_lang_code(headers['Location'], lang_code, self) if should_add_lang_code
157
142
  headers
158
143
  end
159
144
 
@@ -177,5 +162,31 @@ module Wovnrb
177
162
  absolute_path = absolute_path.starts_with?('/') ? absolute_path : URL.join_paths(dirname, absolute_path)
178
163
  URL.normalize_path_slash(path, absolute_path)
179
164
  end
165
+
166
+ private
167
+
168
+ def remove_lang_from_query
169
+ @env['REQUEST_URI'] = @url_lang_switcher.remove_lang_from_uri_component(@env['REQUEST_URI'], lang_code) if @env.key?('REQUEST_URI')
170
+ @env['QUERY_STRING'] = @url_lang_switcher.remove_lang_from_uri_component(@env['QUERY_STRING'], lang_code) if @env.key?('QUERY_STRING')
171
+ @env['ORIGINAL_FULLPATH'] = @url_lang_switcher.remove_lang_from_uri_component(@env['ORIGINAL_FULLPATH'], lang_code) if @env.key?('ORIGINAL_FULLPATH')
172
+ end
173
+
174
+ def remove_lang_from_host
175
+ if @settings['use_proxy'] && @env.key?('HTTP_X_FORWARDED_HOST')
176
+ @env['HTTP_X_FORWARDED_HOST'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_X_FORWARDED_HOST'], lang_code, self)
177
+ else
178
+ @env['HTTP_HOST'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_HOST'], lang_code, self)
179
+ @env['SERVER_NAME'] = @url_lang_switcher.remove_lang_from_uri_component(@env['SERVER_NAME'], lang_code, self)
180
+ end
181
+ @env['HTTP_REFERER'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_REFERER'], lang_code, self) if @env.key?('HTTP_REFERER')
182
+ end
183
+
184
+ def remove_lang_from_path
185
+ @env['REQUEST_URI'] = @url_lang_switcher.remove_lang_from_uri_component(@env['REQUEST_URI'], lang_code, self)
186
+ @env['REQUEST_PATH'] = @url_lang_switcher.remove_lang_from_uri_component(@env['REQUEST_PATH'], lang_code, self) if @env.key?('REQUEST_PATH')
187
+ @env['PATH_INFO'] = @url_lang_switcher.remove_lang_from_uri_component(@env['PATH_INFO'], lang_code, self)
188
+ @env['ORIGINAL_FULLPATH'] = @url_lang_switcher.remove_lang_from_uri_component(@env['ORIGINAL_FULLPATH'], lang_code, self) if @env.key?('ORIGINAL_FULLPATH')
189
+ @env['HTTP_REFERER'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_REFERER'], lang_code, self) if @env.key?('HTTP_REFERER')
190
+ end
180
191
  end
181
192
  end
data/lib/wovnrb/lang.rb CHANGED
@@ -250,7 +250,7 @@ module Wovnrb
250
250
  end
251
251
 
252
252
  def add_query_lang_code(href, lang_code, lang_param_name)
253
- query_separator = /\?/.match?(href) ? '&' : '?'
253
+ query_separator = href.include?('?') ? '&' : '?'
254
254
 
255
255
  href.sub(/(#|$)/, "#{query_separator}#{lang_param_name}=#{lang_code}\\1")
256
256
  end
@@ -15,12 +15,23 @@ module Wovnrb
15
15
  def build_api_compatible_html
16
16
  marker = HtmlReplaceMarker.new
17
17
  converted_html = replace_dom(marker)
18
-
18
+ converted_html = remove_backend_wovn_ignore_comments(converted_html, marker)
19
19
  [converted_html, marker]
20
20
  end
21
21
 
22
22
  private
23
23
 
24
+ def remove_backend_wovn_ignore_comments(html, marker)
25
+ backend_ignore_regex = /(<!--\s*backend-wovn-ignore\s*-->)(.+?)(<!--\s*\/backend-wovn-ignore\s*-->)/m
26
+ html.gsub(backend_ignore_regex) do |_match|
27
+ comment_start = Regexp.last_match(1)
28
+ ignored_content = Regexp.last_match(2)
29
+ comment_end = Regexp.last_match(3)
30
+ key = marker.add_comment_value(ignored_content)
31
+ comment_start + key + comment_end
32
+ end
33
+ end
34
+
24
35
  def html
25
36
  # Ensure a Content-Type declaration in the header. This mimics Nokogumbo
26
37
  # 1.5.0 default serialization behavior.
@@ -196,8 +207,9 @@ module Wovnrb
196
207
  url_pattern = @store.settings['url_pattern']
197
208
  lang_code_aliases_json = JSON.generate(@store.settings['custom_lang_aliases'])
198
209
  lang_param_name = @store.settings['lang_param_name']
210
+ custom_domain_langs = @store.custom_domain_langs.to_html_swapper_hash
199
211
 
200
- [
212
+ result = [
201
213
  "key=#{token}",
202
214
  'backend=true',
203
215
  "currentLang=#{current_lang}",
@@ -206,7 +218,9 @@ module Wovnrb
206
218
  "langCodeAliases=#{lang_code_aliases_json}",
207
219
  "langParamName=#{lang_param_name}",
208
220
  "version=WOVN.rb_#{VERSION}"
209
- ].join('&')
221
+ ]
222
+ result << "customDomainLangs=#{JSON.generate(custom_domain_langs)}" unless custom_domain_langs.empty?
223
+ result.join('&')
210
224
  end
211
225
  end
212
226
  end
@@ -32,6 +32,10 @@ module Wovnrb
32
32
  marked_html
33
33
  end
34
34
 
35
+ def keys
36
+ @mapped_values.map { |v| v[0] }
37
+ end
38
+
35
39
  private
36
40
 
37
41
  def generate_key