Message Boards

React Problem With Liferay.Language.get() method

thumbnail
Vahid Kh, modified 4 Years ago.

React Problem With Liferay.Language.get() method

Junior Member Posts: 54 Join Date: 8/6/19 Recent Posts
Hello
I have a strange problem in localization language keys
​​​​​​​At the following code and inside componentDidMount() method , the first line cannot be translated while the second line works correctly ,
What's the problem ?

export default class extends React.Component {

   constructor(props){
      super(props);
      this.state = {
         label: 'label_userFirstName'
      }
   }

   componentDidMount() {
      console.log('from state --->'  , Liferay.Language.get(this.state.label)) // print: label_userFirstName
      console.log('from String --->' , Liferay.Language.get('label_userFirstName')) //print: User Fist Name 
   }

   render() {
      return (
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div>My Text</div>
&nbsp; &nbsp; &nbsp; );
&nbsp; &nbsp;} &nbsp;
}
thumbnail
David H Nebinger, modified 4 Years ago.

RE: React Problem With Liferay.Language.get() method

Liferay Legend Posts: 14919 Join Date: 9/2/06 Recent Posts
So there's actually a little bit of magic going on with Liferay.Language.get()...

There's a server-side filter which inspects the JS and manually substitutes the Liferay.Language.get() strings with the actual translated strings; it is not actually a web service or anything invoking the backend.

So the second one works because the filter can get the key, look up the value and perform the substitution.

The first one fails because the value is itself a runtime value that the filter cannot substitute, so it leaves the original stuff as it is.

I would recommend solving this by using a container object that has all of your string vars, each one with the 2nd form of the Liferay.Language.get() so that you get the translations. Then in code pick the value to display.
thumbnail
Vahid Kh, modified 4 Years ago.

RE: React Problem With Liferay.Language.get() method

Junior Member Posts: 54 Join Date: 8/6/19 Recent Posts
Thanks David for your quick answer
Your solution can solve my problem but I think it's a problem in React Portlets of Liferay 
because React based on changing on runtime , and in my opinion your solution is a temporary hack
I think Liferay must implement a mechanism for storing language keys that can be used in runtime by JavasScript.
thumbnail
David H Nebinger, modified 4 Years ago.

RE: React Problem With Liferay.Language.get() method

Liferay Legend Posts: 14919 Join Date: 9/2/06 Recent Posts
Liferay's method works for all of Liferay's needs and can be adapted, even in my hacky example, to work for JS solutions.

If you need something more, you are free to build and expose a service to provide all of the functionality you need.

I'd ask that you consider, though, if you really want say 100,000 react portlets or apps continuously invoking a service to do a language translation on a single key. Does this seem like an effective use of your backend, of your network, of your server capacity?

These are the issues that the Liferay solution addresses. Since the keys are processed only during the initial send to the frontend, you don't have to worry about backend hits, excessive network traffic or capacity impact.

So sure, what I suggest will seem "hacky" in that you take away a lot of the dynamism of key lookup at runtime, but I would argue that the benefits over a standard implementation make this hacky option appealing.
thumbnail
Vahid Kh, modified 4 Years ago.

RE: React Problem With Liferay.Language.get() method

Junior Member Posts: 54 Join Date: 8/6/19 Recent Posts
Certainly, invoking a service to do a language translation is a very bad solution, and certainly this is not my mean.
For example all of language keys in all exist languages of a portlet can be send to frontend at loading page , Now all data for translating exist in frontend and no need to invoking a service from server. 
I think language keys isn't a secure data ,so sending all of them to client does not  create a security issue
Although, I know this myself that language keys in most of the time can be very large and this solution in terms of performance is unacceptable.
thumbnail
David H Nebinger, modified 4 Years ago.

RE: React Problem With Liferay.Language.get() method

Liferay Legend Posts: 14919 Join Date: 9/2/06 Recent Posts
Hey, so maybe I didn't explain it right...

On the server side, you have some sort of JS like:

componentDidMount() {
    console.log('from state ---&gt;' , Liferay.Language.get(this.state.label)) // print: label_userFirstName
    console.log('from String ---&gt;' , Liferay.Language.get('label_userFirstName')) //print: User Fist Name
}

This code goes through a filter when sending to the browser. The browser receives the following JS:

componentDidMount() {
    console.log('from state ---&gt;' , Liferay.Language.get(this.state.label)) // print: label_userFirstName
    console.log('from String ---&gt;' , 'User First Name') //print: User Fist Name
}

So there is no need to send everything to the front end, the filter does the replacements so the sent JS already has the corrected values. There's no service call, there's no overhead, etc. It is just a plain string at that point.

And it's why your code-based solution fails. The in-browser implementation of the JS method just returns the key that is passed in, which is why you end up seeing "label_userFirstName".

Sending the whole language bundle doesn't make sense since users don't change languages on the fly (most of the time). In fact there's no need to send the whole bundle for a single language since it is highly likely that not all defined keys are used 100% of the time. It ends up being the smallest amount of data to ship to the front end yet still fully support i18n in JS.
thumbnail
Vahid Kh, modified 4 Years ago.

RE: React Problem With Liferay.Language.get() method

Junior Member Posts: 54 Join Date: 8/6/19 Recent Posts
Thank you David for your complete answer
I could guess the way Liferay works , and  thanks for your further explanation
Certainly data transfer is more important  and I agree with you.

But now , about your solution:

let translated = {
       label_userFirstName : Liferay.Language.get('label_userFirstName'),
       label_userLastName : Liferay.Language.get('label_userLastName'),
       label_userFatherName : Liferay.Language.get('label_userFatherName ')
}
thumbnail
David H Nebinger, modified 4 Years ago.

RE: React Problem With Liferay.Language.get() method

Liferay Legend Posts: 14919 Join Date: 9/2/06 Recent Posts
Yep, that's exactly the kind of solution I was suggesting. It leverages Liferay's existing facilities, allows you to have i18n support in the apps, and minimizes ongoing overhead.