Locale Linux: challenge with double and periods

Jeeezzz @DerkJ my hero!

var percentage as double = items(3).left(items(3).Length - 1).Val
messageBox( percentage.tostring ) 

Local result:

Remote result:

There are likely good reasons why it has been designed this way, but this is an easy trap for many … Wel, RTFM is always the answer, isn’t it? @DerkJ Thank you very much for your help and your time, very much appreciated!

1 Like

Well you may have expect Xojo to give the same result nomatter what the system is (if no locale is set), could still be a bug.

But yeah .Val works that’s great.

1 Like

too early to close the party. Now xojo is rounding up :frowning: … I was to euphoric and was happy finally seeing 2 identical values …

Ok then try

Var myDouble As Double = Double.Parse( theString, Locale.Raw )

When converting a Double to string use Double.ToString(Locale.Raw) also this way it’s the same in as it’s out.

1 Like

Your code is returning on both machines.

But changing it to:

Var loc as new Locale("de_DE")
Var percentage As Double = Double.Parse( items(3).left(items(3).Length - 1), loc )
messageBox(percentage.ToString( loc ))

is showing the right result on both machines!

@DerkJ It seems this is closing the loop of my original question:

double.parse

which I wasn’t aware of seems to be this localization I was looking for. Now it is working, but it still seems or at least “feels” wrong - but perhaps this is just the path you have to follow if you are unlucky like me and you have to deal with non US formats :-).

Thanks again, in one millions years I found not have found this hint.

I know it can be hard, but these outputs are differently which should NOT happen if the locale is RAW (unified the same) or the input value must be different? Or some of the xojo functions handle it differently on different platforms. Which i think should NOT happen…

Anyway as long as you can move on, that’s what’s counting.

1 Like

I fully agree, most likely because Xojo dev is not running themselves into these issues, at least not very often? I would assume that a simple toDouble will do what it is supposed to do or raise an exception. How “val” is working in this particular example doesn’t make much sense to me either.

On top of that I’m setting:
Session.LanguageCode = "de-DE"

So I would assume that any browser interference will be overwritten as well. Perhaps @Greg_O_Lone will tell us that we overlooked something or will find a bug. It just looks strange to me.

For percentage it is not dramatic as you see the problem instantly, different stories for currencies for instance not to speak of any mathematical calculations …

First, Setting the browser LanguageCode doesn’t affect Xojo code except for what localized constants are used.

Next, you mentioned that the locale on the server is set to en-US-UTF8, but I didn’t see what your local machine is set to. If it’s de-DE then everything here makes sense.

The locale of the machine that your code is running on makes all the difference in the world as to how ToDouble and ToString (or Cdbl and Format) work. They both take the computer’s locale into account as to how a number should be formatted for conversion. That means that the thousands and decimal separator must match what the locale on the system where your app is running says it should be.

My suggestion is that you create a Locale object from the browser’s LanguageCode and use that for conversions. You’ll have a better chance of getting the correct conversion for whatever the end-user has their system set to and is using themselves.

Yes, this was confusing, as I changed it over the course of this exercise.

Remote Ubuntu was:

LANG=de_DE.UTF-8
LANGUAGE=
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC=de_DE.UTF-8
LC_TIME="de_DE.UTF-8"
LC_COLLATE="de_DE.UTF-8"
LC_MONETARY="de_DE.UTF-8"
LC_MESSAGES=de_DE.utf8
LC_PAPER="de_DE.UTF-8"
LC_NAME="de_DE.UTF-8"
LC_ADDRESS="de_DE.UTF-8"
LC_TELEPHONE="de_DE.UTF-8"
LC_MEASUREMENT="de_DE.UTF-8"
LC_IDENTIFICATION="de_DE.UTF-8"

and local macOS

when we did all the above investigations.

What about these values?

var percentStr as string = percentage.ToString(locale.raw)
var percentStr2 as string = percentage.ToString(locale.current)

Yeah if set both to locale.raw they should output the same or?
I don’t think it should shift the decimal point by 2 to the right ?

1 Like

+1

Does someone else have a Linux machine at his hands to test? It seems to me that I can change my Ubuntu locale on the remote to en_US.UTF8 with no impact on the code whatsoever. But I want to avoid wasting your time with some crazy configuration error on my machine (though, I don’t think there is a major problem).

It’s not shifting. The problem is that ToDouble doesn’t recognize the comma as a decimal separator and strips it when the system is set that way.

As an example, on a US system, a string formatted as “1,234.56” becomes a double with a value of 1234.56. Thousand separators are stripped. If your string had been “11,555”, the double would have given you 11555.

@Greg_O_Lone this makes perfectly sense, that’s why I asked about “localization for double” in my initial questions. Wrapping things up, am I right to assume that if you have settings where the decimal separator is not a period, you have to work with a local in the following way:

Var yourString As String = "10.000,45"
Var loc as new Locale("de_DE")
Var yourDouble As Double = Double.Parse( yourString, loc )

Or are there better ways to tackle this?

You shouldn’t need to use the locale object if the system itself is already set to de_DE when using ToDouble.

This all assumes that the system locale and number formatting were set before your web app was launched.

1 Like

That’s exactly what I assumed but which doesn’t seem to work.

They were, I did a reboot of the server.

Where I am not confident is that the locale I’m seeing in the bash after SSH-ing into the server is really the global “locale”. The below settings is what I’m seeing in the bash, after being SSHed into that server. The WebApp runs however as a services, perhaps that’s the issue, running under a system user with a different locale?

LANG=de_DE.UTF-8
LANGUAGE=
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC=de_DE.UTF-8
LC_TIME="de_DE.UTF-8"
LC_COLLATE="de_DE.UTF-8"
LC_MONETARY="de_DE.UTF-8"
LC_MESSAGES=de_DE.utf8
LC_PAPER="de_DE.UTF-8"
LC_NAME="de_DE.UTF-8"
LC_ADDRESS="de_DE.UTF-8"
LC_TELEPHONE="de_DE.UTF-8"
LC_MEASUREMENT="de_DE.UTF-8"
LC_IDENTIFICATION

But a “localectl status” shows:

   System Locale: LANG=de_DE.UTF-8
                  LC_MESSAGES=de_DE.utf8
       VC Keymap: n/a
      X11 Layout: fi
       X11 Model: pc105

I think that looks good enough …

Even root is running on de_DE:

root@nuage:~# locale
LANG=de_DE.UTF-8
LANGUAGE=
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC=de_DE.UTF-8
LC_TIME="de_DE.UTF-8"
LC_COLLATE="de_DE.UTF-8"
LC_MONETARY="de_DE.UTF-8"
LC_MESSAGES=de_DE.utf8
LC_PAPER="de_DE.UTF-8"
LC_NAME="de_DE.UTF-8"
LC_ADDRESS="de_DE.UTF-8"
LC_TELEPHONE="de_DE.UTF-8"
LC_MEASUREMENT="de_DE.UTF-8"
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=

I assume you’re getting those values using “env”. Have you tried having your app run that command using a shell? You might also try running “whoami” to find out what user you are.

2 Likes

Good point, will do. Thank you.

Same user I’m using to SSH in and the locale is looking good as well :frowning: