Lazarus 3.0 (2023.12.21.)
Letöltés

  • Oldal:
  • 1

TÉMA:

Válasz:Lazarusszal többnyelvű alkalmazás fejlesztése 2010 dec. 28 22:24 #679

  • Athomas
  • Athomas profilkép
  • Moderátor
  • Moderátor
  • Sör, virsli, Lazarus
  • Hozzászólások: 46
  • Köszönetek: 0
Sziasztok!

Szükségem lett nekem is többnyelvűvé tenni az
alkalmazásomat, és úgy tűnik nagyobb probléma
nélkül sikerült. Ezen a linken viszonylag jó
leírást
találtam. A Projekt beállítások alatt az i18-at engedélyezni
kell, és kijelölni az ide által előállított .po fájl mentési
könyvtárát. A projekt fordításakor elkészíti az alap nyelvi
fájlt, és menti a kijelölt könyvtárba.
Én ezután poedit-el szerkesztettem.
A Lazarus jelenlegi stabil verzióját (0.9.28.2)használom, amihez
szükséges egy PoTranslator nevű unitot csatolni a projekthez.
Ennek a forrása megtalálható a fenti linken. Ezt egyszerűen kimásoltam, és beillesztettem a projektbe.
Állítólag a jelenlegi snapshot-ban ez már nem is kell, és
januárban jön a 0.9.30-as verzió.
A unit1-ben az initialization rész után beillesztettem a
következő sort:
LRSTranslator := TPoTranslator.Create('Reflow.hu.po');

Ettől elkezdett működni.

Sajnos a unitokban elhelyezett stringeket nem veszi fel
a .po fájlba,

mert az .lfm fájlból veszi az adatokat, de ezen

dolgozom.

Válasz:Lazarusszal többnyelvű alkalmazás fejlesztése 2010 okt. 11 20:45 #617

  • szeti
  • szeti profilkép
  • Haladó forumozó
  • Haladó forumozó
  • Hozzászólások: 39
  • Köszönetek: 1
Üdv Mindenkinek!

Szomorúan vettem tudomásul, hogy a Lazarus jelenlegi verziója nem túl erős a multilanguage kérdéskörben. A .po. file-ok előállítása során is tapasztaltam olyan komponenseket, melyek jellemzőit nem válogatta le. Készítettem egy kis Unit-ot, mely egyszerűbb alkalmazások esetén képes ezt a problémát kiváltani. A SaveLanguage eljárás elkészíti a language_hu.lng file-t, melyben a le kell fordítani a magyar szöveget a kívánt nyelvre, majd átnevezni (pl. language_en.lng). Ezt követően a LoadLanguage eljárás alkalmas a megfelelően beállított nyelvi file alapján lefordítani az éppen megjelenített Form-ot. A forráskódba ágyazott szövegekre célszerű valamiféle adatbázist felépíteni, (nálam sqlite-al oldottam meg) melyből a "Shower(S1,S2:string; S3:Integer) eljárás jeleníti meg a kívánt üzenetet. Ami még jó benne, hogy különböző komponensekre tovább fejleszthető. Azért aki Report-ot használ, (pl LazReport) az küzdhet még egy kicsit, mert annak a problémáját sajnos ez a Unit nem oldja meg. Ja igen ahhoz, hogy működjön is a dolog a MainForm onCreate eseményében regisztrálni kell azokat az osztályokat, melyekből a program indulásakor el nem indított formok előállíthatók a SaveLanguage eljárás részére (RegisterClasses([TForm3,TForm4,...])).

Azért ha valakinek van véleménye érdekelne, hogyan lehetne jobbá tenni?

Kód:
unit Language;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, TypInfo, IniFiles, Dialogs, Forms, DbCtrls, DBGrids;
 
  procedure LoadLanguage;
  procedure SaveLanguage;
  procedure Shower(S1,S2:string; S3:Integer);
 
var langvar: string;
 
