Çoklu dil desteği

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
dost
Üye
Mesajlar: 104
Kayıt: 08 Oca 2004 11:33

Çoklu dil desteği

Mesaj gönderen dost »

Merhaba;

Programa çoklu dil seçeneği eklemek istiyorum.

Kod: Tümünü seç

var
  Form1: TForm1;
  MyIni : TIniFile;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  MyIni := TiniFile.Create(GetCurrentDir + '\turkce.lng');
  Label1.Caption := MyIni.ReadString('TLabel','Label1.Caption','N/A');
  Label2.Caption := MyIni.ReadString('TLabel','Label2.Caption','N/A');
  Button1.Caption := MyIni.ReadString('TButton','Button1.Caption','N/A');
  Button2.Caption := MyIni.ReadString('TButton','Button2.Caption','N/A');
  MyIni.Free;
end;
Bu konudaki seçenekler hakkında kodla kısa bilgi verebilirmisiniz ?
Teşekkürler
dost
Üye
Mesajlar: 104
Kayıt: 08 Oca 2004 11:33

Mesaj gönderen dost »

Merhaba;

Arkadaşlar bu konu ile ilgili örnek bulabileceğim link verebilirmisiniz ?

Teşekkürler.
Kullanıcı avatarı
NewMember
Üye
Mesajlar: 990
Kayıt: 29 Haz 2005 06:57
Konum: Bursa

Mesaj gönderen NewMember »

Aslında cevabı kendin vermişsin.Olay Basit.Ini dosya ya da herhengi bir mantıkla hazırlayacağın Tetx dosya dan okutacaksın label ve butonların captionlarını.Ve her dil içn bir dosya hazırlayıp kullanıcının seçimine göre dosyayı yükleyeceksin.Ancak burada şuna dikkat etmelisin.Captionlar her dilde aynı karakter sayısına sahip olmayacağından olmayacağından buton ve labellerin width ve height özelliklerini her dile uyacak şekilde hazırlamalısın.Yani dizayn problemleri olabilir.Ama genel mantığı zaten kendin söylemişsin.
Kolay gelsin.
dost
Üye
Mesajlar: 104
Kayıt: 08 Oca 2004 11:33

Mesaj gönderen dost »

Merhaba;

Form da birçak label, button vs. var,
form create ederken ini dosyasından okutuyorum.
bunu daha kısa kodla ini dosyasını TStringlist e atarak
döngü ile nasıl yapabilirim.

Teşekkürler.
Kullanıcı avatarı
mege
Admin
Mesajlar: 2360
Kayıt: 05 Şub 2004 04:32
Konum: Beşiktaş
İletişim:

Mesaj gönderen mege »

yeni bir kök form oluşturun, diğer formları bı form tipinde create edin.

Kod: Tümünü seç

unit uKokform;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,TntClasses,tntdialogs,tntforms,tntcomctrls,TntStdCtrls,TntButtons,TntMenus,TntExtCtrls,tntdbctrls,TntDBGrids;

