3
votes

I have the following Sightly expression:

 <li data-sly-call="${linkTemplate.dynamicLink @ section='education', 
    url='/en/life-career-events.html', text=${'comp.masthead.navigation.home' @ i18n}}">
 </li>

The dynamiclink template is as follows:

<div data-sly-template.dynamicLink="${@ section, url, text}"
     data-sly-use.membersNav="${'com.comp.cms.component.masthead.MembersNavigation' @ section=section}">
  <a data-sly-attribute.class="${membersNav.cssClass}" href="${url}">${text}</a>
</div>

This doesn't work because text=${'comp.masthead.navigation.home' @ i18n} isn't evaluated as a string and then passed into the dynamiclink.

Is this possible? Can I evaluate and assign to a variable or do I have to create a new template when I want to evaluate i18n lookups?

1
Two things I don't understand in the template example that you provided: First, you have an @i18n option when calling the template, and another one within the template. I guess that only one i18n was intended (when calling). And second, you have a strange href URL with ${language.currentLanguage} ${url}. Here I guess that the intension was to have only ${url}.Gabriel Walt

1 Answers

3
votes

Sightly 1.1 doesn't allow to have expressions within expressions, and there's no plan to change that for now.

Hacking the solution:

There's a trick: data-sly-test can be (ab)used to set variables. It's not really a recommended way to do though, unless you have a real condition, because this will mislead someone who reads the template in thinking that the intention was to have an actual condition.

The trick goes like that: an identifier can be provided to data-sly-test, which will expose the result of the test as a variable. Additionally, data-sly-test will be considered true, unless the resulting string is empty.

For e.g.:

<p data-sly-test.spanishAsset="${'Asset' @ i18n, locale='es'}">${spanishAsset}</p>

Outputs:

<p>Recurso</p>

So in your case, you could write:

<li data-sly-test.linkText="${'comp.masthead.navigation.home' @ i18n}"
    data-sly-call="${linkTemplate.dynamicLink @ section='education', 
url='/en/life-career-events.html', text=linkText}">
</li>

A cleaner solution

As you probably don't want to explain to all the users of this template that they have to write such a hack, and instead of having two separated templates for translated and non-translated texts, you could instead leverage optional templates parameters. So you might for e.g. have a noI18n optional parameter.

The call would then be as simple as it can be:

<!--/* Translating would be the default behavior */-->
<li data-sly-call="${linkTemplate.dynamicLink @
    section='education', 
    url='/en/life-career-events.html',
    text='comp.masthead.navigation.home'}"></li>
<!--/* Or translating could be turned off */-->
<li data-sly-call="${linkTemplate.dynamicLink @
    section='education', 
    url='/en/life-career-events.html',
    text='my text...',
    noI18n=true}"></li>

The template would then have two data-sly-test conditions for the two cases (note that the data-sly-unwrap attributes can be dropped in AEM 6.1+):

<div data-sly-template.dynamicLink="${@ section, url, text, noI18n}"
     data-sly-use.membersNav="${'com.comp.cms.component.masthead.MembersNavigation'
         @ section=section}">
    <a href="${url}" data-sly-attribute.class="${membersNav.cssClass}">
        <sly data-sly-test="${noI18n}" data-sly-unwrap>${membersNav.text}</sly>
        <sly data-sly-test="${!noI18n}" data-sly-unwrap>${membersNav.text @ i18n}</sly>
    </a>
</div>

Optionally, to keep the template as simple as possible and to remove those conditions, you could also make the Use-API do the translation, depending on the noI18n optional parameter:

<div data-sly-template.dynamicLink="${@ section, url, text, noI18n}"
     data-sly-use.membersNav="${'com.comp.cms.component.masthead.MembersNavigation'
         @ section=section, noI18n=noI18n}">
    <a href="${url}" data-sly-attribute.class="${membersNav.cssClass}">
        ${membersNav.text}
    </a>
</div>

The proper code for the logic to translate a string is:

Locale pageLang = currentPage.getLanguage(false);
I18n i18n = new I18n(slingRequest.getResourceBundle(pageLang));
String text = i18n.get("Enter a search keyword");