Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ nav_order: 6

## main

* Fix `Component.translate` raising `UncaughtThrowError` for keys missing from the sidecar translations, and `NoMethodError` for components without sidecar translations. It now falls back to the global translations, like the instance method does. Fix `translate` returning the `default:` value instead of an existing global translation.

*Andrii Furmanets*

* Only recompile components when a template or a translation file changed, instead of before every request, when templates aren't cached. Pages render about twice as fast in development.

*Clément Joubert*
Expand Down
19 changes: 7 additions & 12 deletions lib/view_component/translatable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ def translate(key = nil, **options)
locale = options.delete(:locale) || ::I18n.locale
key = __vc_i18n_key(key, options.delete(:scope))

__vc_i18n_backend.translate(locale, key, options)
if __vc_i18n_backend&.exists?(locale, key)
__vc_i18n_backend.translate(locale, key, options)
else
::I18n.translate(key, locale: locale, **options)
end
end

alias_method :t, :translate
Expand Down Expand Up @@ -102,17 +106,8 @@ def translate(key = nil, **options)

__vc_html_escape_translation_options!(options) if as_html

if key.start_with?(__vc_i18n_scope + ".")
translated =
catch(:exception) do
__vc_i18n_backend.translate(locale, key, options)
end

# Fallback to the global translations
if translated.is_a? ::I18n::MissingTranslation
return @view_context.translate(key, locale: locale, **options)
end

if __vc_i18n_backend.exists?(locale, key)
translated = __vc_i18n_backend.translate(locale, key, options)
translated = __vc_html_safe_translation(translated) if as_html
translated
else
Expand Down
26 changes: 26 additions & 0 deletions test/sandbox/test/translatable_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,32 @@ def test_translating_from_the_class
assert_equal({sidecar: "This is coming from the sidecar"}, TranslatableComponent.translate(".from"))
end

def test_translating_from_the_class_falls_back_to_global_translations
assert_equal "This is coming from Rails", TranslatableComponent.t("from.rails")
assert_equal "Relative key from Rails", TranslatableComponent.t(".relative_rails_key")
assert_equal "Translation missing: en.translatable_component.missing", TranslatableComponent.t(".missing")
assert_equal "Default", TranslatableComponent.t(".missing", default: "Default")

assert_raises(I18n::MissingTranslationData) do
TranslatableComponent.t(".missing", raise: true)
end
end

def test_translating_from_the_class_without_sidecar_translations
assert_equal "OH NO! (you shouldn't see me)", MyComponent.t(".message")
assert_equal "This is coming from Rails", MyComponent.translate("from.rails")
end

def test_default_does_not_shadow_global_translations
assert_equal "This is coming from Rails", TranslatableComponent.t("from.rails", default: "Default")
assert_equal "Relative key from Rails", TranslatableComponent.t(".relative_rails_key", default: "Default")
assert_equal "Default", TranslatableComponent.t(".missing", default: "Default")

assert_equal "This is coming from Rails", translate("from.rails", default: "Default")
assert_equal "Relative key from Rails", translate(".relative_rails_key", default: "Default")
assert_equal "Default", translate(".missing", default: "Default")
end

def test_inheriting_and_overriding_translations
render_inline(TranslatableSubclassComponent.new)

Expand Down
Loading