lit 1.1.4 → 1.1.5
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.md +42 -26
- data/app/assets/stylesheets/lit/lit_frontend.css +16 -15
- data/app/controllers/lit/concerns/request_info_store.rb +0 -15
- data/app/controllers/lit/concerns/request_keys_store.rb +0 -15
- data/app/controllers/lit/request_info_store.rb +10 -0
- data/app/controllers/lit/request_keys_store.rb +10 -0
- data/app/helpers/lit/frontend_helper.rb +65 -65
- data/lib/generators/lit/install/templates/initializer.erb +6 -1
- data/lib/lit/adapters/hash_storage.rb +2 -2
- data/lib/lit/adapters/redis_storage.rb +4 -8
- data/lib/lit/adapters.rb +2 -0
- data/lib/lit/cloud_translation/providers/google.rb +25 -7
- data/lib/lit/engine.rb +4 -7
- data/lib/lit/export.rb +5 -11
- data/lib/lit/i18n_backend.rb +24 -0
- data/lib/lit/services/localization_keys_to_hash_service.rb +18 -15
- data/lib/lit/version.rb +15 -1
- data/lib/lit.rb +11 -11
- metadata +7 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7dcf44da1e10a331cafdd9352461c1d9b985c6ea3d97e61744a1390e036be71a
|
4
|
+
data.tar.gz: 3c03d7e70b3c172092d807539543f0389e4e04c7f0420c66ffb5f96f742a4fa6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ecf7688c8aa6f32c6c01fab3b14024720f75155b66ed1be9494c40f0ed4755855e2b73b9d1d528a7a215513316a27ceb3427a84e72e0420f611a4c7e877b6ce0
|
7
|
+
data.tar.gz: 5f4fe480d203c6ade865f44385b4dfb951aa4a32c33f8e224b9371e3f36f5a16acd444ef73136bc28f7278d6518b7681d29540dca11833e6f7ecfc3b776b1386
|
data/README.md
CHANGED
@@ -22,9 +22,14 @@ Highly inspired by Copycopter by thoughtbot.
|
|
22
22
|
9. (On request) stores paths where translation keys were called
|
23
23
|
10. (On request) is able to show all translation keys used to render current page
|
24
24
|
|
25
|
+
|
25
26
|
### Screenshots
|
26
27
|
|
27
|
-
|
28
|
+
[Feature overview on YouTube](https://www.youtube.com/watch?v=_T9Kg05VvLI)
|
29
|
+
|
30
|
+

|
31
|
+
|
32
|
+
Check wiki for more: [Screenshots](https://github.com/prograils/lit/wiki/Screenshots)
|
28
33
|
|
29
34
|
### Installation
|
30
35
|
|
@@ -130,6 +135,10 @@ Lit::CloudTranslation.provider = Lit::CloudTranslation::Providers::Google
|
|
130
135
|
```
|
131
136
|
gem 'google-cloud-translate', '~> 1.2.4'
|
132
137
|
```
|
138
|
+
...we also support V2 of Google Cloud Translate gem, should you need it:
|
139
|
+
```
|
140
|
+
gem 'google-cloud-translate', '~> 2.1.2'
|
141
|
+
```
|
133
142
|
|
134
143
|
To use translation via Google, you need to obtain a [service account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) containing all the credentials required by the API.
|
135
144
|
|
@@ -199,17 +208,17 @@ Also applies to upgrading from `0.4.pre.alpha` versions.
|
|
199
208
|
|
200
209
|
1. Add `Lit::FrontendHelper` to your `ApplicationController`
|
201
210
|
|
202
|
-
|
203
|
-
|
204
|
-
|
211
|
+
```ruby
|
212
|
+
helper Lit::FrontendHelper
|
213
|
+
```
|
205
214
|
|
206
215
|
2. In you layout file include lit assets
|
207
216
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
217
|
+
```erb
|
218
|
+
<% if admin_user_signed_in? %>
|
219
|
+
<%= lit_frontend_assets %>
|
220
|
+
<% end %>
|
221
|
+
```
|
213
222
|
|
214
223
|
3. You're good to go - now log in to lit (if required) and open your frontend in separate tab (to have session persisted). On the bottom-right of your page you should see "Enable / disable lit highlight" - after enabling it you'll be able to click and translate phrases directly in your frontend
|
215
224
|
|
@@ -217,13 +226,14 @@ Also applies to upgrading from `0.4.pre.alpha` versions.
|
|
217
226
|
|
218
227
|
5. This feature requires jQuery! (at least for now)
|
219
228
|
|
229
|
+
|
220
230
|
### Storing request info
|
221
231
|
|
222
|
-
1. Include `Lit::
|
232
|
+
1. Include `Lit::RequestInfoStore` concern in your `ApplicationController`
|
223
233
|
|
224
|
-
|
225
|
-
|
226
|
-
|
234
|
+
```ruby
|
235
|
+
include Lit::RequestInfoStore
|
236
|
+
```
|
227
237
|
|
228
238
|
2. In lit initializer (`lit.rb`) set `store_request_info` config to true
|
229
239
|
|
@@ -238,25 +248,31 @@ Lit.store_request_info = true
|
|
238
248
|
|
239
249
|
1. Add `Lit::FrontendHelper` in your `ApplicationController`
|
240
250
|
|
241
|
-
|
242
|
-
|
243
|
-
|
251
|
+
```ruby
|
252
|
+
helper Lit::FrontendHelper
|
253
|
+
```
|
254
|
+
|
255
|
+
2. Include `Lit::RequestKeysStore` concern in your `ApplicationController`
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
include Lit::RequestKeysStore
|
259
|
+
```
|
244
260
|
|
245
|
-
|
261
|
+
3. Enable storing of request keys in lit initializer `config/initializers/lit.rb`
|
246
262
|
|
247
|
-
|
248
|
-
|
249
|
-
|
263
|
+
```ruby
|
264
|
+
Lit.store_request_keys = true
|
265
|
+
```
|
250
266
|
|
251
|
-
|
267
|
+
4. On the bottom of you layout file call `lit_translations_info` helper function
|
252
268
|
|
253
|
-
|
254
|
-
|
255
|
-
|
269
|
+
```erb
|
270
|
+
<%= lit_translations_info %>
|
271
|
+
```
|
256
272
|
|
257
|
-
|
273
|
+
5. From now on you'll be able to see all translation keys that were used to render current page. This feature works great with on-site live translations!
|
258
274
|
|
259
|
-
|
275
|
+
6. Lit authorized user must be signed in for this feature to work! This feature requires jQuery!
|
260
276
|
|
261
277
|
|
262
278
|
|
@@ -1,9 +1,11 @@
|
|
1
1
|
.lit-key-generic {
|
2
2
|
}
|
3
|
-
.lit-key-highlight{
|
4
|
-
text-decoration: underline
|
3
|
+
.lit-key-highlight {
|
4
|
+
text-decoration: underline !important;
|
5
|
+
text-decoration-color: red !important;
|
6
|
+
text-decoration-style: wavy !important;
|
5
7
|
}
|
6
|
-
#lit_button_wrapper{
|
8
|
+
#lit_button_wrapper {
|
7
9
|
position: fixed;
|
8
10
|
bottom: 20px;
|
9
11
|
right: 20px;
|
@@ -15,16 +17,15 @@
|
|
15
17
|
cursor: pointer;
|
16
18
|
color: white;
|
17
19
|
}
|
18
|
-
#lit_button_wrapper.lit-highlight-enabled{
|
20
|
+
#lit_button_wrapper.lit-highlight-enabled {
|
19
21
|
background-color: lightgreen;
|
20
22
|
}
|
21
|
-
#lit_textarea{
|
23
|
+
#lit_textarea {
|
22
24
|
position: absolute;
|
23
25
|
padding: 0 0 1px 0;
|
24
26
|
margin: 0 0 0 0;
|
25
27
|
border: 0;
|
26
28
|
border-bottom: 1px solid red;
|
27
|
-
|
28
29
|
}
|
29
30
|
.lit-translations-info.collapsed {
|
30
31
|
position: fixed;
|
@@ -38,7 +39,7 @@
|
|
38
39
|
cursor: pointer;
|
39
40
|
color: white;
|
40
41
|
}
|
41
|
-
.lit-translations-info.expanded{
|
42
|
+
.lit-translations-info.expanded {
|
42
43
|
position: absolute;
|
43
44
|
display: block;
|
44
45
|
width: 80%;
|
@@ -52,16 +53,16 @@
|
|
52
53
|
z-index: 90;
|
53
54
|
}
|
54
55
|
|
55
|
-
.lit-translations-info.collapsed span.lit-open-button{
|
56
|
+
.lit-translations-info.collapsed span.lit-open-button {
|
56
57
|
display: block;
|
57
58
|
}
|
58
|
-
.lit-translations-info.expanded span.lit-open-button{
|
59
|
+
.lit-translations-info.expanded span.lit-open-button {
|
59
60
|
display: none;
|
60
61
|
}
|
61
|
-
.lit-translations-info.collapsed span.lit-close-button{
|
62
|
+
.lit-translations-info.collapsed span.lit-close-button {
|
62
63
|
display: none;
|
63
64
|
}
|
64
|
-
.lit-translations-info.expanded span.lit-close-button{
|
65
|
+
.lit-translations-info.expanded span.lit-close-button {
|
65
66
|
display: block;
|
66
67
|
position: fixed;
|
67
68
|
right: 10%;
|
@@ -71,16 +72,16 @@
|
|
71
72
|
background-color: white;
|
72
73
|
padding: 10px 10px 5px;
|
73
74
|
}
|
74
|
-
.lit-translations-info.collapsed ul.lit-translations-list{
|
75
|
+
.lit-translations-info.collapsed ul.lit-translations-list {
|
75
76
|
display: none;
|
76
77
|
}
|
77
|
-
.lit-translations-info.expanded ul.lit-translations-list{
|
78
|
+
.lit-translations-info.expanded ul.lit-translations-list {
|
78
79
|
}
|
79
80
|
|
80
|
-
.lit-translations-info.expanded ul.lit-translations-list li{
|
81
|
+
.lit-translations-info.expanded ul.lit-translations-list li {
|
81
82
|
margin: 5px;
|
82
83
|
}
|
83
84
|
|
84
|
-
.lit-translations-info.expanded #lit_textarea{
|
85
|
+
.lit-translations-info.expanded #lit_textarea {
|
85
86
|
padding: 2px;
|
86
87
|
}
|
@@ -1,18 +1,3 @@
|
|
1
|
-
module Lit
|
2
|
-
module RequestInfoStore
|
3
|
-
extend ::ActiveSupport::Concern
|
4
|
-
included do
|
5
|
-
before_action :store_request_path
|
6
|
-
end
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
def store_request_path
|
11
|
-
Thread.current[:lit_current_request_path] = request&.path
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
1
|
module Lit::Concerns::RequestInfoStore
|
17
2
|
extend ActiveSupport::Concern
|
18
3
|
|
@@ -1,18 +1,3 @@
|
|
1
|
-
module Lit
|
2
|
-
module RequestKeysStore
|
3
|
-
extend ::ActiveSupport::Concern
|
4
|
-
included do
|
5
|
-
before_action :init_request_keys
|
6
|
-
end
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
def init_request_keys
|
11
|
-
Thread.current[:lit_request_keys] = {}
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
1
|
module Lit::Concerns::RequestKeysStore
|
17
2
|
extend ActiveSupport::Concern
|
18
3
|
|
@@ -1,83 +1,83 @@
|
|
1
|
-
module Lit
|
2
|
-
|
3
|
-
include ActionView::Helpers::TranslationHelper
|
1
|
+
module Lit::FrontendHelper
|
2
|
+
include ActionView::Helpers::TranslationHelper
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
module TranslationKeyWrapper
|
5
|
+
def translate(key, options = {})
|
6
|
+
count = options[:count]
|
7
|
+
options = options.with_indifferent_access
|
8
|
+
key = scope_key_by_partial(key)
|
9
|
+
key = pluralized_key(key, count) if count
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
content
|
17
|
-
end
|
18
|
-
|
19
|
-
def pluralized_key(key, count)
|
20
|
-
pluralizer = I18n.backend.send(:pluralizer, locale)
|
21
|
-
return unless pluralizer.respond_to?(:call)
|
22
|
-
last = count.zero? ? :zero : pluralizer.call(count)
|
23
|
-
format '%<key>s.%<last>s', key: key, last: last
|
24
|
-
end
|
25
|
-
|
26
|
-
def t(key, options = {})
|
27
|
-
translate(key, options)
|
28
|
-
end
|
11
|
+
content = super(key, **options.symbolize_keys)
|
12
|
+
content = get_translateable_span(key, content) if !options[:skip_lit] && lit_authorized?
|
13
|
+
content
|
29
14
|
end
|
30
|
-
prepend Lit::FrontendHelper::TranslationKeyWrapper
|
31
15
|
|
32
|
-
def
|
33
|
-
|
16
|
+
def pluralized_key(key, count)
|
17
|
+
pluralizer = I18n.backend.send(:pluralizer, locale)
|
18
|
+
return unless pluralizer.respond_to?(:call)
|
19
|
+
last = count.zero? ? :zero : pluralizer.call(count)
|
20
|
+
format '%<key>s.%<last>s', key: key, last: last
|
34
21
|
end
|
35
22
|
|
36
|
-
def
|
37
|
-
|
23
|
+
def t(key, options = {})
|
24
|
+
translate(key, options)
|
38
25
|
end
|
26
|
+
end
|
27
|
+
prepend Lit::FrontendHelper::TranslationKeyWrapper
|
39
28
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
29
|
+
def javascript_lit_tag
|
30
|
+
javascript_include_tag 'lit/lit_frontend'
|
31
|
+
end
|
32
|
+
|
33
|
+
def stylesheet_lit_tag
|
34
|
+
stylesheet_link_tag 'lit/lit_frontend'
|
35
|
+
end
|
36
|
+
|
37
|
+
def lit_frontend_assets
|
38
|
+
return unless lit_authorized?
|
48
39
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
40
|
+
meta = content_tag :meta, '', value: lit.find_localization_localization_keys_path, name: 'lit-url-base'
|
41
|
+
safe_join [javascript_lit_tag, stylesheet_lit_tag, meta]
|
42
|
+
end
|
43
|
+
|
44
|
+
def lit_translations_info
|
45
|
+
return if Thread.current[:lit_request_keys].nil?
|
46
|
+
return unless lit_authorized?
|
47
|
+
|
48
|
+
content_tag :div, class: 'lit-translations-info collapsed' do
|
49
|
+
concat content_tag(:span, 'Show translations', class: 'lit-open-button')
|
50
|
+
concat content_tag(:span, 'X', class: 'lit-close-button')
|
51
|
+
concat translations_list_content_tag
|
57
52
|
end
|
53
|
+
end
|
58
54
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
55
|
+
def translations_list_content_tag
|
56
|
+
content_tag :ul, class: 'lit-translations-list' do
|
57
|
+
Lit
|
58
|
+
.init
|
59
|
+
.cache
|
60
|
+
.request_keys
|
61
|
+
.each do |k, v|
|
62
|
+
concat(
|
63
|
+
content_tag(:li) do
|
64
|
+
concat content_tag(:code, "#{k}:")
|
65
|
+
concat get_translateable_span(k, v, alternative_text: '[empty]')
|
66
|
+
end,
|
67
|
+
)
|
66
68
|
end
|
67
|
-
end
|
68
69
|
end
|
70
|
+
end
|
69
71
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
def lit_authorized?
|
73
|
+
return false if Lit.authentication_verification.blank?
|
74
|
+
|
75
|
+
send Lit.authentication_verification
|
76
|
+
end
|
74
77
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
data: { key: key, locale: I18n.locale } do
|
79
|
-
localization.blank? ? alternative_text : localization
|
80
|
-
end
|
78
|
+
def get_translateable_span(key, localization, alternative_text: nil)
|
79
|
+
content_tag :span, class: 'lit-key-generic', data: { key: key, locale: I18n.locale } do
|
80
|
+
localization.blank? ? alternative_text : localization
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# `nil` will let everyone in.
|
4
4
|
Lit.authentication_function = <%= @authentication_function || 'nil' %>
|
5
5
|
|
6
|
-
# Which authentication verification function to use (ie. :user_signed_in)?
|
6
|
+
# Which authentication verification function to use (ie. :user_signed_in?)?
|
7
7
|
# This is used together with frontend translation module to determine, if
|
8
8
|
# helper button should be applied and translations wrapped in custom span
|
9
9
|
Lit.authentication_verification = <%= @authentication_verification || 'nil' %>
|
@@ -53,6 +53,11 @@ Lit.set_last_updated_at_upon_creation = true
|
|
53
53
|
# For more information please check the README.md
|
54
54
|
Lit.store_request_info = false
|
55
55
|
|
56
|
+
# Store request keys - this will store all keys used to render a page. Useful
|
57
|
+
# only when combined with Lit::RequestKeysStore concern to view those keys in
|
58
|
+
# frontend
|
59
|
+
Lit.store_request_keys = false
|
60
|
+
|
56
61
|
# Initialize lit
|
57
62
|
Lit.init
|
58
63
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Lit
|
1
|
+
module Lit::Adapters
|
2
2
|
class HashStorage < Hash
|
3
3
|
def incr(key)
|
4
4
|
self[key] ||= 0
|
@@ -25,7 +25,7 @@ module Lit
|
|
25
25
|
|
26
26
|
cache_localizations = form_cache_localizations(keys_of_subtree)
|
27
27
|
|
28
|
-
full_subtree = Lit::LocalizationKeysToHashService.call(cache_localizations)
|
28
|
+
full_subtree = Lit::Services::LocalizationKeysToHashService.call(cache_localizations)
|
29
29
|
requested_part = full_subtree.dig(*key.split('.'))
|
30
30
|
return nil if requested_part.blank?
|
31
31
|
return requested_part if requested_part.is_a?(String)
|
@@ -13,7 +13,7 @@ module Lit
|
|
13
13
|
Lit.redis_url || ENV[ENV['REDIS_PROVIDER'] || 'REDIS_URL']
|
14
14
|
end
|
15
15
|
|
16
|
-
class RedisStorage
|
16
|
+
class Adapters::RedisStorage
|
17
17
|
def initialize
|
18
18
|
Lit.redis
|
19
19
|
end
|
@@ -44,9 +44,7 @@ module Lit
|
|
44
44
|
delete(k)
|
45
45
|
if v.is_a?(Array)
|
46
46
|
Lit.redis.set(_prefixed_key_for_array(k), '1')
|
47
|
-
v.each
|
48
|
-
Lit.redis.rpush(_prefixed_key(k), ve.to_s)
|
49
|
-
end
|
47
|
+
v.each { |ve| Lit.redis.rpush(_prefixed_key(k), ve.to_s) }
|
50
48
|
elsif v.nil?
|
51
49
|
Lit.redis.set(_prefixed_key_for_nil(k), '1')
|
52
50
|
Lit.redis.set(_prefixed_key(k), '')
|
@@ -79,9 +77,7 @@ module Lit
|
|
79
77
|
end
|
80
78
|
|
81
79
|
def sort
|
82
|
-
Lit.redis.keys.sort.map
|
83
|
-
[k, self.[](k)]
|
84
|
-
end
|
80
|
+
Lit.redis.keys.sort.map { |k| [k, self.[](k)] }
|
85
81
|
end
|
86
82
|
|
87
83
|
def prefix
|
@@ -119,7 +115,7 @@ module Lit
|
|
119
115
|
values_of_subtree = Lit.redis.mget(keys_of_subtree)
|
120
116
|
cache_localizations = form_cache_localizations(keys_of_subtree, values_of_subtree)
|
121
117
|
|
122
|
-
full_subtree = Lit::LocalizationKeysToHashService.call(cache_localizations)
|
118
|
+
full_subtree = Lit::Services::LocalizationKeysToHashService.call(cache_localizations)
|
123
119
|
requested_part = full_subtree.dig(*key.split('.'))
|
124
120
|
return nil if requested_part.blank?
|
125
121
|
return requested_part if requested_part.is_a?(String)
|
data/lib/lit/adapters.rb
ADDED
@@ -45,13 +45,10 @@ module Lit::CloudTranslation::Providers
|
|
45
45
|
# end
|
46
46
|
class Google < Base
|
47
47
|
def translate(text:, from: nil, to:, **opts)
|
48
|
-
|
49
|
-
::Google::Cloud::Translate.new(project_id: config.keyfile_hash['project_id'],
|
50
|
-
credentials: config.keyfile_hash)
|
51
|
-
result = @client.translate(sanitize_text(text), from: from, to: to, **opts)
|
48
|
+
result = client.translate(sanitize_text(text), from: from, to: to, **opts)
|
52
49
|
unsanitize_text(
|
53
50
|
case result
|
54
|
-
when
|
51
|
+
when translation_class then result.text
|
55
52
|
when Array then result.map(&:text)
|
56
53
|
end
|
57
54
|
)
|
@@ -67,6 +64,27 @@ module Lit::CloudTranslation::Providers
|
|
67
64
|
|
68
65
|
private
|
69
66
|
|
67
|
+
def client
|
68
|
+
@client ||= begin
|
69
|
+
args = {
|
70
|
+
project_id: config.keyfile_hash['project_id'], credentials: config.keyfile_hash,
|
71
|
+
version: :v2
|
72
|
+
}
|
73
|
+
if Gem.loaded_specs['google-cloud-translate'].version < Gem::Version.create('2.0')
|
74
|
+
args = args.tap { |hs| hs.delete(:version) }
|
75
|
+
end
|
76
|
+
::Google::Cloud::Translate.new(**args)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def translation_class
|
81
|
+
if Gem.loaded_specs['google-cloud-translate'].version < Gem::Version.create('2.0')
|
82
|
+
::Google::Cloud::Translate::Translation
|
83
|
+
else
|
84
|
+
::Google::Cloud::Translate::V2::Translation
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
70
88
|
def default_config
|
71
89
|
if ENV['GOOGLE_TRANSLATE_API_KEYFILE'].blank?
|
72
90
|
env_keys = ENV.keys.grep(/\AGOOGLE_TRANSLATE_API_/)
|
@@ -93,7 +111,7 @@ module Lit::CloudTranslation::Providers
|
|
93
111
|
def sanitize_text(text_or_array)
|
94
112
|
case text_or_array
|
95
113
|
when String
|
96
|
-
text_or_array.gsub(/%{(.+?)}/, '<code>__LIT__\1__LIT__</code>')
|
114
|
+
text_or_array.gsub(/%{(.+?)}/, '<code>__LIT__\1__LIT__</code>').gsub(/\r\n/, '<code>0</code>')
|
97
115
|
when Array
|
98
116
|
text_or_array.map { |s| sanitize_text(s) }
|
99
117
|
when nil
|
@@ -106,7 +124,7 @@ module Lit::CloudTranslation::Providers
|
|
106
124
|
def unsanitize_text(text_or_array)
|
107
125
|
case text_or_array
|
108
126
|
when String
|
109
|
-
text_or_array.gsub(
|
127
|
+
text_or_array.gsub(%r{<code>0</code>}, "\r\n").gsub(%r{<code>__LIT__(.+?)__LIT__</code>}, '%{\1}')
|
110
128
|
when Array
|
111
129
|
text_or_array.map { |s| unsanitize_text(s) }
|
112
130
|
else
|
data/lib/lit/engine.rb
CHANGED
@@ -3,7 +3,8 @@ module Lit
|
|
3
3
|
require 'jquery-rails'
|
4
4
|
|
5
5
|
config.autoload_paths += %W[#{Lit::Engine.root}/app/controllers/lit/concerns]
|
6
|
-
|
6
|
+
|
7
|
+
paths.add 'lib'
|
7
8
|
|
8
9
|
isolate_namespace Lit
|
9
10
|
|
@@ -13,16 +14,12 @@ module Lit
|
|
13
14
|
end
|
14
15
|
|
15
16
|
initializer 'lit.reloader' do |app|
|
16
|
-
config.to_prepare
|
17
|
-
Lit.loader.cache.reset_local_cache if Lit.loader
|
18
|
-
end
|
17
|
+
config.to_prepare { Lit.loader.cache.reset_local_cache if Lit.loader }
|
19
18
|
end
|
20
19
|
|
21
20
|
initializer 'lit.migrations.append' do |app|
|
22
21
|
unless app.root.to_s.include?(root.to_s)
|
23
|
-
config.paths['db/migrate'].expanded.each
|
24
|
-
app.config.paths['db/migrate'] << expanded_path
|
25
|
-
end
|
22
|
+
config.paths['db/migrate'].expanded.each { |expanded_path| app.config.paths['db/migrate'] << expanded_path }
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
data/lib/lit/export.rb
CHANGED
@@ -4,7 +4,7 @@ require 'lit/services/localization_keys_to_hash_service'
|
|
4
4
|
module Lit
|
5
5
|
class Export
|
6
6
|
def self.call(locale_keys:, format:, include_hits_count: false)
|
7
|
-
raise ArgumentError,
|
7
|
+
raise ArgumentError, 'format must be yaml or csv' if %i[yaml csv].exclude?(format)
|
8
8
|
Lit.loader.cache.load_all_translations
|
9
9
|
localizations_scope = Lit::Localization.active
|
10
10
|
if locale_keys.present?
|
@@ -12,13 +12,11 @@ module Lit
|
|
12
12
|
localizations_scope = localizations_scope.where(locale_id: locale_ids) unless locale_ids.empty?
|
13
13
|
end
|
14
14
|
db_localizations = {}
|
15
|
-
localizations_scope.find_each
|
16
|
-
db_localizations[l.full_key] = l.translation
|
17
|
-
end
|
15
|
+
localizations_scope.find_each { |l| db_localizations[l.full_key] = l.translation }
|
18
16
|
|
19
17
|
case format
|
20
18
|
when :yaml
|
21
|
-
exported_keys = Lit::LocalizationKeysToHashService.call(db_localizations)
|
19
|
+
exported_keys = Lit::Services::LocalizationKeysToHashService.call(db_localizations)
|
22
20
|
exported_keys.to_yaml
|
23
21
|
when :csv
|
24
22
|
relevant_locales = locale_keys.presence || I18n.available_locales.map(&:to_s)
|
@@ -46,9 +44,7 @@ module Lit
|
|
46
44
|
relevant_locales.map { |l| Array.wrap(db_localizations["#{l}.#{key_without_locale}"]) }
|
47
45
|
transpose(key_localizations_per_locale).each do |translation_series|
|
48
46
|
csv_row = [key_without_locale, *translation_series]
|
49
|
-
if include_hits_count
|
50
|
-
csv_row << (Lit.init.cache.get_global_hits_counter(key_without_locale) || 0)
|
51
|
-
end
|
47
|
+
csv_row << (Lit.init.cache.get_global_hits_counter(key_without_locale) || 0) if include_hits_count
|
52
48
|
csv << csv_row
|
53
49
|
end
|
54
50
|
end
|
@@ -59,9 +55,7 @@ module Lit
|
|
59
55
|
# This is like Array#transpose but ignores size differences between inner arrays.
|
60
56
|
private_class_method def self.transpose(matrix)
|
61
57
|
maxlen = matrix.max { |x| x.length }.length
|
62
|
-
matrix.each
|
63
|
-
array[maxlen - 1] = nil if array.length < maxlen
|
64
|
-
end
|
58
|
+
matrix.each { |array| array[maxlen - 1] = nil if array.length < maxlen }
|
65
59
|
matrix.transpose
|
66
60
|
end
|
67
61
|
end
|
data/lib/lit/i18n_backend.rb
CHANGED
@@ -16,9 +16,22 @@ module Lit
|
|
16
16
|
I18n.const_set(:RESERVED_KEYS, reserved_keys.freeze)
|
17
17
|
end
|
18
18
|
|
19
|
+
## DOC
|
20
|
+
## Translation flow starts with Rails-provided ActionView::Helpers::TranslationHelper `translate` method
|
21
|
+
## In that method any calls to `I18n.translate` are catched by this method below (because Lit acts as I18 backend)
|
22
|
+
## Any calls in Lit to `super` go straight to I18n
|
19
23
|
def translate(locale, key, options = {})
|
20
24
|
options[:lit_default_copy] = options[:default].dup if can_dup_default(options)
|
21
25
|
content = super(locale, key, options)
|
26
|
+
|
27
|
+
if on_rails_6_1_or_higher?
|
28
|
+
@untranslated_key = key if key.present? && options[:default].instance_of?(Object)
|
29
|
+
|
30
|
+
if key.nil? && options[:lit_default_copy].present?
|
31
|
+
update_default_localization(locale, content, options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
22
35
|
if Lit.all_translations_are_html_safe && content.respond_to?(:html_safe)
|
23
36
|
content.html_safe
|
24
37
|
else
|
@@ -54,6 +67,17 @@ module Lit
|
|
54
67
|
|
55
68
|
private
|
56
69
|
|
70
|
+
def on_rails_6_1_or_higher?
|
71
|
+
"#{::Rails::VERSION::MAJOR}#{::Rails::VERSION::MINOR}".to_i == 61 ||
|
72
|
+
::Rails::VERSION::MAJOR >= 7
|
73
|
+
end
|
74
|
+
|
75
|
+
def update_default_localization(locale, content, options)
|
76
|
+
parts = I18n.normalize_keys(locale, @untranslated_key, options[:scope], options[:separator])
|
77
|
+
key_with_locale = parts.join('.')
|
78
|
+
@cache.update_locale(key_with_locale, content, content.is_a?(Array))
|
79
|
+
end
|
80
|
+
|
57
81
|
def can_dup_default(options = {})
|
58
82
|
return false unless options.key?(:default)
|
59
83
|
return true if options[:default].is_a?(String)
|
@@ -1,23 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Lit
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
module Services
|
5
|
+
# Converts flat hash with localization_keys as keys and translations as values to nested hash
|
6
|
+
# by nesting on '.' localization key dots
|
7
|
+
class LocalizationKeysToHashService
|
8
|
+
# http://subtech.g.hatena.ne.jp/cho45/20061122
|
9
|
+
def self.call(db_localizations)
|
10
|
+
deep_proc =
|
11
|
+
proc do |_k, s, o|
|
12
|
+
next s.merge(o, &deep_proc) if s.is_a?(Hash) && o.is_a?(Hash)
|
11
13
|
|
12
|
-
|
14
|
+
next o
|
15
|
+
end
|
16
|
+
nested_keys = {}
|
17
|
+
db_localizations.sort.each do |k, v|
|
18
|
+
key_parts = k.to_s.split('.')
|
19
|
+
converted = key_parts.reverse.reduce(v) { |a, n| { n => a } }
|
20
|
+
nested_keys.merge!(converted, &deep_proc)
|
21
|
+
end
|
22
|
+
nested_keys
|
13
23
|
end
|
14
|
-
nested_keys = {}
|
15
|
-
db_localizations.sort.each do |k, v|
|
16
|
-
key_parts = k.to_s.split('.')
|
17
|
-
converted = key_parts.reverse.reduce(v) { |a, n| { n => a } }
|
18
|
-
nested_keys.merge!(converted, &deep_proc)
|
19
|
-
end
|
20
|
-
nested_keys
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
data/lib/lit/version.rb
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lit
|
2
|
-
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def version
|
7
|
+
Gem::Version.new Version::STRING
|
8
|
+
end
|
9
|
+
|
10
|
+
module Version
|
11
|
+
MAJOR = 1
|
12
|
+
MINOR = 1
|
13
|
+
TINY = 5
|
14
|
+
|
15
|
+
STRING = [MAJOR, MINOR, TINY].compact.join('.')
|
16
|
+
end
|
3
17
|
end
|
data/lib/lit.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'lit/engine'
|
2
2
|
require 'lit/loader'
|
3
|
+
require 'lit/adapters'
|
3
4
|
|
4
5
|
module Lit
|
5
6
|
mattr_accessor :authentication_function
|
@@ -30,7 +31,7 @@ module Lit
|
|
30
31
|
self.loader ||= Loader.new
|
31
32
|
Lit.humanize_key = false if Lit.humanize_key.nil?
|
32
33
|
Lit.humanize_key_ignored_keys = [] if Lit.humanize_key_ignored_keys.nil?
|
33
|
-
Lit.humanize_key_ignored = %w[i18n date datetime number time support
|
34
|
+
Lit.humanize_key_ignored = %w[i18n date datetime number time support]
|
34
35
|
Lit.humanize_key_ignored |= Lit.humanize_key_ignored_keys
|
35
36
|
Lit.humanize_key_ignored = Regexp.new("(#{Lit.humanize_key_ignored.join('|')}).*")
|
36
37
|
Lit.ignore_yaml_on_startup = true if Lit.ignore_yaml_on_startup.nil?
|
@@ -42,6 +43,7 @@ module Lit
|
|
42
43
|
Lit.hits_counter_enabled = false if Lit.hits_counter_enabled.nil?
|
43
44
|
Lit.store_request_info = false if Lit.store_request_info.nil?
|
44
45
|
Lit.store_request_keys = false if Lit.store_request_keys.nil?
|
46
|
+
|
45
47
|
# if loading all translations on start, migrations have to be already
|
46
48
|
# performed, fails on first deploy
|
47
49
|
# self.loader.cache.load_all_translations
|
@@ -55,10 +57,10 @@ module Lit
|
|
55
57
|
rescue ActiveRecord::ActiveRecordError => e
|
56
58
|
log_txt =
|
57
59
|
"An #{e.class} error has been raised during Lit initialization. " \
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
"Lit assumes that database tables do not exist.\n\n" \
|
61
|
+
"Error: #{e.message}\n\n" \
|
62
|
+
"Backtrace:\n" \
|
63
|
+
"#{e.backtrace.join("\n")}"
|
62
64
|
Logger.new(STDOUT).error(log_txt) if ::Rails.env.test? # ensure this is logged to stdout in test
|
63
65
|
::Rails.logger.error(log_txt)
|
64
66
|
false
|
@@ -68,18 +70,16 @@ module Lit
|
|
68
70
|
case Lit.key_value_engine
|
69
71
|
when 'redis'
|
70
72
|
require 'lit/adapters/redis_storage'
|
71
|
-
return RedisStorage.new
|
73
|
+
return ::Lit::Adapters::RedisStorage.new
|
72
74
|
else
|
73
75
|
require 'lit/adapters/hash_storage'
|
74
|
-
return HashStorage.new
|
76
|
+
return ::Lit::Adapters::HashStorage.new
|
75
77
|
end
|
76
78
|
end
|
77
79
|
|
78
80
|
def self.fallback=(_value)
|
79
|
-
::Rails.logger.error
|
81
|
+
::Rails.logger.error '[DEPRECATION] Lit.fallback= has been deprecated, please use `config.i18n.fallbacks` instead'
|
80
82
|
end
|
81
83
|
end
|
82
84
|
|
83
|
-
if defined?
|
84
|
-
require 'lit/rails'
|
85
|
-
end
|
85
|
+
require 'lit/rails' if defined?(Rails)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maciej Litwiniuk
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2021-
|
14
|
+
date: 2021-12-23 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rails
|
@@ -19,14 +19,14 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: 5.2.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 5.2.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: jquery-rails
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,20 +111,6 @@ dependencies:
|
|
111
111
|
- - "~>"
|
112
112
|
- !ruby/object:Gem::Version
|
113
113
|
version: 4.7.1
|
114
|
-
- !ruby/object:Gem::Dependency
|
115
|
-
name: google-cloud-translate
|
116
|
-
requirement: !ruby/object:Gem::Requirement
|
117
|
-
requirements:
|
118
|
-
- - "~>"
|
119
|
-
- !ruby/object:Gem::Version
|
120
|
-
version: 1.2.4
|
121
|
-
type: :development
|
122
|
-
prerelease: false
|
123
|
-
version_requirements: !ruby/object:Gem::Requirement
|
124
|
-
requirements:
|
125
|
-
- - "~>"
|
126
|
-
- !ruby/object:Gem::Version
|
127
|
-
version: 1.2.4
|
128
114
|
- !ruby/object:Gem::Dependency
|
129
115
|
name: minitest
|
130
116
|
requirement: !ruby/object:Gem::Requirement
|
@@ -233,6 +219,8 @@ files:
|
|
233
219
|
- app/controllers/lit/locales_controller.rb
|
234
220
|
- app/controllers/lit/localization_keys_controller.rb
|
235
221
|
- app/controllers/lit/localizations_controller.rb
|
222
|
+
- app/controllers/lit/request_info_store.rb
|
223
|
+
- app/controllers/lit/request_keys_store.rb
|
236
224
|
- app/controllers/lit/sources_controller.rb
|
237
225
|
- app/helpers/lit/application_helper.rb
|
238
226
|
- app/helpers/lit/dashboard_helper.rb
|
@@ -308,6 +296,7 @@ files:
|
|
308
296
|
- lib/generators/lit/install/templates/initializer.erb
|
309
297
|
- lib/generators/lit/install_generator.rb
|
310
298
|
- lib/lit.rb
|
299
|
+
- lib/lit/adapters.rb
|
311
300
|
- lib/lit/adapters/hash_storage.rb
|
312
301
|
- lib/lit/adapters/redis_storage.rb
|
313
302
|
- lib/lit/cache.rb
|