Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedding YAML alias within YAML string

I'm trying to declare an alias within my YAML file and use it later on within a string. For example, I declare this:

en:
  support_email: &support_email "[email protected]"
  support_text: "Having a problem? Reach out to <a href="*support_email">*support_email</a>"

and want en.support_text to evaluate to Having a problem? Reach out to <a href="[email protected]">[email protected]</a>.

Is there a way to accomplish this? For context, this is within a RoR project.

Thanks for the help!

like image 617
Daniel Thorne Avatar asked Jan 13 '20 17:01

Daniel Thorne


1 Answers

You can't do this with YAML itself, because the specification specificity excludes this:

7.1. Alias Nodes

Subsequent occurrences of a previously serialized node are presented as alias nodes. The first occurrence of the node must be marked by an anchor to allow subsequent occurrences to be presented as alias nodes.

An alias node is denoted by the “*” indicator. The alias refers to the most recent preceding node having the same anchor. It is an error for an alias node to use an anchor that does not previously occur in the document. It is not an error to specify an anchor that is not used by any alias node.

Note that an alias node must not specify any properties or content, as these were already specified at the first occurrence of the node.

Example 7.1. Alias Nodes

First occurrence: &anchor Foo
Second occurrence: *anchor
Override anchor: &anchor Bar
Reuse anchor: *anchor

You can however use variable interpolation with I18n. Taking your example this would look like:

en:
  support_email: '[email protected]'
  support_text: 'Having a problem? Reach out to <a href="mailto:%{support_email}">%{support_email}</a>'

Then in your view:

<%= t('support_text', support_email: t('support_email')) %>

Note that the above is not marked as HTML safe, which can be done by adding the _html suffix changing the last element to html. Alternatively you can call .html_safe on the result yourself or input as raw content using <%== ... %> (instead of <%= ... %>) or <%= raw ... %>.

If you want to assign variables more dynamically consider changing the structure of the YAML file.

en:
  support:
    constants:
      message: 'Having a problem?'
      phone: '0123456789'
      email: '[email protected]'
    help_messages:
      phone:
        text: '%{message} Call us on %{phone}.'
        html: '%{message} Call us on %{phone}.'
      email:
        text: '%{message} Reach out to %{email}.'
        html: '%{message} Reach out to <a href="mailto:%{email}">%{email}</a>.'

Now do something like this:

<% vars = t('support.constants') %>
<%= t('support.help_messages.email.html', vars) %>

You could also move this to your own helper:

def t_with_constants(base, path, options = {})
  options = t("#{base}.constants").deep_merge(options)
  t("#{base}.#{path}", options)
end

Which allows you to use:

<%= t_with_constants('support', 'help_messages.email.html') %>

Note that if you're not in the view or helper you might need to use I18n.t instead. Which will doesn't have the quality of life improvements that ActionView::Helpers::TranslationHelper#t offers (like marking strings as HTML safe).

Of course you can give your own twist to this, but I suggest checking out the I18n guide and the documentation under ActionView::Helpers::TranslationHelper#translate for additional info.

like image 120
3limin4t0r Avatar answered Oct 04 '22 19:10

3limin4t0r