Erzwungene Locale geht nicht mit Linux.

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Mathias
Beiträge: 7012
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Erzwungene Locale geht nicht mit Linux.

Beitrag von Mathias »

Ich habe folgendes kleine Demo, wie erwartet, kommt ein "Punkt" bei mir in der Schweiz als Dezimaltrenner.

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption := FloatToStr(123.456);
end;
Starte ich mein Programm von der Konsole aus mit erzwungenem DE Ländercode kommt immer noch ein "Punkt";

Code: Alles auswählen

LANG="de_DE.UTF8" ./project1 # Punkt
Mache ich das selbe mit einer Windows-EXE und wine, kommt wie erwartet ein "Komma".

Code: Alles auswählen

ANG="de_DE.UTF8" wine project1.exe # Komma
An Linux kann dies nicht liegen, mache ich das ganze Experiment mit einem C Programm, dann kommt ein "Komma" unter Linux.

Code: Alles auswählen

#include <stdio.h>
#include <locale.h>
#include <time.h>

int main(void)
{
  time_t currtime;
  struct tm *timer;
  char buffer[80];

  time( &currtime );
  timer = localtime( &currtime );

  printf("\nsetlocale: %s\n", setlocale(LC_ALL, ""));
  strftime(buffer,80,"%c", timer );
  printf("Float: %f   Date: %s\n\n", 123.456, buffer) ;

  return 0;
}

Code: Alles auswählen

echo 
echo ======== Linux ========
echo 
rm main
gcc -o main main.c 
LANG="de_CH.UTF8"  ./main # Punkt
LANG="de_DE.UTF8"  ./main # Komma
LANG="en_US.UTF8"  ./main # Punkt
LANG="en_GB.UTF8"  ./main # Punkt
echo 
echo ======== Windows ========
echo 
rm main.exe
x86_64-w64-mingw32-gcc main.c -o main.exe
LANG="de_CH.UTF8" wine main.exe # Punkt
LANG="de_DE.UTF8" wine main.exe # Komma
LANG="en_US.UTF8" wine main.exe # Punkt
LANG="en_GB.UTF8" wine main.exe # Punkt
Waran könnte dies liegen, das Lazarus und Linux da nicht zusammen spielen `
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Stevie
Beiträge: 180
Registriert: Di 27. Feb 2024, 22:40

Re: Erzwungene Locale geht nicht mit Linux.

Beitrag von Stevie »

Hallo Mathias,

hast Du die Anmerkung von der Man-Page im Blick?
Note that on unix systems, the localization support must be enabled explicitly, see Localization.
In anderen Worten: du musst in deiner 'Uses'-Liste die Unit "clocale" importieren, damit die Lokalisierung funktioniert...

Code: Alles auswählen

program localetest;

uses
  clocale, sysutils;

begin
 writeln(FloatToStr(123.456));
end.

Code: Alles auswählen

% LANG="de_DE.UTF-8" ./localetest
123,456
% LANG="de_CH.UTF8" ./localetest
123.456
%

Mathias
Beiträge: 7012
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Erzwungene Locale geht nicht mit Linux.

Beitrag von Mathias »

So wie es scheint, wurstelt da die Unit System etwas im Hintergrund.

Nicht mal das geht, ohne die unit clocale.

Code: Alles auswählen

  function printf(str: PChar): Integer; varargs cdecl; external 'c';

begin
  printf('float: %f', 123.456);
end.  
Woher weis Pascal, was für eine Ländereinstellung das System hat ?
Da muss es für die Abfrage noch was anderes geben als die Umgebungsvariable "LANG".
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

MmVisual
Beiträge: 1605
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4.2 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Erzwungene Locale geht nicht mit Linux.

Beitrag von MmVisual »

Ich frage mich was dein Ziel dieser Übung ist.

In meiner EXE habe ich das , und . Problem relativ einfach umgangen indem ich diese 2 Zeichen einfach in DefaultFormatSettings.DecimalSeparator umwandle bevor ich den String in eine Float Zahl konvertiere.
In sämtlichen Eingaben lasse ich beide Zeichen zu und konvertiere.

Damit funktioniert das ganze immer so wie derjenige, der vor dem Bildschirm sitzt, es erwarten würde wenn er Zahlen eingibt und ich werde mit diesen "Problemchen" nicht belästigt. Und 1000der Trennzeichen gibt ohnehin niemand ein, zumindest keiner freiwillig oder aus Gewohnheit.

Bei Datenbank Felder, die man mit TDBEdit verbunden hat, wird in der Regel auch nur das . oder das , erlaubt. Beim TFloatField kann man mit TFloatField.ValidChars noch das , und . hinzufügen. Beispiel:

Code: Alles auswählen

          If DefaultFormatSettings.DecimalSeparator = ',' Then
            TFloatField.ValidChars := TFloatField.ValidChars + ['.'] // Hinzufügen . als Dezmaltrennzeichen
          Else If DefaultFormatSettings.DecimalSeparator = '.' Then
            TFloatField.ValidChars := TFloatField.ValidChars + [','] // Hinzufügen , als Dezmaltrennzeichen
          Else TFloatField.ValidChars := TFloatField.ValidChars + [',', '.']; // Beide hinzufügen 
EleLa - Elektronik Lagerverwaltung - www.elela.de

Stevie
Beiträge: 180
Registriert: Di 27. Feb 2024, 22:40

Re: Erzwungene Locale geht nicht mit Linux.

Beitrag von Stevie »

Mathias hat geschrieben: Mo 3. Jun 2024, 19:25 ...
Nicht mal das geht, ohne die unit clocale.
...
Aber mit der Unit clocale geht es dann? Und geht es mit clocale dann komplett wie gewünscht?

PascalDragon
Beiträge: 981
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Erzwungene Locale geht nicht mit Linux.

Beitrag von PascalDragon »

Mathias hat geschrieben: Mo 3. Jun 2024, 19:25 So wie es scheint, wurstelt da die Unit System etwas im Hintergrund.

Nicht mal das geht, ohne die unit clocale.

Code: Alles auswählen

  function printf(str: PChar): Integer; varargs cdecl; external 'c';

begin
  printf('float: %f', 123.456);
end.  
Woher weis Pascal, was für eine Ländereinstellung das System hat ?
Da muss es für die Abfrage noch was anderes geben als die Umgebungsvariable "LANG".
Die clocale-Unit ruft als Teil ihrer Initialisierung die C-Funktion setlocale() auf, welche die Umgebungsvariablen auswertet und die Interna der C-Bibliothek entsprechend konfiguriert. Ohne diesen Aufruf hat auch ein C-Programm keinerlei Ahnung von den Spracheinstellungen.
FPC Compiler Entwickler

Antworten