implementation
uses UDataModule, UnitMain;
 
 
procedure LoadLanguage;
var Lng: TIniFile;
    Dir,S: String;
    VarForm: TForm;
    lngfile: file of char;
 
    procedure ComponentRead(Form: TForm);
    var j,k: integer;
        S: String;
    begin
      with Form do
      begin
      for j:=0 to ComponentCount-1 do
      begin
       If IsPublishedProp(Components[j],'Caption') then
       begin
       S:=Lng.ReadString(Name,Components[j].Name+'_Caption','');
       SetPropValue(Components[j],'Caption',S);
       end;
 
       If IsPublishedProp(Components[j],'Hint') then
       begin
       S:=Lng.ReadString(Name,Components[j].Name+'_Hint','');
       SetPropValue(Components[j],'Hint',S);
       end;
 
       If (IsPublishedProp(Components[j],'Hints') and (Components[j].ClassName='TDBNavigator')) then
       begin
        for k:=0 to (components[j] as TDBNavigator).ControlCount-1 do
        begin;
         S:=Lng.ReadString(Name,Components[j].Name+'_Strings'+IntToStr(k),'');
         (Components[j] as TDBNavigator).Hints.Strings[k]:=S;
        end;
       end;
 
       If (IsPublishedProp(Components[j],'Items') and (Components[j].ClassName='TDBComboBox')) then
       begin
        for k:=0 to (components[j] as TDBComboBox).Items.Count-1 do
        begin;
         S:=Lng.ReadString(Name,Components[j].Name+'_ItemStrings'+IntToStr(k),'');
         (Components[j] as TDBComboBox).Items.Strings[k]:=S;
        end;
       end;
 
       If (IsPublishedProp(Components[j],'Columns') and (Components[j].ClassName='TDBGrid')) then
       begin
        for k:=0 to (components[j] as TDBGrid).Columns.Count-1 do
        begin;
         S:=Lng.ReadString(Name,Components[j].Name+'_Columns'+IntToStr(k),'');
         (Components[j] as TDBGrid).Columns.Items[k].Title.Caption:=S;
        end;
       end;
 
// Tóvábbi komponenseket lehet bekódolni.
//       If (IsPublishedProp(Components[j],'Items') and (Components[j].ClassName='TPopupMenu')) then
//       begin
//        for k:=0 to (components[j] as TPopupMenu).Items.Count-1 do
//        begin;
//         Lng.WriteString(Name,(Components[j].Name+'_Item'+IntToStr(k)),(components[j] as TPopupMenu).items.items[k].Caption);
//        end;
//       end;
 
      end;
      end;
    end;
 
begin
 S:='';
 IF not (FileExists(DM1.ZTParam.FieldByName('langdir').AsString+DM1.ZTParam.FieldByName('langfile').AsString))then
  begin
    Dir:=GetCurrentDir();
    SetCurrentDir(DM1.ZTParam.FieldByName('langdir').AsString);
    Shower('Language',langvar,1);
    if DM1.ZTParam.FieldByName('langfile').AsString<>'language_hu.lng' then
    begin
     DM1.ZTParam.Edit;
     DM1.ZTParam.FieldByName('langfile').AsString:='language_hu.lng';
     DM1.ZTParam.Post;
    end else
    begin
     AssignFile(lngfile, UTF8ToSys('language_hu.lng'));
     Rewrite(lngfile);
     CloseFile(lngfile);
    end;
  End else begin
             Dir:=GetCurrentDir();
             SetCurrentDir(DM1.ZTParam.FieldByName('langdir').AsString);
           end;
  Lng := TINIFile.Create(DM1.ZTParam.FieldByName('langfile').AsString);
 
 VarForm:=Screen.ActiveForm;
 if DM1.ZTParam.FieldByName('langfile').AsString<>'language_hu.lng' then
 begin
  with VarForm do
  begin
    S:=Lng.ReadString(Name,Name+'_Caption','');
    SetPropValue(VarForm,'Caption',S);
    S:=Lng.ReadString(Name,Name+'_Hint','');
    SetPropValue(VarForm,'Hint',S);
    ComponentRead(VarForm);
  end;
 end;
 
 SetCurrentDir(Dir);
 Lng.Destroy;
 
 end;
 
