Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.
Quante volte è capitato di dirsi, però ora che ho fatto il programma se lo rendessi multilingua potrei distribuirlo in numero maggiore! Bene questo tutorial spiega i passi per rendere il vostro software multilingua in maniera semplice e multipiattaforma. Tutto questo con l'ausilio dei file INi.
Bene per prima cosa necessitiamo di un file ini che chiameremo lingue.ini (nella stessa cartella dell'eseguibile), così strutturato.
[Lingue]
; in questa zona dichiaro le lingue che andrò ad implementare nel mio programma
Come seconda cosa andiamo ad analizzare un po di codice Free Pascal per interagire con tale file INI. Creiamo un nuovo progetto con una form che si chiama Form1 e aggiungete tre componenti, una TComboBox e due TLabel. Ecco come sarà il sorgente
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls
,INIFiles {libreria per usare i file ini}
;
type
{ TForm1 }
TForm1 = class(TForm)
Cmb_Lingue: TComboBox;
Lbl_Nome: TLabel;
Lbl_Cognome: TLabel;
procedure Cmb_LingueChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ private declarations }
procedure CambiaLingua();
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
{ In fase di caricamento delle form inserisco nella combobox le possibili lingue inserite nel file ini}
procedure TForm1.FormCreate(Sender: TObject);
Var
INI:TINIFile;
Numero, i: integer;
begin
INI := TINIFile.Create(Application.Location + 'lingue.ini');
Numero := StrToInt(INI.ReadString('Lingue','Numero',''));
for i:=1 to Numero do
begin
Cmb_Lingue.Items.Add(INI.ReadString('Lingue','Lingua' + IntToStr(i),''));
end;
Ini.Free;
Cmb_Lingue.Text:=Cmb_Lingue.Items.Strings[0];
CambiaLingua();
end;
{ Al cambiamento del contenuto della ComboBox cambio i valori delle label }
procedure TForm1.Cmb_LingueChange(Sender: TObject);
begin
CambiaLingua();
end;
procedure TForm1.CambiaLingua();
var
i: integer;
INI:TINIFile;
Lingua: string;
begin
Lingua:=Cmb_Lingue.Text;
INI := TINIFile.Create(Application.Location + 'lingue.ini');
for i:=0 to Form1.ComponentCount-1 do
begin
Form1.Controls[i].Caption:=INI.ReadString(Lingua,Form1.Components[i].Name,'');
end;
Ini.Free;
Cmb_Lingue.Text:=Lingua;
end;
end.
Il codice è abbastanza semplice, è facile dedurne il funzionamento compilandolo. Se avete soluzioni migliori o alternative (ma sempre il più possibile multipiattaforma) mandatemeli tramite messaggio, io provvederò a pubblicarli.
Esempio: www.lazaruspascal.it/esempi/Multilingua.zip
file lingue.ini
[lingue]
Numero=2
Default=1
[descrizione]
Lingua1=italiano
Lingua2=inglese
file di supporto italiano.lng e inglese.lng con il nome del componente e la sua traduzione
Lbl_Nome=Nome
Lbl_Cognome=Cognome
BtClose=Chiudi
in fine il sorgente
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls
,INIFiles {libreria per usare i file ini}
;
type
{ TForm1 }
TForm1 = class(TForm)
BtClose: TButton;
Cmb_Lingue: TComboBox;
Edit1: TEdit;
Edit2: TEdit;
Lbl_Nome: TLabel;
Lbl_Cognome: TLabel;
procedure BtCloseClick(Sender: TObject);
procedure Cmb_LingueChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ private declarations }
procedure CambiaLingua();
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
uses TypInfo;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
Var
INI:TINIFile;
Numero, i, nDefault: integer;
sLingua: String;
begin
INI := TINIFile.Create(Application.Location + 'lingue.ini');
Try
Numero := StrToInt(INI.ReadString('lingue','Numero',''));
nDefault := StrToInt(INI.ReadString('lingue','Default',''));
for i:=1 to Numero do
begin
sLingua := INI.ReadString('descrizione','Lingua' + IntToStr(i),'');
Cmb_Lingue.Items.Add(sLingua);
end;
Cmb_Lingue.Text:=Cmb_Lingue.Items.Strings[nDefault-1];
CambiaLingua;
finally
Ini.Free;
end;
end;
procedure TForm1.Cmb_LingueChange(Sender: TObject);
begin
CambiaLingua;
end;
procedure TForm1.BtCloseClick(Sender: TObject);
begin
Application.terminate;
end;
procedure TForm1.CambiaLingua;
var
i: integer;
sFile: String;
oStringa: TStringList;
oComp: TComponent;
PropInfo: PPropInfo;
begin
oStringa := TStringList.create;
Try
sFile := (Cmb_Lingue.Items[Cmb_Lingue.ItemIndex]);
oStringa.LoadFromFile(sFile+'.lng');
For i:= 0 to oStringa.Count-1 do
begin
oComp := FindComponent(oStringa.Names);
if Assigned(oComp) then
begin
PropInfo := GetPropInfo (oComp.ClassInfo, 'Caption'); // siamo sicuri che ci sia la caption
if Assigned(PropInfo) then // se c'e' allora cast a tcontrol e assegno
(oComp as TControl).Caption := oStringa.Values[oStringa.Names]
end;
end;
finally
oStringa.Free;
end;
end;
end.
Il tutto è rimasto simile all'originale, un ulteriore miglioria sarebbe di andare a beccare tutti i componenti caption con rtti.
G.
procedure TForm1.CambiaLingua;
var
i: integer;
sFile: String;
oStringa: TStringList;
oComp: TComponent;
PropInfo: PPropInfo;
begin
oStringa := TStringList.create;
Try
sFile := (Cmb_Lingue.Items[Cmb_Lingue.ItemIndex]);
oStringa.LoadFromFile(sFile+'.lng');
For i:= 0 to oStringa.Count-1 do
begin
oComp := FindComponent(oStringa.Names[i]);
if Assigned(oComp) then
begin
PropInfo := GetPropInfo (oComp.ClassInfo, 'Caption'); // siamo sicuri che ci sia la caption
if Assigned(PropInfo) then // se c'e' allora cast a tcontrol e assegno
(oComp as TControl).Caption := oStringa.Values[oStringa.Names[i]];
end;
end;
finally
oStringa.Free;
end;
end;
[\CODE]
Non l'ho mai usato, a dire il vero, ma mi pare abbastanza potente e versatile:
http://wiki.lazarus.freepascal.org/Translations_/_i18n_/_localizations_for_programs
http://www.ailis.de/~k/archives/42-I18N-with-Lazarus.html