wovnrb 3.8.0 → 3.9.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.
- checksums.yaml +4 -4
- data/README.en.md +44 -15
- data/README.ja.md +51 -20
- data/README.md +1 -1
- data/lib/wovnrb/api_translator.rb +5 -0
- data/lib/wovnrb/custom_domain/custom_domain_lang.rb +31 -0
- data/lib/wovnrb/custom_domain/custom_domain_lang_url_handler.rb +27 -0
- data/lib/wovnrb/custom_domain/custom_domain_langs.rb +40 -0
- data/lib/wovnrb/headers.rb +62 -51
- data/lib/wovnrb/lang.rb +1 -1
- data/lib/wovnrb/services/html_converter.rb +17 -3
- data/lib/wovnrb/services/html_replace_marker.rb +4 -0
- data/lib/wovnrb/store.rb +10 -1
- data/lib/wovnrb/url_language_switcher.rb +44 -4
- data/lib/wovnrb/version.rb +1 -1
- data/lib/wovnrb.rb +7 -2
- data/test/lib/custom_domain/custom_domain_lang_test.rb +85 -0
- data/test/lib/custom_domain/custom_domain_lang_url_handler_test.rb +75 -0
- data/test/lib/custom_domain/custom_domain_langs_test.rb +82 -0
- data/test/lib/headers_test.rb +209 -48
- data/test/lib/services/html_converter_test.rb +70 -0
- data/test/lib/url_language_switcher_test.rb +148 -0
- data/test/lib/wovnrb_test.rb +1 -0
- metadata +9 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a0283acd73cab4171aefb1bb183832a0536a2c88fd4c62ac3fef0befee06a2a2
|
|
4
|
+
data.tar.gz: b8eebae5190864b55c02f53c30e166ec955ce08c19fd7866185a7ec50df54c3c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
|
129
|
-
|
|
130
|
-
'path'
|
|
131
|
-
'subdomain'
|
|
132
|
-
'query'
|
|
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` パラメータで設定できます。設定できるタイプは
|
|
125
|
+
ライブラリはRubyアプリケーションの中で、翻訳されるURLを新たに追加することで動作します。
|
|
126
|
+
urlの種類は `url_pattern` パラメータで設定できます。設定できるタイプは4種類。
|
|
126
127
|
|
|
127
128
|
|
|
128
|
-
パラメータ
|
|
129
|
-
|
|
130
|
-
'path'
|
|
131
|
-
'subdomain'
|
|
132
|
-
'query'
|
|
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
|
-
|
|
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
|
data/lib/wovnrb/headers.rb
CHANGED
|
@@ -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']
|
|
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']
|
|
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
|
-
|
|
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
|
|
80
|
-
if @
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
@
|
|
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
|
|
120
|
+
def request_out
|
|
113
121
|
@env['wovnrb.target_lang'] = lang_code
|
|
114
122
|
case @settings['url_pattern']
|
|
115
123
|
when 'query'
|
|
116
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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 =
|
|
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
|
-
]
|
|
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
|