On a site translated with the i18n gem, I try to shorten the length of keys of translations in templates. The following helper does a similar trick as Rails. The shortcut <%= t(".title") %> in templates/users/show.html.erb implicitly extends the key to views.users.show.title.
# Translate the given key
#
# If the key starts with a dot, it is prefixed with "views." and the
# template path.
def t(key)
if key.start_with? "."
template_key = _rendering.config.template.tr("/", ".")
I18n.t([template_key, key].join, scope: :views)
else
I18n.t(key)
end
end
The _rendering.config.template is a bit hackish since I’ve just scanned the context for any info on the template.
However, inside partials, this will still prefix the template key. This is not necessarily a problem, it could actually be a feature this way since it allows for different translations depending on where the partial is used. (And giving the full key explicitly is always an option.) But it differs from how it works in Rails.
I’m wondering whether inside a helper, there’s a better, more future proof or informative way to figure out which template, partial etc is currently being rendered.
I mostly saw this “automatic lookup for translation” modified/overwritten in bigger projects anyway cause they often incorporate some ViewComponents or non standard partial location so it is hard to come up with a structure that will satisfy everyone, but as long as its easily overwritten it would be a nice addition. But given hanami structure I think even between slices there is a change there will be some differences in how frontend is structured (if one slices uses ViewComponent and the other does not). So I am a bit lost on where to put this kind of thing in Hanami
The site I’m currently working on has no slices, so this helper along with a provider which preps the I18n class does the trick just fine. But I’ll start to translate strings in my sliced pet project soonish, a good moment to experiment with these things. Unfortunately, monolingual apps are no thing in my part of the world.
After a dive into the hanami-view code, I don’t see any way to discover the current partial other than maybe extracting the file path from the caller array which is way too inefficient.
So I settle with a less obscure approach, the following two helpers:
# Set a translation key prefix for the duration of the block
def with_t_prefix(prefix)
old_prefix = @_t_prefix
@_t_prefix = prefix
yield
ensure
@_t_prefix = old_prefix
end
# Translate the given key
#
# If the key starts with a dot, it is prefixed with either what has
# been set by +with_t_scope+ or with the current template path.
def t(key, **options)
if key.start_with? "."
prefix = @_t_prefix
prefix ||= "templates." + _rendering.config.template.tr("/", ".")
I18n.t([prefix, key].join, **options)
else
I18n.t(key, **options)
end
end
This way, t defaults to the views i18n scope and prefixes the current template if f the key path starts with a . – but you can override this implicit prefix like so:
with_t_prefix "layouts.footer" do
t(".foo") # => translation of layouts.footer.foo
end