type
  TKokForm = class(TTntForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  KokForm: TKokForm;

implementation

uses dil;
{$R *.dfm}

procedure TKokForm.FormCreate(Sender: TObject);
var iComp,iFont,iSubitem:integer;
begin
  for iComp := 0 to ComponentCount-1 do
   begin
     {------------------------------------------------}
     {               T T N T F O R M S                }
     {------------------------------------------------}
     if (components[iComp] is TTntForm) then
        begin
         (components[iComp] as TTntForm).caption := SearchCaption(Name,(components[iComp] as TTntForm).Name,(components[iComp] as TTntForm).caption,iFont);
        end
     {------------------------------------------------}
     {               T T N T P A N E L                }
     {------------------------------------------------}
     else if (components[iComp] is TTntPanel) then
        begin
         iFont :=(components[iComp] as TTntPanel).Font.Size;
         (components[iComp] as TTntPanel).caption := SearchCaption(Name,(components[iComp] as TTntPanel).Name,(components[iComp] as TTntPanel).caption,iFont);
         if iFont <> (components[iComp] as TTntPanel).Font.Size then
          (components[iComp] as TTntPanel).Font.Size := iFont;
        end
     {------------------------------------------------}
     {               T T N T D B G R I D              }
     {------------------------------------------------}
     else if (components[iComp] is TTntDBGrid) then
       for iSubitem := 0 to (components[iComp] as TTntDBGrid).Columns.Count -1 do
        begin
          iFont :=(components[iComp] as TTntDBGrid).Columns[iSubitem].Title.Font.size;
          (components[iComp] as TTntDBGrid).Columns[iSubitem].Title.Caption := SearchCaption(Name,(components[iComp] as TTntDBGrid).Name+inttostr(iSubitem),(components[iComp] as TTntDBGrid).Columns[iSubitem].Title.Caption,iFont);
          if iFont <> (components[iComp] as TTntDBGrid).Columns[iSubitem].Title.Font.size then
            (components[iComp] as TTntDBGrid).Columns[iSubitem].Title.Font.size := iFont;
        end
     {------------------------------------------------}
     {               T T N T  T O O L B U T T O N     }
     {------------------------------------------------}
     else if (components[iComp] is TTntToolButton) then
        begin
         (components[iComp] as TTntToolButton).Caption := SearchCaption(Name,(components[iComp] as TTntToolButton).name,(components[iComp] as TTntToolButton).Caption,iFont);
         (components[iComp] as TTntToolButton).Hint := SearchCaption(Name,(components[iComp] as TTntToolButton).name+'HINT',(components[iComp] as TTntToolButton).Hint,iFont);
        end
     {------------------------------------------------}
     {               T T N T S P E E D B U T T O N    }
     {------------------------------------------------}
     else if (components[iComp] is TTntSpeedButton) then
        begin
         iFont :=(components[iComp] as TTntSpeedButton).Font.Size;
         (components[iComp] as TTntSpeedButton).caption := SearchCaption(Name,(components[iComp] as TTntSpeedButton).Name,(components[iComp] as TTntSpeedButton).caption,iFont);
         if iFont <> (components[iComp] as TTntSpeedButton).Font.Size then
          (components[iComp] as TTntSpeedButton).Font.Size := iFont;
        end
     {------------------------------------------------}
     {           T T n t D B R a d i o G r o u p      }
     {------------------------------------------------}
     else if (components[iComp] is TTntDBRadioGroup) then
       for iSubitem := 0 to (components[iComp] as TTntDBRadioGroup).Items.Count -1 do
        begin
          iFont :=(components[iComp] as TTntDBRadioGroup).Font.Size;
          (components[iComp] as TTntDBRadioGroup).Items.Strings[iSubitem] := SearchCaption(Name,(components[iComp] as TTntDBRadioGroup).Name+inttostr(iSubitem),(components[iComp] as TTntDBRadioGroup).Items.Strings[iSubitem],iFont);
          if iFont <> (components[iComp] as TTntDBRadioGroup).Font.Size then
            (components[iComp] as TTntDBRadioGroup).Font.Size := iFont;
        end
     {------------------------------------------------}
     {           T T n t M E N U  I T E M             }
     {------------------------------------------------}
     else if (components[iComp] is TTntMenuItem) then
        begin
         (components[iComp] as TTntMenuItem).Caption := SearchCaption(Name,(components[iComp] as TTntMenuItem).name,(components[iComp] as TTntMenuItem).Caption,iFont);
         (components[iComp] as TTntMenuItem).Hint := SearchCaption(Name,(components[iComp] as TTntMenuItem).name+'HINT',(components[iComp] as TTntMenuItem).Hint,iFont);
        end
     {------------------------------------------------}
     {               T T N T L A B E L                }
     {------------------------------------------------}
     else if (components[iComp] is TTntLabel) then
        begin
         iFont :=(components[iComp] as TTntLabel).Font.Size;
         (components[iComp] as TTntLabel).caption := SearchCaption(Name,(components[iComp] as TTntLabel).Name,(components[iComp] as TTntLabel).caption,iFont);
         if iFont <> (components[iComp] as TTntLabel).Font.Size then
          (components[iComp] as TTntLabel).Font.Size := iFont;
        end
     {------------------------------------------------}
     {               T T N T  B U T T O N             }
     {------------------------------------------------}
     else if (components[iComp] is TTntButton) then
        begin
         iFont :=(components[iComp] as TTntButton).Font.Size;
         (components[iComp] as TTntButton).caption := SearchCaption(Name,(components[iComp] as TTntButton).Name,(components[iComp] as TTntButton).caption,iFont);
         if iFont <> (components[iComp] as TTntButton).Font.Size then
          (components[iComp] as TTntButton).Font.Size := iFont;
        end
     {------------------------------------------------}
     {               T T N T  B I T B T N             }
     {------------------------------------------------}
     else if (components[iComp] is TTntBitBtn) then
        begin
         iFont :=(components[iComp] as TTntBitBtn).Font.Size;
         (components[iComp] as TTntBitBtn).caption := SearchCaption(Name,(components[iComp] as TTntBitBtn).Name,(components[iComp] as TTntBitBtn).caption,iFont);
         if iFont <> (components[iComp] as TTntBitBtn).Font.Size then
          (components[iComp] as TTntBitBtn).Font.Size := iFont;
        end
     {------------------------------------------------}
     {               T T N T  C H E C K B O X         }
     {------------------------------------------------}
     else if (components[iComp] is TTntCheckBox) then
        begin
         iFont :=(components[iComp] as TTntCheckBox).Font.Size;
         (components[iComp] as TTntCheckBox).caption := SearchCaption(Name,(components[iComp] as TTntCheckBox).Name,(components[iComp] as TTntCheckBox).caption,iFont);
         if iFont <> (components[iComp] as TTntCheckBox).Font.Size then
          (components[iComp] as TTntCheckBox).Font.Size := iFont;
        end
     {------------------------------------------------}
     {             T T n t T r e e V i e w            }            
     {------------------------------------------------}
     else if (components[iComp] is TTntTreeView) then
       for iSubitem := 0 to (components[iComp] as TTntTreeView).Items.Count -1 do
        begin
          iFont :=(components[iComp] as TTntTreeView).Font.Size;
          (components[iComp] as TTntTreeView).Items.Item[iSubitem].Text := SearchCaption(Name,(components[iComp] as TTntTreeView).Name+inttostr(iSubitem),(components[iComp] as TTntTreeView).Items.Item[iSubitem].Text,iFont);
          if iFont <> (components[iComp] as TTntTreeView).Font.Size then
            (components[iComp] as TTntTreeView).Font.Size := iFont;
        end


   end; // for

end;

end.
SearchCaption ise sizin bileşenin adından texti getirecek fonksiyon, bunuda istediğiniz şekilde yazın, mesela

Kod: Tümünü seç

function SearchCaption(sFormname,sCompName:string;wDefault:widestring;var FontSize:integer):widestring;
var iDongu:integer;
begin
 result := '';
 if (wDefault = '') or (wDefault = ' ') then exit;
 result := wDefault;
 

 for iDongu:= 1 to MAX_CAPTIONS do
  if (uppercase(language.Captions[iDongu].FormName) = uppercase(sFormName)) and
     (uppercase(language.Captions[iDongu].CompName) = uppercase(sCompName)) then
      begin
       Result := language.Captions[iDongu].Text;
       exit;
      end;
 // buraya düştü ise bulamadı texti dosyaya ekle..
  SavetoFile(wideformat('[captions]<%s%s%s%s%d>%s',[sFormName,SEPARATOR_CHAR,sCompName,SEPARATOR_CHAR,Fontsize,wDefault]));
end;
ayrıca benzer birçok örnek atmıştım forumda aratırsanız bulursunuz.
.-.-.-.-.-.-.-. ^_^
dost
Üye
Mesajlar: 104
Kayıt: 08 Oca 2004 11:33

Mesaj gönderen dost »

İyi akşamlar,

İlginize çok teşekkürler.
Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 216
Kayıt: 09 Tem 2003 10:04

Mesaj gönderen Opt2000 »

Selam,

RTTI kullanarak çok daha genel ve pratik bir çözüm uygulanabilir. Aşağıda bir örnek kod yazıyorum.

Kod: Tümünü seç


var
  I:integer;
  NewValue:string;
begin
  for I:=0 to ControlCount-1 do
  begin 
    //NewValue değerini belirle
     NewValue = 'Hebele hübele'
     if IsPublishedProp(Controls[I], 'Caption') then
     begin
       SetStrProp(Controls[I], 'Caption', NewValue ) ;
     end;

     if IsPublishedProp(Controls[I],'Text') then
     begin
       SetStrProp(Controls[I], 'Text', NewValue) ;
     end;

  end;
end;
Bunun tek dezavantajı şudur: Run Time Type Information kullanmak bütün dillerde daima daha yavaştır, ama sizin durumunuzu düşündüğümüzde, yazacağınız her türlü koddan daha hızlı çalışacaktır.

Bu arada ufak bir detay daha var. Normalde dil değiştirme, sadece metinlerin değiştirilmesi değildir, para birimi, tarih, saat vs gibi bütün bilgiler değiştirilir. Bu yüzden çoklu dil desteği istediğiniz zaman Translation Manager kullanmanız daha doğru olur. Translation Manager'daki temel mantık ise basittir. Program içindeki bütün formların her dil için farklı sürümü oluşturulur ve siz hepsini tek tek tercüme edersiniz. Seçtiğiniz dile göre de program içindeki tarih, saat görünümleri güncellenir (Resource'dan geldiği için otomatik olarak yapılır). En büyük dezavantajı ise güncelleme yapılmasının zor olması ve sadece programın kaynak kodlarına sahip kişilerin dil tanımlaması yapabilmesidir. Ama ben daha önce bir projemde kullandım, gerçekten de metin dosyalarından veri almakla kıyaslanamayacak kadar rahat.

