Internationalization and Localization

I want to start a dialog about internationalization and localization. Many of the device types currently in use are targeted towards American methods of measurement. Fahrenheit for temperatures for example.

This is the common setup for temperature in a thermostat

valueTile("temperature", "device.temperature", width: 2, height: 2) {
			state("temperature", label:'${currentValue}°',
				backgroundColors:[
					[value: 31, color: "#153591"],
					[value: 44, color: "#1e9cbb"],
					[value: 59, color: "#90d2a7"],
					[value: 74, color: "#44b621"],
					[value: 84, color: "#f1d801"],
					[value: 95, color: "#d04e00"],
					[value: 96, color: "#bc2323"]
				]
			)
		}

I am working on a device type that has a preference setting for Fahrenheit/Celsius, and it is fairly easy to change the actual temp reading to reflect that. The more difficult task is how do you change the background color for the tiles? 32 degrees Celsius is fairly warm, and well 96 degrees Celsius and you are having a pretty bad day. Throwing if statements into the tile markup seems inelegant. I am just wondering if there is a best practice for situations like this? Any thoughts? @Jim @Ben

2 Likes

This is how the Nest thermostat handles it, i wish we could use the getTemperatureScale() function here so we could use hub settings to set the colors correctly.

valueTile("temperature", "device.temperature", canChangeIcon: true, canChangeBackground:true) {
			state("temperature", label: '${currentValue}°', backgroundColors: [
				// Celsius Color Range
				[value: 0, color: "#153591"],
				[value: 7, color: "#1e9cbb"],
				[value: 15, color: "#90d2a7"],
				[value: 23, color: "#44b621"],
				[value: 29, color: "#f1d801"],
				[value: 33, color: "#d04e00"],
				[value: 36, color: "#bc2323"],
				// Fahrenheit Color Range
				[value: 40, color: "#153591"],
				[value: 44, color: "#1e9cbb"],
				[value: 59, color: "#90d2a7"],
				[value: 74, color: "#44b621"],
				[value: 84, color: "#f1d801"],
				[value: 92, color: "#d04e00"],
				[value: 96, color: "#bc2323"]
			]
			)
		}
2 Likes

Yeah, this “solution” relies on the fact that temperature ranges don’t overlap, which is true for indoor temperature, but not for outdoor.

1 Like

We have a lot of work going in to internationalization and localization right now. Great topic.

2 Likes

Can you share some examples? I am trying to get a sense of how others are handling these issues.

1 Like

@Tyler, just to let you know, the ST platform needs to let users enter negative value in smartapps.

This is required for proper Celsius Temperature Handling in Canada and Europe.

So far,I haven’t been able to enter any negative values in the smartapps that I’ve developed.

BTW, all my devices and smartapps were developed for both US and metric scales, so I use getTemperatureScale() to transition from one scale to another.

Regards.

3 Likes

Don’t be so negative, Yves. :slight_smile:

1 Like

Is that in the official API? I cannot find it in the docs.

To my knowledge, it’s part of the official API…

On iPhones, the background color will work automatically without specifying the set for Celcius. The only downside is there’s no easy way to display decimals on iPhones.

Ranted on that before. It’s used in official device types examples.

Just FYI, there’s method fahrenheitToCelsius() and celsiusToFahrenheit() that will convert the temps for you too. They can only be used within device types, not smartapps.

I found this http://docs.smartthings.com/en/latest/ref-docs/location-ref.html#temperaturescale

But when I try to use the undocumented getTemperatureScale() I get this error.

java.lang.NullPointerException: Cannot get property ‘locationDTO’ on null object @ line 44

@jodyalbritton,

Here is the way I do it in my smartapps.

As an example, I’ve included some code snippets for distance, speed, fuel consumption (in mpg or kpl),
and so on.

So, basically, I use getTemperatureScale() to determine if the ST user uses US or the metric system
for all types of scales.

Regards,

private def getConsumptionInMpg(value) {

if (getTemperatureScale() == "F"){
	return value    
}
return (kmplToMpg(value))

}

private def getConsumptionInKmpl(value) {

if (getTemperatureScale() == "C"){
	return value    
}
return (kmplToMpg(value))

}

private def getVolumeScale() {

def scale= getTemperatureScale()
if (scale == 'C') {
	return "liters"
}
return "gallons"

}

private def getVolume(value) {

if (getTemperatureScale() == "C"){
	return value    
}
if (!value) {
	return 0
}        
return (value * 0.26417)

}

private def getConsumptionScale() {

def scale= getTemperatureScale()
if (scale == 'C') {
	return "kmpl"
}
return "mpg"

}

private def getDistanceScale() {

def scale= getTemperatureScale()
if (scale == 'C') {
	return "km"
}
return "mi"

}

private def getSpeedScale() {

def scale= getTemperatureScale()
if (scale == 'C') {
	return "kmh"
}
return "mph"

}

private def milesToKm(distance) {

if (!distance) {
	return 0    
}    
return (distance * 1.609344) 

}

private def kmToMiles(distance) {

if (!distance) {
	return 0    
}    
return (distance * 0.62137) 

}

If I use

def scale= getTemperatureScale()

I get

java.lang.NullPointerException: Cannot get property 'locationDTO' on null object @ line 140

That’s the line where the def scale is located.

@jodyalbritton, that’s weird… I’ve never seen that exception before…

Must be a new platform issue…

Apparently it’s just for me. I just had someone else test the code and it does not throw the error. I will open a ticket for this.