Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2009-06

BoolToStr() with correct locale output

18 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi,

I'm busy translating our projects. fpGUI Toolkit uses it's own translation via .po files (similar to Lazarus projects). But now there are some output that is not being translated because it is output from the RTL. One such case is the output of BoolToStr().

How am I supposed to translate that, or must I implement my own fpgBoolToStr() to fpGUI project?

My default locale is en_ZA.UTF-8. Normally if I change the LANG environment variable, my fpGUI based projects look for those language translation .po files and if none is found, it reverts to the default compiled locale (normally English, but other languages can be selected as default)

======== Console output ==================
$ ./project1
True
False

$ export LANG=af_ZA

$ ./project1
True
False

$ locale
LANG=af_ZA
LC_CTYPE="af_ZA"
LC_NUMERIC="af_ZA"
LC_TIME=en_DK.UTF-8
LC_COLLATE="af_ZA"
LC_MONETARY="af_ZA"
LC_MESSAGES="af_ZA"
LC_PAPER="af_ZA"
LC_NAME="af_ZA"
LC_ADDRESS="af_ZA"
LC_TELEPHONE="af_ZA"
LC_MEASUREMENT="af_ZA"
LC_IDENTIFICATION="af_ZA"
LC_ALL=

==========================

=============  project1.pas  ===============
program project1;
{$mode objfpc}{$H+}
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, Sysutils;
var
  b: Boolean;
begin
  b := True;
  writeln(BoolToStr(b, True));
  b := False;
  writeln(BoolToStr(b, True));
end.
============================================

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 9 lines
Hi, I'm busy translating our projects. fpGUI Toolkit uses it's own translation via .po files (similar to Lazarus projects). But now there are some output that is not being translated because it is output from the RTL. One such case is the output of BoolToStr(). How am I supposed to translate that, or must I implement my own fpgBoolToStr() to fpGUI project?

No. The Boolean strings are exposed in from the sysutils unit, see TrueBoolStr, FalseBoolStr. The first string in those arrays is used. If there are no elements in those arrays, they are initialized with 'True' and 'False'.

So all you need to do is initialize them with the localized versions prior to the first call of BoolToStr().

Michael.

Show quoted text 72 lines
My default locale is en_ZA.UTF-8. Normally if I change the LANG environment variable, my fpGUI based projects look for those language translation .po files and if none is found, it reverts to the default compiled locale (normally English, but other languages can be selected as default) ======== Console output ================== $ ./project1 True False $ export LANG=af_ZA $ ./project1 True False $ locale LANG=af_ZA LC_CTYPE="af_ZA" LC_NUMERIC="af_ZA" LC_TIME=en_DK.UTF-8 LC_COLLATE="af_ZA" LC_MONETARY="af_ZA" LC_MESSAGES="af_ZA" LC_PAPER="af_ZA" LC_NAME="af_ZA" LC_ADDRESS="af_ZA" LC_TELEPHONE="af_ZA" LC_MEASUREMENT="af_ZA" LC_IDENTIFICATION="af_ZA" LC_ALL= ========================== ============= project1.pas =============== program project1; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, Sysutils; var b: Boolean; begin b := True; writeln(BoolToStr(b, True)); b := False; writeln(BoolToStr(b, True)); end. ============================================ Regards, - Graeme - _______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/ _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Graeme Geldenhuys
to Michael Van Canneyt
Michael Van Canneyt wrote
So all you need to do is initialize them with the localized versions prior to the first call of BoolToStr().

Thanks Michael. Now the other obvious question, why is TrueBoolStrs and FalseBoolStrs array types? Why not simply of type String?

  SetLength(TrueBoolStrs,1);
  TrueBoolStrs[0] := 'Waar';
  SetLength(FalseBoolStrs,1);
  FalseBoolStrs[0] := 'Onwaar';

Looking at the implementation of BoolToStr(), it only ever uses the first element. Reading the fpdoc help on BoolToStr and FalseBoolStrs it doesn't mention anything about why the are defined as arrays and what the other elements (if more than one) is used for.

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 20 lines
Michael Van Canneyt wrote: > > So all you need to do is initialize them with the localized versions > prior to the first call of BoolToStr(). Thanks Michael. Now the other obvious question, why is TrueBoolStrs and FalseBoolStrs array types? Why not simply of type String? SetLength(TrueBoolStrs,1); TrueBoolStrs[0] := 'Waar'; SetLength(FalseBoolStrs,1); FalseBoolStrs[0] := 'Onwaar'; Looking at the implementation of BoolToStr(), it only ever uses the first element. Reading the fpdoc help on BoolToStr and FalseBoolStrs it doesn't mention anything about why the are defined as arrays and what the other elements (if more than one) is used for.