Kolay gelsin,
Bahadır Alkaç
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Ben artık standartlaşmış, çok kolay, rahat ve uzun süredir kullanılan bir yöntem olan gettext'i tavsiye edeceğim. OpenDatagenerator uygulamamızda kullandık ve memnunuz.

http://dybdahl.dk/dxgettext/ adresinden gerekli dosyaları indirip, uygulamanızı çok kısa bir sürede çoklu dil desteğine kavuşturabilirsiniz.

Yardıma ihtiyacınız olduğunda buradayız. :)
dost
Üye
Mesajlar: 104
Kayıt: 08 Oca 2004 11:33

Mesaj gönderen dost »

Merhaba,

ilginize çok teşekkür ederim.

gettext'in gerekli dosyalarını indirdim ama Label, Button captionlarını nasıl okutabilirim. Kullanı hakkında biraz bilgi veya basit bir örnek ile gösterebilirmisiniz ?

Teşekkürler.
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

gettext'te bütün çeviri işleri PO dediğimiz text tabanlı çeviri dosyaları ile yapılır. PO dosyalarına farklı dil desteği kazandırmak için http://www.poedit.org yazılımını kullanabilirsiniz.

Eğer uygulamanız içinde mesela bir Exception üretip mesaj veriyorsanız, kaynak kodunuzdaki bu Exception mesajının gettext tarafından desteklenmesi için. İlgili unitenin başına:

