Written by xinyiman Ottobre 24, 2011, 11:47:00 pm21554 ViewsRating: 0 (0 Rates)Print
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
Numero=2
Lingua1=italiano
Lingua2=inglese
[italiano]
;notare che italiano è tutto minuscolo per essere uguale alla lingua dichiarata sopra nella sezione Lingue
;per non creare problematiche di alcun tipo in sistemi operativi case-sensitive
Lbl_Nome=Nome
Lbl_Cognome=Cognome
[inglese]
Lbl_Nome=Name
Lbl_Cognome=Surname
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}
;
{ 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.
xinyiman registered at Italian community of Lazarus and Free Pascal on Ottobre 14, 2011, 10:56:28 pm and has posted 3263 posts in the boards since then. Last visit was Oggi alle 09:12:20 am.
Written by Goblin
il Ottobre 25, 2011, 11:36:38 am
Prendendo spunto dal sorgente ho effettuato qualche piccolqa modifica, spostando la logica solo sulle traduzioni, fondamentalmente perchè non mi piaceva il ciclo for su tutti i componenti, se nella mia form ci sono 100 componenti immagine e 2 label devo aspettare 100 iterazioni .. allora ho invertito le carte in tavola leggo il file delle traduzioni e cerco i componenti da tradurre, ho modificato leggermente il sorgente e i file ini.
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.
2) Re: Realizzare programmi multilingua
Written by Goblin
il Ottobre 25, 2011, 11:49:34 am
mm ci deve essere qualche bug oppure ho sbagliato qualcosa ... ma il sorgente contiene alcuni errori ... vediamo se adesso viene postato in forma corretta
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]
3) Re: Realizzare programmi multilingua
Written by Legolas
il Ottobre 25, 2011, 12:32:01 pm
C'è anche un modo nativo per gestire diverse lingue nelle applicazioni fatte con Lazarus: i18n.
Non l'ho mai usato, a dire il vero, ma mi pare abbastanza potente e versatile:
Questo blog non rappresenta una testata giornalistica poiché viene
aggiornato senza alcuna periodicità. Non può pertanto considerarsi un
prodotto editoriale ai sensi della legge n. 62/2001.
Questo sito utilizza cookie, anche di terze parti, per offriti servizi in linea con le tue preferenze. Chiudendo questo banner, scorrendo questa pagina, cliccando su un link o proseguendo la navigazione in altra maniera, acconsenti all’uso dei cookie.
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.