Reset an Item Label in rule

Is it possible to set the label of an item through a js (ECMA-2021) rule?

I would like to store alternative labels in metadata (to create a multi-language) mainUI.

DSL has something like .setLabel('txxx') – but access to metadata is cumbersome.
I can access metadata easily in ECMA-2021, but I didn’t find a method, which dynamically replaces the label. There is replaceItem(itemConfig) but that seems to be cracking a nut with a sledgehammer, as the full itemConfig needs to be supplied and - if I understood correctly - this actually removes the Item and adds a new one, effectively removing all itemHistory.

I believe the JS Item Object has a rawItem property which is the original Java Item Object from OH. That is the same Object you’re using in Rules DSL and so setLabel should work.

Removing the Item does not delete the history. As long as the Item comes back with the same name and the same type, the history is preserved. If it did lose the history, you’d lose everything every time you change a .items file.

Often this sort of thing is handled using expressions in the widgets.

Note that editing Item labels in-flight is not a documented feature, and so the various UI are not expected to support immediate changes.
In other words, changing a label might or might not show up on-screen at some time.

That’s a really good point. There is no event when the label changes so I would expect the page would need to be refreshed in the browser at a minimum to pick up the changes. That will force it to pull all the Items from the REST API again.

Could you expand on that?

Is that possible for built-in standard widgets as well?

Just about every field in a widget supports expressions. For more details see the following docs for more details on using expressions in widgets.

Also look at the config for simple widgets on the marketplace for lots of examples. For example Humidity shows an expression used to change the color and icon of a simple oh-label-item widget based on the state of the Item. You can use the expression in any of the widget’s fields so the title, subtitle, etc could be changes based on the state of some Item (it doesn’t have to be the Item the widget is displaying).

In the UI the expression would look something like

Note: now that I’ve pasted that in I notice that Test Number and número de prueba needs to be in quotes but I’m too lazy to recreate the screenshot. It should be