Kod: Tümünü seç

uses gnugettext
ekleyin. Bu unite dxgettext ile birlikte gelmektedir. Mesela Exception kodunuz şu şekilde ise:

Kod: Tümünü seç

raise Exception.Create('Parameter types mismatch');
şu hale getirin:

Kod: Tümünü seç

raise Exception.Create(_('Parameter types mismatch'));
Bu sayede dxgettext ile extract işleminde başında _( bulunan stringler de PO dosyasına toplanabilirler.

DXGettext'i sisteminize kurduğunuzda Windows Explorer'ın sağ tuş menüsüne kendi menü seçeneğini ekler. Uygulamanızın kaynak kodlarının bulunduğu dizinin üzerinde sağ tuş yapıp, "Extract translations to template" seçeneğini seçmeniz ile Dxgettext, formlarınız ve kaynak kodlarınızdaki bütün çevrilebilir string'leri bulup bir po dosyasına çıkaracaktır.

Daha fazla bilgi için dxgettext in yardım dosyasına da bakabilirsiniz.
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

dost yazdı:.. Kullanı hakkında biraz bilgi veya basit bir örnek ile gösterebilirmisiniz ?
http://datagenerator.sourceforge.net adresinde uygulamamızın kaynak kodlarını da bulabilirsiniz. Bu kodlardan faydalanarak neler yaptığımıza bakabilirsiniz.

Ayrıca http://dybdahl.dk/dxgettext/docs/howto.php okumanızı öneririm.

Formlarınızın OnCreate olayına:

Kod: Tümünü seç

TranslateComponent (self);
eklemeyi unutmayın ;)
dost
Üye
Mesajlar: 104
Kayıt: 08 Oca 2004 11:33

