[MAGNOLIA-6890] TemplatingFunctions: Provide possibility to resolve language string to Locale object. Created: 29/Nov/16  Updated: 03/Jan/17

Status: Accepted
Project: Magnolia
Component/s: core, templating
Affects Version/s: 5.4.9, 5.5
Fix Version/s: None

Type: Improvement Priority: Neutral
Reporter: Christian Ringele Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: to-verify
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Text File TemplatingFunctions.patch    
Template:
Patch included:
Yes
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Date of First Response:

 Description   

For creating a language switch (for example in a navigation) one will use this TemplatingFunctions method (as also the travel demo does):

[#assign localizedLinks = cmsfn.localizedLinks()!]

the problem is, that the map contains the languages (Strings) as keys and not the Locale object itself. One reason is, that when Freemarker transforms the map to a hash sequence, it has trouble to use a complex object as the key (the Locale itself) when resolving by the key for an element.

The problem:
One wants not just the language name but also the Locale object itself for calling .getDisplayName() on the locale itself.
The travel demo does this really badly as delegating the resolving of the locale to the model of the project:

${model.getLocale(lang).getDisplayName()!}

This is just not usable in a light development approach...

Solution / Improvement:
Provide the possibility of resolving a language String to the Locale object via the TemplatingFunctions class:

public Locale getLocale(String language) {
        // Must catch throwing exception for returning properly Null to the Freemarker script.
        try {
            return LocaleUtils.toLocale(language);
        } catch (Exception e) {
            log.warn("Unable to resolve Locale for language {}", language, e);
        }
        return null;
}

So one can do in a navigation script the following:

${cmsfn.getLocale(lang).getDisplayName()!}

Side Topic:
I suggest to also add this method, so a Locale can directly be checked if its current:

    public boolean isCurrentLocale(Locale locale) {
        return StringUtils.equals(aggregationStateProvider.get().getLocale().toString(), locale.toString());
    }

Already existing:

    public boolean isCurrentLocale(String language) {
        return StringUtils.equals(aggregationStateProvider.get().getLocale().toString(), language);
    }


 Comments   
Comment by Christopher Zimmermann [ 19/Dec/16 ]

I agree that there should be an OOTB way to get the current locale in a templatescript, including the isCurrentLocale change.
The suggested API looks fine to me.
I don't have an opinion on the technical details.

Comment by Jan Haderka [ 20/Dec/16 ]

as a frontend developer:

  • why do you need locale as Object when you have locale string already?
  • why do you need to have extra method overload to check whether given locale is current for Locale object when you already have same for it's String accepting counterpart?

I guess what it boils down is: What is the benefit of introducing Locale object for front end developers, apart from familiarity of such object for backend developers? I don't see any. All I see is extra duplication of all language related methods currently accepting String as parameter.

The only real problem I read between the lines is - there is no easy way to obtain display (nice, readable) name of the current (or any) language at the moment. However to me, it remains to be determined whether solving this problem has to be done by exposing locale object or whether that can be internalized and exposed e.g. by cmsfn.getDisplayName(String someLanguage)

Comment by Christopher Zimmermann [ 20/Dec/16 ]

I like the suggestion of just a simple method that returns the name of the language, ie cmsfn.getLocaleDisplayName(String someLanguage), as a simple alternative that probably solves the problem.
There is a tradeoff between simplicity, vs the flexibility of having the Locale object. I agree the typical templater is happy if they dont have to read javadocs for locale class.
cringele do you agree this one method is sufficient?

Comment by Christian Ringele [ 03/Jan/17 ]

I think we should stop trying to foreseen, what a Front-End person might use and need out of an available Object/set of possible data.
We detect something, as the demo shows the need for a value out of the Locale object. So lets provide the Locale object instead of trying to foreseeing of what he ever could need form a Locale, and constraining him out of no real reason.
In the reality of the front end dev it means, if we foreseen something wrong, he has to wait for MONTHS to get it/solve it properly over Magnolia.

What is our gain of not providing the Locale? not having to duplicate 2 methods...? It was just a suggestion, the ticket is about the Locale object itself.
I don't care if the methods are not duplicated, because the problem can be solved properly in the script without them.

Front end developers are not stupid, and reading a Javadoc of the Locale object is... come on a really easy thing to do for any developer.

Fact is:
We create in the Front-End training a language switch. And there is no way for the Front_End devs to get the display name.
And when we only add the cmsfn.getDisplayName(String someLanguage) what should I reply to the questions ?

  • and how can i get the displayCountry? -> you can't...
  • why not? -> because we only added the displayName?
  • why? -> hard to explain, somebody thought you will NEVER need the displayCountry
  • and why don't you just provide the Locale itself? -> ehm also hard to explain... one reason is we wanted to prevent you from having to read the Javadoc...

I think the Locale itself provides quite some useful methods/data for a front end developer. Just some examples:
getDisplayLanguage()
getDisplayName()
getDisplayCountry()
getISO3Country()
getISO3Language()
getISOCountries()
getISOLanguages()

Generated at Mon Feb 12 04:18:48 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.