procedure SaveLanguage;
type TombIDX1=array of string;
var i,j,k,l: integer;
    Lng: TIniFile;
    Dir,Sstr: String;
    lngfile: file of char;
    VarForm: TForm;
    FormsStr: TombIDX1;
 
       procedure ComponentWrite(Form:TForm);
       var j,k: integer;
       begin
        With Form do
        begin
        for j:=0 to ComponentCount-1 do
        begin
         If IsPublishedProp(Components[j],'Caption') then Lng.WriteString(Name,Components[j].Name+'_Caption',GetPropValue(Components[j],'Caption'));
         If IsPublishedProp(Components[j],'Hint') then Lng.WriteString(Name,Components[j].Name+'_Hint',GetPropValue(Components[j],'Hint'));
 
         If (IsPublishedProp(Components[j],'Hints') and (Components[j].ClassName='TDBNavigator')) then
         begin
          for k:=0 to (components[j] as TDBNavigator).ControlCount-1 do
          begin;
           Lng.WriteString(Name,Components[j].Name+'_Strings'+IntToStr(k),(components[j] as TDBNavigator).Hints.Strings[k]);
          end;
         end;
 
         If (IsPublishedProp(Components[j],'Items') and (Components[j].ClassName='TDBComboBox')) then
         begin
          for k:=0 to (components[j] as TDBComboBox).Items.Count-1 do
          begin;
           Lng.WriteString(Name,Components[j].Name+'_ItemStrings'+IntToStr(k),(components[j] as TDBComboBox).Items.Strings[k]);
          end;
         end;
 
         If (IsPublishedProp(Components[j],'Columns') and (Components[j].ClassName='TDBGrid')) then
         begin
          for k:=0 to (components[j] as TDBGrid).Columns.Count-1 do
          begin;
           Lng.WriteString(Name,Components[j].Name+'_Columns'+IntToStr(k),(components[j] as TDBGrid).Columns.Items[k].Title.Caption);
          end;
         end;
 
//További komponenseket lehet bekódolni szükég esetén.
//         If (IsPublishedProp(Components[j],'Items') and (Components[j].ClassName='TPopupMenu')) then
//         begin
//          for k:=0 to (components[j] as TPopupMenu).Items.Count-1 do
//          begin;
//           Lng.WriteString(Name,(Components[j].Name+'_Item'+IntToStr(k)),(components[j] as TPopupMenu).items.items[k].Caption);
//          end;
//         end;
 
        end;
        end;
       end;
 
begin
 FormsStr:=nil;
 IF not (FileExists(DM1.ZTParam.FieldByName('langdir').AsString+'language_hu.lng'))then
  begin
    Dir:=GetCurrentDir();
    SetCurrentDir(DM1.ZTParam.FieldByName('langdir').AsString);
    AssignFile(lngfile, UTF8ToSys('language_hu.lng'));
    Rewrite(lngfile);
    CloseFile(lngfile);
  End else begin
             Dir:=GetCurrentDir();
             SetCurrentDir(DM1.ZTParam.FieldByName('langdir').AsString);
           end;
  Lng := TINIFile.Create('language_hu.lng');
  Lng.WriteString('Language','Ver.','1.0');
 
//A létező (futásidőben létrehozott) formok adatait helyezi be az lng-be.)
 for i:= Screen.FormCount-1 downto 0 do with Screen.Forms[i] do
 begin
  VarForm:=Screen.Forms[i];
  Lng.WriteString(Name,Name+'_Caption',Caption);
  Lng.WriteString(Name,Name+'_Hint',Hint);
  ComponentWrite(VarForm);
 end;
 
//A Work.ini- formsname szekcióban szereplő adatai alapján a formok létrehozása.
 l:=1;
 j:=0;
 Sstr:=Form1.ini.ReadString('formsname','Forms','');
 
 if length(Sstr)>0 then
 begin
   for k:=1 to length(Sstr) do
   begin
    if (Sstr[k]=',') or (Sstr[k]=';') then l:=l+1;
   end;
   setlength(FormsStr,l);
   for k:=1 to length(Sstr) do
   begin
    if (Sstr[k]<>',') and (Sstr[k]<>';') then FormsStr[j]:=FormsStr[j]+Sstr[k] else j:=j+1;
   end;
 end;
 
 for j:=0 to l-1 do
 begin
  VarForm:=TFormClass(FindClass(FormsStr[j])).Create(Application);
  Lng.WriteString(VarForm.Name,VarForm.Name+'_Caption',VarForm.Caption);
  Lng.WriteString(VarForm.Name,VarForm.Name+'_Hint',VarForm.Hint);
  ComponentWrite(VarForm);
  VarForm.Destroy;
 end;
 
 SetCurrentDir(Dir);
 Lng.Destroy;
 
end;
 