=(items['Language'].state == "english") ? "Test Number" : (items['Language'].state == "spanish" ? "número de prueba" : "Prüfnummer"

But the screen shot shows how you would enter an expression into the form instead of just how it looks in the YAML.

Got it.

But in this case, I have to recreate these verbose expressions for every Title/Label – and more importantly – for every widget separately. Isn’t it?

In actual fact, the translation of the Label is a property of the Item, rather than of the UI.

Anyway, the other approach for resetting the label

works very well.

Yes, that’s correct. In the browser, you can get away with refreshing the page.
In the openhab Android App, I even have to close and reopen.

Would there be a javascript command to actually trigger that ?
In the same context, is it possible to set the MainUI Locale (to change the display language of the non-Item texts)?

Not necessarily. You should create your own widgets that have these expressions and then you can use those across multiple Items. For example, I have nearly a dozen humidity sensors. I created just the one humidity widget and applied it to all those Items.

You might be able to create a set of generic widgets that implements the expression and then just has passthrough properties for everything else. There are lots of options.

No.

Yes, of course. Settings → Regional Settings is where you set the language, country, time zone, and location.

:upside_down_face: That I knew :grinning:

I have set up a numeric ‘languageID’ Item.

Number Lang  

I have stored the translations as metadata in the synonyms namespace for every Item:

Group Garage "Garage" <garage> (Basement) ["Garage"] {synonyms="Garage,Parking,Garage,Parking,Garage,Parkplatz"}

I have a cell “Button”, with which I iterate through the various languageID’s, changing the Lang Item state.

component: oh-cell
config:
  title: "=(items['Lang'].state == 0) ? \"English\" : (items['Lang'].state == 2) ? \"Français\" : \"Deutsch\""
  action: command
  actionRule: test
  actionItem: Lang
  actionCommand: "=(items['Lang'].state == 0) ? \"2\" : (items['Lang'].state == 2) ? \"4\" : \"0\""
  icon: "='iconify:openmoji:flag-'+((items['Lang'].state == 0) ? \"united-kingdom\" : (items['Lang'].state == 2) ? \"france\" : \"germany\")"
  subtitle: "=(items['Lang'].state == 0) ? \"English\" : (items['Lang'].state == 2) ? \"French\" : \"German\""
  header: "=(items['Lang'].state == 0) ? \"Display Language\" : (items['Lang'].state == 2) ? \"Langue Ecran\" : \"Anzeigesprache\""

I then trigger a rule, every time the Lang Item changes value:

languageNumber = items.getItem("Lang").state;
items.getItems().forEach(i => {
  
  let translations = i.getMetadataValue("synonyms")
  if (translations !== undefined && translations !== null)
    i.rawItem.setLabel(translations.split(',')[languageNumber]);
});

So far so good. I was wondering, whether I would be able to trigger the change in Regional Settings to a new language/country from within that js code.

Oh, well everything you do through MainUI ultimately results in a REST API call to the server. So look in Developer Tools → API Explorer and see if you can figure out what calls are made to change the language.

You might need to watch the log in MainUI and/or sniff the traffic to figure out what calls are really made when you change that setting though. All I can say is it’ll be an HTTP POST which can be done easily from a JS rule.

I don’t think this is a use case anyone anticipated.
It’s a home automation system, and even in a bilingual home we don’t often go around changing the labels on equipment.

But yes, the “correct” approach would be to enhance the Item object to include multiple labels, each with language tags. It might not be a bad idea to put in a formal suggestion, maybe in OH-4 there will be a more comprehensive approach to language handling which Item label could be included in.

Just to riff on that, I could see this feature being useful for marketplace widgets which could help make some of them support multiple languages without requiring people to edit the code by hand. It’r probably going to be a big job though.

The HOME part is indeed appreciated. My primary use case (next to my household being bilingual) is a holiday vacation home, which is going to be rented out. I can see plenty of features of HOME automation being useful there, and multi-lingual is key for support here.

I did that, but there isn’t any secttion for General Settings, though or is there?

I have sniffed the network traffic in Chrome developer tools and the change of the Locale is done through a PUT to the following URL:

http://openhabian:8080/rest/services/org.openhab.i18n/config

with the following JSON payload:

{language: "en", location: "50,4", measurementSystem: "SI",…}

I’m not a CURL geek and how you would actually launch that PUT from within openhab mainUI (with all kinds of authentification and settings in the header) is way beyond my skills, though.

Why is that - actually? wouldn’t we have an openhab equivalent of

window.location.reload()

It’s probably the services end point.

Use the sendHttpPutRequest Action from a rule, or use the native JavaScript ability to make HTTP calls. There are several examples on the forum using that to make calls on OH’s API from rules, including the authorization.

Whether or not it’s beyond your skills, if you want to go down this approach you will have to figure it out. It’s the only way I can see to achieve your goals.

Rules run on the server, not in the browser. If you run that command from a rule which of the N clients that may be connected at any given time should be reloaded? Should the server be forcing reloads on the clients in the first place, especially given how heavy that initial load of MainUI is? It could end up forcing a DoS attack on itself.

There is no way to write code in MainUI Widgets that:

  1. react to changes in an Item’s state to do something beyond change it’s own parameters
  2. cause changes to the whole MainUI app

So a rule is your only option.

It is possible to get pages and even individual widgets to refresh their data using the vue key property:

As you can see in that post to get this to work would still require some item state event. But if you’re running a rule to change item labels, it’s a simple thing to change the state of a proxy item that can then trigger a UI refresh.

At that point, timing might be the only thing I would be worried about. If you make a bunch of label changes in a rule and immediately follow that with an event that causes the UI refresh, will all of those label changes have actually been finalized yet?

1 Like

OK, I’ve progressed on this, by using the HTTP binding.
I sniffed the url and json payload format for reading and setting the regional configuration data in a rule, but I struggle to find the correct authentication appraoch for this. I’m opening a separate topic on this, since this is slightly off topic from this thread.
Thanks for pointing me in this direction, though.

https://community.openhab.org/t/openhab-3-api-and-http-binding-authentication/141354