module ActionView::Helpers::TranslationHelper

Constants

MISSING_TRANSLATION
NO_DEFAULT

Attributes

raise_on_missing_translations[RW]

Public Instance Methods

l(object, **options)
Alias for: localize
localize(object, **options) click to toggle source

Delegates to I18n.localize with no additional functionality.

See www.rubydoc.info/gems/i18n/I18n/Backend/Base:localize for more information.

# File lib/action_view/helpers/translation_helper.rb, line 115
def localize(object, **options)
  I18n.localize(object, **options)
end
Also aliased as: l
t(key, **options)
Alias for: translate
translate(key, **options) { |translation, key| ... } click to toggle source

Delegates to I18n#translate but also performs three additional functions.

First, it will ensure that any thrown MissingTranslation messages will be rendered as inline spans that:

  • Have a translation-missing class applied

  • Contain the missing key as the value of the title attribute

  • Have a titleized version of the last key segment as text

For example, the value returned for the missing translation key "blog.post.title" will be:

<span
  class="translation_missing"
  title="translation missing: en.blog.post.title">Title</span>

This allows for views to display rather reasonable strings while still giving developers a way to find missing translations.

If you would prefer missing translations to raise an error, you can opt out of span-wrapping behavior globally by setting config.i18n.raise_on_missing_translations = true or individually by passing raise: true as an option to translate.

Second, if the key starts with a period translate will scope the key by the current partial. Calling translate(".foo") from the people/index.html.erb template is equivalent to calling translate("people.index.foo"). This makes it less repetitive to translate many keys within the same partial and provides a convention to scope keys consistently.

Third, the translation will be marked as html_safe if the key has the suffix “_html” or the last element of the key is “html”. Calling translate("footer_html") or translate("footer.html") will return an HTML safe string that won't be escaped by other HTML helper methods. This naming convention helps to identify translations that include HTML tags so that you know what kind of output to expect when you call translate in a template and translators know which keys they can provide HTML values for.

To access the translated text along with the fully resolved translation key, translate accepts a block:

<%= translate(".relative_key") do |translation, resolved_key| %>
  <span title="<%= resolved_key %>"><%= translation %></span>
<% end %>

This enables annotate translated text to be aware of the scope it was resolved against.

# File lib/action_view/helpers/translation_helper.rb, line 72
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
Also aliased as: t

Private Instance Methods

missing_translation(key, options) click to toggle source
# File lib/action_view/helpers/translation_helper.rb, line 141
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
scope_key_by_partial(key) click to toggle source
# File lib/action_view/helpers/translation_helper.rb, line 127
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