Mesaj gönderen dost »

Yardımlarınız için çok teşekkürler,
dost
Üye
Mesajlar: 104
Kayıt: 08 Oca 2004 11:33

Mesaj gönderen dost »

Merhaba,

gettext ve poedit'in gerekli dosyalarını indirerek kurdum,
basit bir uygulama yaptımsada çalıştıramadım.

Kod: Tümünü seç

implementation

uses
  gnugettext;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  TranslateComponent(self);
end;

procedure TForm1.ComboBox1Change(Sender: TObject);
const
  LangCode: array[0..1] of string = ('en','tr');
var
  i: integer;
begin
  i := ComboBox1.ItemIndex;

  UseLanguage(LangCode[i]);

  TranslateComponent(self);

  ComboBox1.ItemIndex := i
end;

end.
verdiği hata,

This application tried to swetch the language, but in an incorrect way. The programmer needs to replace a call to TranslateComponent with a call to RetranslateComponent(). The programmer should see the changelog of gnugettext.pas for more information

Yardımcı olabilirmisiniz ?
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Mesaj gönderen Akin_Delphi »

dost yazdı:Merhaba,
This application tried to swetch the language, but in an incorrect way. The programmer needs to replace a call to TranslateComponent with a call to RetranslateComponent(). The programmer should see the changelog of gnugettext.pas for more information

Yardımcı olabilirmisiniz ?
Hiç kullanmadım ancak mesaj şunu söylüyor:

Bu uygulama dil değiştirmeye çalıştı ancak bunu yanlış şekilde yaptı. Programıncının TranslateComponent'e yapılan çağrıyı RetranslateComponent ile değiştirmesi gerekiyor. Programcı gnugettex.pas'ın değişim kaydına bakmalıdır.

Umarım yardımcı olur.
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Anladıım kadarıyla uygulama etkin iken seçilen dile göre uygulama dilini değiştirebilmeye çalışıyorsunuz.

@Akın_Delphi'nin söylediği doğru. Bunun için:

RetranslateComponent(Self)

çağrısını kullanmalısınız. TranslateComponent çağrısı sadece FormCreate'de kullanılmalıdır.
Cevapla