module ActionView::Helpers::TranslationHelper
def localize(object, **options)
See https://www.rubydoc.info/gems/i18n/I18n/Backend/Base:localize
Delegates to I18n.localize with no additional functionality.
def localize(object, **options) I18n.localize(object, **options) end
def missing_translation(key, options)
def missing_translation(key, options) keys = I18n.normalize_keys(options[:locale] || I18n.locale, key, options[:scope]) title = +"translation missing: #{keys.join(".")}" options.each do |name, value| unless name == :scope title << ", " << name.to_s << ": " << ERB::Util.html_escape(value) end end if ActionView::Base.debug_missing_translation content_tag("span", keys.last.to_s.titleize, class: "translation_missing", title: title) else title end end
def scope_key_by_partial(key)
def scope_key_by_partial(key) if key&.start_with?(".") if @virtual_path @_scope_key_by_partial_cache ||= {} @_scope_key_by_partial_cache[@virtual_path] ||= @virtual_path.gsub(%r{/_?}, ".") "#{@_scope_key_by_partial_cache[@virtual_path]}#{key}" else raise "Cannot use t(#{key.inspect}) shortcut because path is not available" end else key end end
def translate(key, **options)
resolved against.
This enables annotate translated text to be aware of the scope it was
<% end %>
<%= translation %>
<%= translate(".relative_key") do |translation, resolved_key| %>
translation key, translate accepts a block:
To access the translated text along with the fully resolved
they can provide HTML values for.
when you call translate in a template and translators know which keys
that include HTML tags so that you know what kind of output to expect
helper methods. This naming convention helps to identify translations
will return an HTML safe string that won't be escaped by other HTML
translate("footer_html") or translate("footer.html")
has the suffix "_html" or the last element of the key is "html". Calling
Third, the translation will be marked as html_safe if the key
a convention to scope keys consistently.
repetitive to translate many keys within the same partial and provides
translate("people.index.foo"). This makes it less
the people/index.html.erb template is equivalent to calling
the key by the current partial. Calling translate(".foo") from
Second, if the key starts with a period translate will scope
translate.
individually by passing raise: true as an option to
config.i18n.raise_on_missing_translations = true or
opt out of span-wrapping behavior globally by setting
If you would prefer missing translations to raise an error, you can
giving developers a way to find missing translations.
This allows for views to display rather reasonable strings while still
title="translation missing: en.blog.post.title">Title
class="translation_missing"
"blog.post.title" will be:
For example, the value returned for the missing translation key
* Have a titleized version of the last key segment as text
* Contain the missing key as the value of the +title+ attribute
* Have a translation-missing class applied
be rendered as inline spans that:
First, it will ensure that any thrown +MissingTranslation+ messages will
functions.
Delegates to I18n#translate but also performs three additional
def translate(key, **options) return key.map { |k| translate(k, **options) } if key.is_a?(Array) key = key&.to_s unless key.is_a?(Symbol) alternatives = if options.key?(:default) options[:default].is_a?(Array) ? options.delete(:default).compact : [options.delete(:default)] end options[:raise] = true if options[:raise].nil? && TranslationHelper.raise_on_missing_translations default = MISSING_TRANSLATION translation = while key || alternatives.present? if alternatives.blank? && !options[:raise].nil? default = NO_DEFAULT # let I18n handle missing translation end key = scope_key_by_partial(key) translated = ActiveSupport::HtmlSafeTranslation.translate(key, **options, default: default) break translated unless translated == MISSING_TRANSLATION if alternatives.present? && !alternatives.first.is_a?(Symbol) break alternatives.first && I18n.translate(**options, default: alternatives) end first_key ||= key key = alternatives&.shift end if key.nil? && !first_key.nil? translation = missing_translation(first_key, options) key = first_key end block_given? ? yield(translation, key) : translation end