{**************************Hiba és üzenet kiírása adatbázisból*************************}
procedure Shower(S1,S2:string; S3:Integer);
  begin
   DM1.ZTShow.Close;
   DM1.ZTShow.SQL.Clear;
   DM1.ZTShow.SQL.Add('select * from help where unitkod=:p0 and lngkod=:p1 and ssz=:p2');
   DM1.ZTShow.Parambyname('p0').AsString:=S1;
   DM1.ZTShow.Parambyname('p1').AsString:=S2;
   DM1.ZTShow.Parambyname('p2').AsInteger:=S3;
   DM1.ZTShow.Open;
 
   ShowMessage('>> '+Trim(DM1.ZTShow.FieldByName('uzenet').AsString)+' <<');
 
  end;
 
 
end.

Válasz:Lazarusszal többnyelvű alkalmazás fejlesztése 2010 szept. 29 11:17 #607

  • szeti
  • szeti profilkép
  • Haladó forumozó
  • Haladó forumozó
  • Hozzászólások: 39
  • Köszönetek: 1
Üdv. Mindenkinek!

Azért eleveníteném fel ezt a témakört, mert érdekelne, sikerült-e megoldani a multilanguage problémát? Írtam egy kis alkalmazást, melyet szeretnék lefordítani néhány nyelvre. Az appl.xx.po file-ok előállítása megtörtént, azonban a "wiki.lazarus.freepascal.org/Getting_translation_strings_right" helyen található TranslateLCL eljárás nálam nem működik. Befordul hibátlanul, de nem cseréli le az alkalamazás szövegmezőit.

Válasz:Lazarusszal többnyelvű alkalmazás fejlesztése 2008 dec. 22 14:49 #284

  • Gábor
  • Gábor profilkép
  • Adminisztrátor
  • Adminisztrátor
  • Hozzászólások: 504
  • Köszönetek: 86
Nem írtad, hogy konzolos vagy GUI alkalmazásról van-e szó...

A Lazarus WIKI-ben ezt találtam:
wiki.lazarus.freepascal.org/Translations_/_i18n_/_localizations_for_programs

A FreePascal/Lazarus dokumentációk telepítése után vagy a neten a Free Component Library (FCL) csomag súgójában megtalálhatod a GetText unit-ot is:
www.freepascal.org/docs-html/fcl/gettext/index.html

A prog.hu-n pedig ezt a módszert is megtalálhatod GUI alkalmazásokhoz:
www.prog.hu/tudastar/24276/Tobb+nyelvu+alkalmazasok+letrehozasa+Delphi-ben.html

Az első kettő inkább konzolos programokhoz jó, bár a resourcestrings cseréje elvileg GUI alkalmazásoknál is működik.

A harmadik direkt GUI alkalmazásokhoz lett kitalálva. Ehhez hasonló megoldást tartalmazó unitot írtam magamnak én is... lehet egyszer fel is töltöm ide...
Hogyan kérdezzünk okosan? / Mit kell tennünk kérdezés előtt? -- Lazarus 3.0 -- FPC 3.2-- GNU/Linux 5.15.0 x86_64

Lazarusszal többnyelvű alkalmazás fejlesztése 2008 dec. 18 21:48 #280

  • cspal
  • cspal profilkép Témaindító
  • Új tag
  • Új tag
  • Hozzászólások: 1
  • Köszönetek: 0
Tiszteletem!

Van egy egyenlőre elég egyszerű alkalmazásom, freepascal -ban fejlesztem, Lazarusszal.

Lazarus verziója 0.9.26 beta
fpc verziója 2.2.2-0

Érdeklődöm, hogy mi jelenleg a legegyszerűbb módja annak, hogy az alkalmazásom többnyelvűvé tegyem?

Már elkészítettem a
név.hu.po,
név.po
név.hu.mo
név.mo

állományokat, de hogyan tovább?

Nincs még ennek egy automatizált módja Lazaruszban?

Ezt a kérdést már egyszer föltettem az angol nyelvű Lazarus fórumon, s a következő választ kaptam:

Some work has been done on automatic storing the forms strings into .po
files and reading them back again. But there are many things left to
do. That's why there is only a simple unit (lcl/defaulttranslator.pas)
to load the strings. And this comes without documentation and has
several limitations.

Maybe it's better to use ResourceStrings.


Hogyan kell többnyelvűvé tennem az alkalmazásomat?
Van-e erre valahol egy szájbarágós leírás?
Üdvözlettel,
Pál

  • Oldal:
  • 1