Recent

Author Topic: [solved] Locales decimal separator  (Read 2696 times)

andyH

  • Jr. Member
  • **
  • Posts: 99
[solved] Locales decimal separator
« on: January 06, 2022, 07:36:57 pm »
Have an application distributed via iso, works fine. Installing from deb in a user's system generates an error when run ["100.00" is an invalid float.]. Suspect user's locale uses "," (comma) as the decimal separator, application is compiled in English, decimal separator "." (full stop). Googling for how to fix this points towards GetLocaleFormatSettings. Supposed to be in sysutils, can't find it, suspect not implemented in linux?

Can someone point me in the right direction, I can parse the output of the terminal utility locale to find the user's locale, but how then do I tell my application what to use? Not yet looking to do full translations of the application, that is on the to-do list for the future.

EDIT - I can do this externally, i.e. read the user's locale and set LC_NUMERIC="en_GB.UTF-8" and then reset it on close, but would prefer the application to use the existing setting for LC_NUMERIC. Would this mean changing all the code that does formatfloat(#,##0,somenumber) to an if statement if x then formatfloat(#,##0,somenumber) else formatfloat(#.##0,somenumber) ?
« Last Edit: January 11, 2022, 07:30:32 pm by andyH »

Bart

  • Hero Member
  • *****
  • Posts: 4689
    • Bart en Mariska's Webstek
Re: Locales decimal separator
« Reply #1 on: January 06, 2022, 09:46:18 pm »
FormatFloat has an overload in which you can supply a TFormatSetting.

Bart

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 9979
  • FPC developer.
Re: Locales decimal separator
« Reply #2 on: January 06, 2022, 09:48:56 pm »
Afaik Sysutiols.GetLocalFormatSettings() works fine, but is Windows only.

tetrastes

  • Full Member
  • ***
  • Posts: 194
Re: Locales decimal separator
« Reply #3 on: January 06, 2022, 11:18:27 pm »
Code: Pascal  [Select][+][-]
  1. DefaultFormatSettings.DecimalSeparator := '.';
?

Sieben

  • Sr. Member
  • ****
  • Posts: 299
Re: Locales decimal separator
« Reply #4 on: January 06, 2022, 11:19:38 pm »
Since you seem to be on linux, try adding clocale to the uses clause of your lpr, like this for instance:

Code: Pascal  [Select][+][-]
  1. program TestEditor;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}
  7.   {$IFDEF UseCThreads}
  8.   cthreads,
  9.   {$ENDIF}
  10.   clocale,
  11.   {$ENDIF}
  12.   Interfaces, // this includes the LCL widgetset
  13.   Forms, TestMain
  14.   { you can add units after this };
  15.   //...
  16.  
Lazarus 2.2.0, FPC 3.2.2, .deb install on Ubuntu Xenial 32 / Gtk2 / Unity7

andyH

  • Jr. Member
  • **
  • Posts: 99
Re: Locales decimal separator
« Reply #5 on: January 11, 2022, 07:30:08 pm »
Since you seem to be on linux,
Apologies for the delay in reponding, yes, that's why I posted in the linux sub-forum.

Thanks for the info on clocale, this fixed one problem and something else learnt. The ultimate problem was a badly behaved utility (partclone) that was only partly following the locale. I'm parsing the output for a progress window. With LC_NUMERIC set so that the decimal separator is a comma, it was reporting progress correctly:
Code: Pascal  [Select][+][-]
  1. Elapsed: 00:05:00, Remaining: 00:00:01, Completed:  99,39%,   4,85GB/min,
  2.                                                       ^ correct
until it reached 100% complete when it switched to using a full stop!!
Code: Pascal  [Select][+][-]
  1. Elapsed: 00:05:02, Remaining: 00:00:00, Completed: 100.00%, Rate:   4,84GB/min,
  2.                                                       ^ what?
Hence getting 100.00 is an invalid float in a StrToFloat. Easy to fix (try except), difficult to find :(

winni

  • Hero Member
  • *****
  • Posts: 3045
Re: [solved] Locales decimal separator
« Reply #6 on: January 11, 2022, 08:08:28 pm »
Hi!

Instead of fighting against the foolish locale settings from Delphi do it yourself:

Code: Pascal  [Select][+][-]
  1. function internatStr2Float (s: string) : Double;
  2. var error,p Integer;
  3. begin
  4. p := pos (',',s);
  5. if p > 0 then s[p] := '.';
  6. val (s,result,error);
  7. // do something if error <> 0
  8. end;
  9.  
  10.  

Winni

 

TinyPortal © 2005-2018