Skip to content

Commit 24d100d

Browse files
authored
Fix bug with overwriting of defaults with recent Rails 6.1 compatibility fix (#183)
* Fix default overwriting bug * More bugfixes for default value and humanization on Rails 6.1
1 parent 9303996 commit 24d100d

File tree

7 files changed

+83
-22
lines changed

7 files changed

+83
-22
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
55

66
## [Unreleased]
7-
### Added
8-
- Proper CHANGELOG [@pnikrat](https://github.com/pnikrat)
7+
### Fixed
8+
- When running Lit on Rails 6.1 defaults could sometimes be overwritten [@pnikrat](https://github.com/pnikrat)
99

1010
## [WIP]
1111
- Efforts to use Vanilla JS and remove jQuery [WIP]
@@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1717
- When using Cloud translations, support V2 `google-cloud-translate` gem [@pnikrat](https://github.com/pnikrat)
1818
- Proper Rails 6.1 support. Fixes new Rails translate logic not saving defaults in Lit [@pnikrat](https://github.com/pnikrat)
1919
- Add screenshots to README [@mlitwiniuk](https://github.com/mlitwiniuk)
20+
- Proper CHANGELOG [@pnikrat](https://github.com/pnikrat)
2021

2122
### Changed
2223
- Lit now uses Ruby 2.7.4 [@pnikrat](https://github.com/pnikrat)

app/helpers/lit/frontend_helper.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ def pluralized_key(key, count)
2323
def t(key, options = {})
2424
translate(key, options)
2525
end
26+
27+
def missing_translation(key, options)
28+
# We try to humanize the key. Rails will do
29+
# it anyway in below call to super, but then it will wrap it also in
30+
# translation_missing span.
31+
# Humanizing key should be last resort
32+
if Lit::Services::HumanizeService.should_humanize?(key)
33+
return Lit::Services::HumanizeService.humanize_and_cache(key, options)
34+
end
35+
36+
super(key, options)
37+
end
2638
end
2739
prepend Lit::FrontendHelper::TranslationKeyWrapper
2840

lib/lit/i18n_backend.rb

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'i18n'
2+
require 'lit/services/humanize_service'
23

34
module Lit
45
class I18nBackend
@@ -28,7 +29,7 @@ def translate(locale, key, options = {})
2829
@untranslated_key = key if key.present? && options[:default].instance_of?(Object)
2930

3031
if key.nil? && options[:lit_default_copy].present?
31-
update_default_localization(locale, content, options)
32+
update_default_localization(locale, options)
3233
end
3334
end
3435

@@ -72,10 +73,12 @@ def on_rails_6_1_or_higher?
7273
::Rails::VERSION::MAJOR >= 7
7374
end
7475

75-
def update_default_localization(locale, content, options)
76+
def update_default_localization(locale, options)
7677
parts = I18n.normalize_keys(locale, @untranslated_key, options[:scope], options[:separator])
7778
key_with_locale = parts.join('.')
78-
@cache.update_locale(key_with_locale, content, content.is_a?(Array))
79+
content = options[:lit_default_copy]
80+
# we do not force array on singular strings packed into Array
81+
@cache.update_locale(key_with_locale, content, content.is_a?(Array) && content.length > 1)
7982
end
8083

8184
def can_dup_default(options = {})
@@ -118,35 +121,35 @@ def lookup(locale, key, scope = [], options = {})
118121
if options[:lit_default_copy].is_a?(Array)
119122
default = options[:lit_default_copy].map do |key_or_value|
120123
if key_or_value.is_a?(Symbol)
121-
I18n.normalize_keys(nil, key_or_value.to_s, options[:scope], options[:separator]).join('.').to_sym
124+
normalized = I18n.normalize_keys(
125+
nil, key_or_value.to_s, options[:scope], options[:separator]
126+
).join('.')
127+
if on_rails_6_1_or_higher? && Lit::Services::HumanizeService.should_humanize?(key)
128+
Lit::Services::HumanizeService.humanize(normalized)
129+
else
130+
normalized.to_sym
131+
end
122132
else
123133
key_or_value
124134
end
125135
end
126-
default = default.first if default.is_a?(Array)
127136
else
128137
default = options[:lit_default_copy]
129138
end
130139
content = default
131140
end
132141
# if we have content now, let's store it in cache
133142
if content.present?
134-
@cache[key_with_locale] = content
135-
content = @cache[key_with_locale]
136-
end
137-
# content might be nil - default value passed to cache was in fact
138-
# useless.
139-
# if content is still nil, we may try to humanize it. Rails will do
140-
# it anyway if we return nil, but then it will wrap it also in
141-
# translation_missing span.
142-
# Humanizing key should be last resort
143-
if content.nil? && Lit.humanize_key && Lit.humanize_key_ignored.match(key).nil?
144-
content = key.to_s.split('.').last.humanize
145-
if content.present?
146-
@cache[key_with_locale] = content
147-
content = @cache[key_with_locale]
143+
content = Array.wrap(content).compact.reject(&:empty?).reverse.find do |default_cand|
144+
@cache[key_with_locale] = default_cand
145+
@cache[key_with_locale]
148146
end
149147
end
148+
149+
if content.nil? && !on_rails_6_1_or_higher? && Lit::Services::HumanizeService.should_humanize?(key)
150+
@cache[key_with_locale] = Lit::Services::HumanizeService.humanize(key)
151+
content = @cache[key_with_locale]
152+
end
150153
end
151154
end
152155
# return translated content

lib/lit/services/humanize_service.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# frozen_string_literal: true
2+
3+
module Lit
4+
module Services
5+
# Checks if should humanize based on config and blacklist.
6+
# Performs humanize if required
7+
# Caches the value of humanization
8+
class HumanizeService
9+
def self.should_humanize?(key)
10+
Lit.humanize_key && Lit.humanize_key_ignored.match(key).nil?
11+
end
12+
13+
def self.humanize(key)
14+
key.to_s.split('.').last.humanize
15+
end
16+
17+
def self.humanize_and_cache(key, options)
18+
content = humanize(key)
19+
parts = I18n.normalize_keys(
20+
options[:locale] || I18n.locale, key, options[:scope], options[:separator]
21+
)
22+
key_with_locale = parts.join('.')
23+
I18n.cache_store[key_with_locale] = content
24+
I18n.cache_store[key_with_locale]
25+
end
26+
end
27+
end
28+
end

test/dummy/app/views/projects/_form.html.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
</div>
1212
<% end %>
1313

14+
<div><%= t('some_random.key') %></div>
15+
<div><%= t('another_random.key', default: 'Random') %></div>
1416
<div class="field">
1517
<%= f.label :name %><br />
1618
<%= f.text_field :name %>

test/unit/i18n_backend_test.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ def teardown
3232
end
3333

3434
test 'auto-humanizes key when Lit.humanize_key=true' do
35+
# since Rails 6.1 pure i18n calls should not be humanized
36+
skip if I18n.backend.send(:on_rails_6_1_or_higher?)
3537
Lit.humanize_key = true
3638
I18n.locale = :en
3739
test_key = 'this_will_get_humanized'
@@ -65,7 +67,8 @@ def teardown
6567
loc_key_count = -> { Lit::LocalizationKey.where(localization_key: [test_key, fallback_key]).count }
6668
assert_equal 0, loc_key_count.call
6769
assert_equal 'foobar', I18n.t(test_key, default: [fallback_key, 'foobar'])
68-
assert_equal 2, loc_key_count.call
70+
# We do not create localization key record for fallback keys if value is found
71+
assert_equal 1, loc_key_count.call
6972

7073
# on subsequent translation calls, they should not be fetched from DB
7174
assert_no_database_queries do

test/unit/lit_behaviour_test.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,18 @@ def teardown
252252
assert_equal hash_result[:sub_one], 'Left leaf'
253253
end
254254

255+
test 'it must not overwrite default with I18n content when calling same key twice ' \
256+
'with different interpolations' do
257+
assert_difference 'Lit::LocalizationKey.count', 1 do
258+
I18n.t('interpolated_key', default: 'Candidate %{name}', name: 'Tester')
259+
end
260+
assert_no_difference 'Lit::LocalizationKey.count' do
261+
result = I18n.t('interpolated_key', default: 'Candidate %{name}', name: 'Famous person')
262+
assert_equal result, 'Candidate Famous person'
263+
end
264+
assert_equal find_localization_for('interpolated_key', :en).default_value, 'Candidate %{name}'
265+
end
266+
255267
private
256268

257269
def find_localization_for(key, locale)

0 commit comments

Comments
 (0)