Re: Saving strings to ini file

From: Bruce Roberts (ber_at_bounceitattcanada.xnet)
Date: 01/25/05


Date: Tue, 25 Jan 2005 15:09:56 -0500


"Raptor" <bogus@none.com> wrote in message
news:ct4ckj01omo@news2.newsguy.com...

> Writing code to read and write an ini for captions, hints and other text
> data from components--to create a file for translation into other
> languages--was an interesting exercise. TIniFile and TStringList are easy
> and complementary in their function. My test app creates data like this:

I doubt that I would use an ini file simply because of the size its going to
reach in most applications. I tend to use an embedded db table, i.e.
something that compiles directly into the app - something like DBISAM.

I've tried two different approaches to coding things. The first was to
create descedants of all the controls to be used embeding the translation in
the appropriate property Set methods. The second, and simpler to code was a
routine that is called by Forms' Loaded method. It goes through and
translates/looksup the form Caption, Hint, etc. properties as well as those
of any owned controls.

> There's probably an (or many) elegant and obvious way(s) to write and read
> other string constants, things normally declared like
>
> const
> ermLangFileMissing = 'Selected language file not present in program
> folder.';

Well there is the Delphi's ResourceString. What I tend to use is a function
that is able translate and do parametric replacement.

A class that encapsulates translation behavior works for me. Something like

tCustomTranslator = class (tObject)
  private
     fDisplayLanguage : tDisplayLanguage;
     fLanguageChange : tNotifyEvent;
     procedure SetDisplayLanguage (dispLang : tDisplayLanguage);
     function GetTranslation (key : string) : string;
  protected
     function Lookup (const key : string; var rslt : string) : boolean;
virtual; abstract;
     procedure doLanguageChange; virtual;

     property DisplayLanguage : tDisplayLanguage read fDisplayLanguage write
SetDisplayLanguage;
     property Translation [key : string] : string read GetTranslation;
default;
     property LanguageChange : tNotifyEvent read fLanguageChange write
fLanguageChange;
  public
     procedure TranslateControl (aControl : tControl); virtual;
     function Translate (const key : string) : string; overload;
     function Translate (const key, dflt : string) : string; overload;
virtual;
     function Translate (const key, dflt : string; replacements : array of
string) : string; overload;
  end;

>From which descendants can be created to cater for different translation
sources. In the OP case, perhaps something like (while the code compiles,
none of its tested)

tTranslatorIniF = class (tCustomTranslator)
  private
     fIniFName : string;
     fStrings : tIniFile;
     procedure SetIniFilename (fName : string);
  protected
     function Lookup (const key : string; var rslt : string) : boolean;
override;
  public
     destructor Destroy; override;
     property Translation;
  published
     property IniFilename : string read fIniFName write SetIniFilename;
     property DisplayLanguage;
     property LanguageChange;
  end;

function tCustomTranslator.Translate (const key, dflt : string) : string;

begin
if not Lookup (key, result)
then result := dflt;
end;

function tCustomTranslator.Translate (const key, dflt : string; replacements
: array of string) : string;

var i : integer;

begin
result := Translate (key, dflt);
for i := Low (replacements) to High (replacements) do
   result := StringReplace (result, '%' + intToStr (i), Translate
(replacements [i]), [rfReplaceAll, rfIgnoreCase]);
end;

procedure tCustomTranslator.TranslateControl (aControl : tControl);

     function OwnerName (aControl : tComponent) : string;

     begin
     if Assigned (aControl)
     then begin
       if aControl.Name = ''
       then result := aControl.ClassName + '.'
       else result := aControl.Name + '.';
       result := OwnerName (aControl.Owner) + result;
       end
     else result := '';
     end;

var key : string;
     i : integer;
     c : tControlHack;

begin
c := tControlHack (aControl);
key := OwnerName (c.Owner) + aControl.Name + '.';
c.Caption := Translate (key + 'Caption', c.Caption);
c.Hint := Translate (key + 'Hint', c.Hint);
for i := 0 to (aControl.ComponentCount - 1) do
   begin
   if aControl.Components [i] is tControl
   then begin
       c := tControlHack (aControl.Components [i]);
       key := OwnerName (c);
       c.Caption := Translate (key + 'Caption', c.Caption);
       c.Hint := Translate (key + 'Hint', c.Hint);
       end;
   end;
end;

Positioning adjustments are really better done through careful design and
use of the Anchors property. Its messy work otherwise.



Relevant Pages

  • Re: Replace Count
    ... If you want to know the number of replacements required then it would be faster to run through the string first using InString in a loop and modifying the Start parameter within the loop to each time point to the first character after the previously found substring. ... Firstly, in your code you are replacing multiple vbCr characters whereas most standard Windows .txt files use the character pair vbCrLf instead of just a vbCr character, so presumably you are working with a text file that does use just vbCr to signify a new line, of which of course there are many, but you do need to know which kind of text file you are working with. ... Dim OldPointer As Long, NewPointer As Long ...
    (microsoft.public.vb.general.discussion)
  • Re: Multi-Language Site
    ... a meaningfull string would be a better option IMO, ... GetTrans(StringId, LanguageId) function, to fetch the wanted translated ... and also request them by page (less data to request = ... you might consider storing all translation data in the Application ...
    (microsoft.public.inetserver.asp.db)
  • Re: Which is this sentence
    ... But in order to achieve this translation ... is objectionable in NAFL). ... This superposition state is similar to the Schrodinger cat's ... Now define the "fixed point term" for any string S to be ...
    (sci.logic)
  • Re: Variable length/precision formats?
    ... Yes, it's standard conforming. ... The first is a string in which replacements will occur. ... The second is a pattern which will be replaced. ...
    (comp.lang.fortran)
  • Re: What is considered to be good material for a trem sustain block?
    ... The vibration of the string is transferred through the saddle, bridge, ... The sound you hear is from the pickups, ... I replaced the potmetal block on a 80's MIJ ESP Strat ... replacements. ...
    (alt.guitar)