Passing components in block form to Ember helpers, and rendering them

I want to pass to and render a component inside a helper function.

For example, let’s say I have a helper, t, that, given a String and key-value pairs, returns a string in a given locale. So, for a given string, welcome_user, t could return an English translation: Welcome {{name}}!. Here is the string with its translation, defined in a .yml file:

en:
  welcome_user: 'Welcome {{name}}!'

Naively, {{t 'welcome_user' name=user.name}} would output "Welcome Bob!" if user.name was "Bob".

The problem

Now, what if I want to add some markup around user.name? Ideally, I want to be able to wrap user.name with a component (say, a link to the homepage). Is there a way Ember can allow this?

To help illustrate what I’m trying to do, here’s some really rough interfaces:

{{t 'welcome_user'
  name=({{#link-to 'main'}}
      {{param.user.name}}
    {{/link-to}})
}}

{{!-- or --}}

{{#t 'welcome_user'}}
  {{#param "name"}}
    {{#link-to 'main'}}
      {{param.user.name}}
    {{/link-to}}
  {{/#param}}
{{/t}}

{{!-- or (based off http://www.sitepoint.com/using-inline-partials-and-decorators-with-handlebars-4-0/) --}}

{{t 'welcome_user' name=(partial 'user-name')}}

{{#* inline 'user-name'}}
  {{#link-to 'main'}}
    {{param.user.name}}
  {{/link-to}}
{{/inline}}

In all possibilities, the link-to component is passed as a name argument to t. t will then, somehow, render the component. Is there an easy (or hard) solution to doing this? To clarify, t was a helper only for illustrative purposes. If a solution requires t to be a component, for example, I’m happy to convert.

I believe this is a legitimate need, and important to allow for a couple reasons:

  • This will improve solutions for internationalization and accessibility. This is my biggest motivation and most important reason.
  • We should be able to express powerful ideas in templates.
  • I’d like to avoid shoving HTML into computed properties/helpers.

I don’t have any particular opinion on what the API would look like, just as long as it’s possible to achieve the theoretical use-case I outlined here.

What do y’all think?

Is there a reason why you can’t do something like: {{t 'welcome'}} {{user.name}}? That way, you could format user separately and add a link to it.

Is it the case that the placement of name might be positioned differently within the translated string depending on the language, like it might be 'Welcome {{name}}!' for one language but '{{name}} Welcome!' in another? Can you clarify a bit more why name needs to be passed into the helper?

Is it the case that the placement of name might be positioned differently within the translated string depending on the language, like it might be ‘Welcome {{name}}!’ for one language but ‘{{name}} Welcome!’ in another?

Yep, that’s why; word order isn’t the same in all languages. Interpolation is common in translation libraries, including ember-i18n for that reason.

Could you do something along the lines of what is described here: https://github.com/jamesarosen/ember-i18n/issues/79#issuecomment-26533948

In other words, you could write a function that constructs an anchor tag wrapped around name using string interpolation, and then you could use that string in your translation helper. For example, a computed property on the user model could be defined like this:

nameLink: Ember.computed('name', function() {
  let name = get(this, 'name');
  let link = `<a href="/welcome/users/link">${name}</a>`;
  
  return link;
})

And then you could send your computed nameLink string to your translation helper like:

{{t 'welcome_user' name=user.nameLink}}

You may need to mark the HTML string that is returned in the computed property as html safe (check out Ember - 4.6 - Ember API Documentation)