StrToBool should use all elements ?

Michael.

Graeme Geldenhuys
to Michael Van Canneyt
Michael Van Canneyt wrote
StrToBool should use all elements ?

In FPC 2.2.5 it does not.

============ implementation  =====================
begin
 if UseBoolStrs Then
  begin
    CheckStrs;
    if B then
      Result:=TrueBoolStrs[0]
    else
      Result:=FalseBoolStrs[0];
  end
 else
  If B then
    Result:='-1'
  else
    Result:='0';
end;
======================================

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Vincent Snijders
to Graeme Geldenhuys: In FPC 2.2.5 it does not. ============ implementation ===================== begin if…
Graeme Geldenhuys wrote 22 lines
Michael Van Canneyt wrote: > StrToBool should use all elements ? In FPC 2.2.5 it does not. ============ implementation ===================== begin if UseBoolStrs Then begin CheckStrs; if B then Result:=TrueBoolStrs[0] else Result:=FalseBoolStrs[0]; end else If B then Result:='-1' else Result:='0'; end; ======================================

Please add the declaration, to make sure it is StrToBool

Vincent

Graeme Geldenhuys
to Vincent Snijders
Vincent Snijders wrote
Please add the declaration, to make sure it is StrToBool

I'm not that blind. :-) And the function in question in BoolToStr(). But now that you mention StrToBool(), that is even worse, it hard-codes the 'FALSE' and 'TRUE' and doesn't even use the arrays.

How come nobody ever noticed this? Does everybody only write English programs. :-)

==================================
function BoolToStr(B: Boolean;UseBoolStrs:Boolean=False): string;
procedure CheckStrs;
begin
    If Length(TrueBoolStrs)=0 then
      begin
        SetLength(TrueBoolStrs,1);
        TrueBoolStrs[0]:='True';
      end;
    If Length(FalseBoolStrs)=0 then
      begin
        SetLength(FalseBoolStrs,1);
        FalseBoolStrs[0]:='False';
      end;
end;
begin
 if UseBoolStrs Then
  begin
    CheckStrs;
    if B then
      Result:=TrueBoolStrs[0]
    else
      Result:=FalseBoolStrs[0];
  end
 else
  If B then
    Result:='-1'
  else
    Result:='0';
end;

==================================

function TryStrToBool(const S: string; out Value: Boolean): Boolean;
Var
  Temp : String;
  D : Double;
  Code: word;
begin
  Temp:=upcase(S);
  Val(temp,D,code);
  Result:=true;
  If Code=0 then
    Value:=(D0.0)
  else If Temp='TRUE' then
    Value:=true
  else if Temp='FALSE' then
    Value:=false
  else
    Result:=false;
end;

==================================

Regards,
- Graeme -

_______________________________________________________ fpGUI - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Vincent Snijders
to Graeme Geldenhuys
Graeme Geldenhuys wrote 5 lines
Vincent Snijders wrote: > Please add the declaration, to make sure it is StrToBool I'm not that blind. :-) And the function in question in BoolToStr(). But now that you mention StrToBool(), that is even worse, it hard-codes

I did not mention StrToBool first, Michael did, and you seemed to ignore that.

Vincent

Vincent Snijders
to Graeme Geldenhuys: I'm not that blind. :-) And the function in question in BoolToStr(). But now that you…
Graeme Geldenhuys wrote
How come nobody ever noticed this? Does everybody only write English programs. :-)

Because I always thought these function were not for users, but for systems, for example to store a boolean in a xml file or to create an adhoc dynamic SQL query. You would not want to have those strings translated (unless it an MS-Access system of last century).

Vincent

Henry Vermaak
to Vincent Snijders

2009/6/26 Vincent Snijders :

Show quoted text 10 lines
Graeme Geldenhuys schreef: > How come nobody ever noticed this? Does everybody only write English > programs. :-) > Because I always thought these function were not for users, but for systems, for example to store a boolean in a xml file or to create an adhoc dynamic SQL query. You would not want to have those strings translated (unless it an MS-Access system of last century).

I think even for config/system files they are useless, since it's a lot more friendly to support yes/no, true/false and on/off, not just true/false. I presume these functions are there for Delphi compatibility?

Henry

Graeme Geldenhuys
to Vincent Snijders: Because I always thought these function were not for users, but for systems, for example…
Vincent Snijders wrote
Because I always thought these function were not for users, but for systems, for example to store a boolean in a xml file or to create an

Your example is a good one and I agree there, but I do think it's for users to. For example, the whole reason I noticed the translation issue, was in my TStringGrid mediator. I displayed records (actually objects) that have a IsActive boolean property. The display mediator I use translates booleans to strings, displays TDateTime in the user specific format, displays TDateTime = 0 (ridiculous 1899-12-30 date) into something more user understandable, displays currencies as the users specified etc... Anyway, all worked except for the English True/False strings (from TTaxRate.IsActive property) return by BoolToStr() which should have been in Afrikaans. Or at least I expected it to be in Afrikaans or whatever other locale was active.

Regards,
- Graeme -

________________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Graeme Geldenhuys
to Henry Vermaak: 2009/6/26 Vincent Snijders : I think even for config/system files they are useless, since…
Henry Vermaak wrote
I think even for config/system files they are useless, since it's a lot more friendly to support yes/no, true/false and on/off, not just true/false.

Maybe that was the idea behind the TrueBoolStrs array. Element 0 is true/false, element 1 maybe yes/no, element 3 maybe on/off....? Either way, I did not find any documentation why there is an array used or what should actually be in it. The implementation of BoolToStr and StrToBool does give any clues either, because they always use element 0 or a hardcoded string value in English.

So I take it you agree with Vincent, that I should basically never user BoolToStr or StrToBool for user displayed values and rather duplicate the code in my own application which supports translated values? And then use the SysUtils version for config files or database stored value? Again, nothing like this is hinted at in the documentation. I'll double check on Monday what the Kylix 3 help says regarding BoolToStr and StrToBool and localization and when it should actually be used.

Regards,
- Graeme -

________________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

John Coppens
to Henry Vermaak: 2009/6/26 Graeme Geldenhuys : Because it's so simple/trivial that everyone rolls their…
> How come nobody ever noticed this? Does everybody only write English > programs. :-)

I _hate_ to think of the consequences of localization of those strings. Have we had enough of the . and , problem? I don't think we need another cause for incompatibilities in data files. Localization should be done by the application program which assigns a meaning to the variable, not by Pascal.

Boolean values tend to represent too many things, apart from TRUE and FALSE. Like FULL and EMPTY, FAST and SLOW, and so on. To me it makes sense that booleans are stored as bits, and, if _really_ necessary, shown as TRUE or FALSE, mainly for debugging purposes. Wirth's Pascal definition specifies the use of TRUE and FALSE.

Just my $.02

John

Giuliano Colla
to Graeme Geldenhuys: Maybe that was the idea behind the TrueBoolStrs array. Element 0 is true/false, element 1…

Graeme Geldenhuys ha scritto:

Again, nothing like this is hinted at in the documentation. I'll double check on Monday what the Kylix 3 help says regarding BoolToStr and StrToBool and localization and when it should actually be used.

Kylix 3 help on TrueBoolStrs variable specifies:
<quote>
When using the BoolToString function, true values are converted to the first string of the list. When using the StrToBool function, any string in the list is converted to true.
</quote>
The same for FalseBoolStrs variable, of course.

Apparently the mechanism is intended to convert from human understandable or localized strings to standardized TRUE/FALSE strings. The opposite of what you needed. No wonder it fails for you.

Giuliano Colla Whenever people agree with me, I always feel I must be wrong (O. Wilde)
Michael Van Canneyt
to Giuliano Colla
Giuliano Colla wrote 16 lines
Graeme Geldenhuys ha scritto: > Again, nothing like this is hinted at in the documentation. I'll double > check on Monday what the Kylix 3 help says regarding BoolToStr and > StrToBool and localization and when it should actually be used. > Kylix 3 help on TrueBoolStrs variable specifies: <quote> When using the BoolToString function, true values are converted to the first string of the list. When using the StrToBool function, any string in the list is converted to true. </quote> The same for FalseBoolStrs variable, of course. Apparently the mechanism is intended to convert from human understandable or localized strings to standardized TRUE/FALSE strings. The opposite of what you needed. No wonder it fails for you.

But there is a bug in strtobool: it does not check all elements in the list. (in fact, none) So that must be fixed.

Michael.