Zapocinjem rad ne vecem projektu u Delphi 7, projekat treba da ima podrsku za vise jezika, pa me zanima na koji je nacin najbolje da to odradim, dok sam jos u ranoj fazi razvoja projekta ? Kontam da ce kasnije to biti skoro pa nemoguce ako ne pripremim projekat za lokalizacjiu vec sada. Jel postoje neke komponente za ovo ? Bilo kakvi hintovi su dobrodosli. Hvala :)
Lokalizacija projekta
Zaključano
Zakačeno
kad nece iskusniji ajd ja da ti predlozim, jezicke postavke cuvas u .txt fajlu i pri form create ucitavas sve labele, buttone itd, to mozda moze i neki .ini da bude
Sam Delphi ima alat za lokalizaciju mada mi se nikada nije dopao, imaš i neka gotova rešenja poput http://dxgettext.po.dk.
Ja sam to bio radio preko ovog unita, s tim što je on namenjen za unicode controle (TNT). Svakoj kontroli se dodeli jedinstveni tag i kasnije se u ini fajlovima (za svaki jezik po jedan), daju konkretni prevodi.
Ja sam to bio radio preko ovog unita, s tim što je on namenjen za unicode controle (TNT). Svakoj kontroli se dodeli jedinstveni tag i kasnije se u ini fajlovima (za svaki jezik po jedan), daju konkretni prevodi.
Potpis
Do not be a help vampire (http://slash7.com/pages/vampires), use the google.
How to ask questions the smart way:
http://www.catb.org/~esr/faqs/smart-questions.html
http://solair.eunet.rs/~fangor...stions/smart-questions.sr.html
How to ask questions the smart way:
http://www.catb.org/~esr/faqs/smart-questions.html
http://solair.eunet.rs/~fangor...stions/smart-questions.sr.html
Prvo, ako možeš, pređi na Delphi 2010 zbog Unicode podrške (naročito ako planiraš da podržavaš i ćirilicu i latinicu u istoj aplikaciji). To će ti uštedeti vreme i nećeš imati glavobolje kasnije.
Drugo, Delphi ima ITE (Integrated Translation Environment). Kada otvoriš projekat, pogledaj meni Project -> Languages.
Treće, ako baš insistiraš da ostaneš na Delphi 7, onda pogledaj dxGetText. Takođe, ne gine ti da koristiš TNT komponente jer jedino one podržavaju Unicode kako valja, ali je problem što se više ne održavaju, tj. kupio ih je TMS Software i integrisao u svoje proizvode. Može i dalje da se nađe negde arhiva sa originalnim komponentama, pa potraži malo.
Četvrto, postoji dosta komercijalnih paketa koji omogućavaju izradu višejezičkih aplikacija, pa pogledaj sledeće:
- tsiLang
- Localizer
- Multilizer
- Helicon Translator
- Sisulizer
Pogledaj i ove linkove, možda će te zanimati:
http://delphi.about.com/library/weekly/aa102400a.htm
http://delphi.about.com/od/objectpascalide/l/aa020502a.htm
Nadam se da sada imaš dovoljno informacija
Drugo, Delphi ima ITE (Integrated Translation Environment). Kada otvoriš projekat, pogledaj meni Project -> Languages.
Treće, ako baš insistiraš da ostaneš na Delphi 7, onda pogledaj dxGetText. Takođe, ne gine ti da koristiš TNT komponente jer jedino one podržavaju Unicode kako valja, ali je problem što se više ne održavaju, tj. kupio ih je TMS Software i integrisao u svoje proizvode. Može i dalje da se nađe negde arhiva sa originalnim komponentama, pa potraži malo.
Četvrto, postoji dosta komercijalnih paketa koji omogućavaju izradu višejezičkih aplikacija, pa pogledaj sledeće:
- tsiLang
- Localizer
- Multilizer
- Helicon Translator
- Sisulizer
Pogledaj i ove linkove, možda će te zanimati:
http://delphi.about.com/library/weekly/aa102400a.htm
http://delphi.about.com/od/objectpascalide/l/aa020502a.htm
Nadam se da sada imaš dovoljno informacija
Potpis
"There is a theory which states that if ever anybody discovers exactly what the
Universe is for and why it is here, it will instantly disappear and be replaced by
something even more bizarre and inexplicable. There is another theory which states
that this has already happened."
-- Douglas Adams
Universe is for and why it is here, it will instantly disappear and be replaced by
something even more bizarre and inexplicable. There is another theory which states
that this has already happened."
-- Douglas Adams
Hvala lepo :)
izmenjeno 1 put, poslednji put reiser 03.01.2012. u 03:10
Izmene poruke
- reiser03.01.2012. u 03:10zapis iz teksta poruke
Evo da se javim i kazem sta sam uradio, mozda ce nekome jos pomoci. Posto sam probao vecinu ovih gore alata i svi su mi delovali konfuzno / nisu radili ono sto ja hocu, napisao sam moju klasu za to. Klasa je smestena u jednom unitu - Localization.pas a dinamicki stringovi u drugom - LocalizationStr.pas.
Language fajl je u stvari .ini fajl koji se sastoji iz tri dela, info, data i strresources. U info idu razni podaci, ime autora, naziv jezika itd.
U data delu su imena komponenti i njihovi stringovi. Recimo, Form1.Label1 = LabelNaSrpskom. Prilikom lokalizacije, ucitavaju se svi stringovi iz ovog dela, nalazi komponenta sa ovim imenom na formi i ispituje da li komponenta ima Caption ili Text property. Ako postoji, setuje ga na ucitani string. Ako zelite da setujete hint komponente, ime komponente treba da pocne sa #. Dakle, za Label1, setovanje hinta bi izgledalo ovako: #Form1.Label1 = Hint Labele
strresources deo sadrzi tzv "dinamicke" stringovi. Oni se koriste kod objekta kod kojih je potrebno da se caption dinamicki menja, recimo ako zelite da u jednom labelu prikazete "Downloading file..." dok se fajl skida i "Download finished" kada se download zavrsi. Svaki string se smesta u LocalizationStr.pas kao promenljiva, i dodaje se sledeca linija u TLocalizer.LocalizeResourceStrings() funkciji koji taj string ucitava (recimo da se string promenljiva zove RS_AUTHENTICATING):
Sa dinamickim stringovima je neophodno manuelno menjanje captiona naravno, recimo u OnDownloadBegin stavite Label1.Caption := RS_DOWNLOAD_BEGIN, u OnDownloadFinished stavite Label1.Caption := RS_DOWNLOAD_FINISHED
Localization.pas:
Evo i raznih funkcija koje klasa koristi, a nema ih u samoj klasi. Ja ih pozivam iz drugog unita u kome smestam sve helper funkcije i koji sam includovao u klasu, ali je lakse da izvucem samo funkcije koje se koriste umesto da linkujem ceo unit:
Ovako bi izgledao LocalizationStr.pas:
Naravno, ovo je sve hardkodovano u programu, tj ako ne postoje language fajlovi, prikazace se ovi hardkodovani stringovi umesto praznih :)
I ovako bi na kraju trebao da izgleda language fajl za ovu klasu:
Eto, ako neko uspe da razume sve ovo, hteo bih da cujem misljenje, jer sam siguran da se nesto moze poboljsati :)
Language fajl je u stvari .ini fajl koji se sastoji iz tri dela, info, data i strresources. U info idu razni podaci, ime autora, naziv jezika itd.
U data delu su imena komponenti i njihovi stringovi. Recimo, Form1.Label1 = LabelNaSrpskom. Prilikom lokalizacije, ucitavaju se svi stringovi iz ovog dela, nalazi komponenta sa ovim imenom na formi i ispituje da li komponenta ima Caption ili Text property. Ako postoji, setuje ga na ucitani string. Ako zelite da setujete hint komponente, ime komponente treba da pocne sa #. Dakle, za Label1, setovanje hinta bi izgledalo ovako: #Form1.Label1 = Hint Labele
strresources deo sadrzi tzv "dinamicke" stringovi. Oni se koriste kod objekta kod kojih je potrebno da se caption dinamicki menja, recimo ako zelite da u jednom labelu prikazete "Downloading file..." dok se fajl skida i "Download finished" kada se download zavrsi. Svaki string se smesta u LocalizationStr.pas kao promenljiva, i dodaje se sledeca linija u TLocalizer.LocalizeResourceStrings() funkciji koji taj string ucitava (recimo da se string promenljiva zove RS_AUTHENTICATING):
Code:
RS_AUTHENTICATING := PrepareString(INI.ReadString(SECTION, 'RS_AUTHENTICATING', RS_AUTHENTICATING));
RS_AUTHENTICATING := PrepareString(INI.ReadString(SECTION, 'RS_AUTHENTICATING', RS_AUTHENTICATING));
Sa dinamickim stringovima je neophodno manuelno menjanje captiona naravno, recimo u OnDownloadBegin stavite Label1.Caption := RS_DOWNLOAD_BEGIN, u OnDownloadFinished stavite Label1.Caption := RS_DOWNLOAD_FINISHED
Localization.pas:
Code:
unit Localization;
interface
uses
Classes;
type
TLanguageInfo = record
Name : String;
LocalName : String;
CountryCode : String;
Author : String;
end;
{$M+}
TLocalizer = class
private
FLanguageFile : String;
FLanguageList : TStringList;
FLanguagesDir : String;
FLanguagesFileMask : String;
public
constructor Create(const ALanguagesDir : String = ''; const ALanguagesFilemask : String = '*.*');
destructor Destroy; override;
procedure Localize(const AComponent : TComponent);
procedure LocalizeResourceStrings;
procedure RefreshLanguageList;
function GetLanguageInfo(const ALanguageFile : String) : TLanguageInfo;
function FindLanguageByName(const ALanguageName : String; var AIndex : Integer) : Boolean;
published
property LanguageFile : String read FLanguageFile write FLanguageFile;
property LanguageList : TStringList read FLanguageList;
property LanguagesDir : String read FLanguagesDir write FLanguagesDir;
end;
{$M-}
implementation
uses
SysUtils, INIFiles, TypInfo, LocalizationStr;
constructor TLocalizer.Create(const ALanguagesDir : String = ''; const ALanguagesFilemask : String = '*.*');
begin
FLanguageFile := '';
FLanguagesDir := ALanguagesDir;
FLanguagesFilemask := ALanguagesFilemask;
FLanguageList := TStringList.Create;
FLanguageList.Clear;
FLanguageList.Sorted := TRUE;
RefreshLanguageList;
end;
destructor TLocalizer.Destroy;
begin
FLanguageList.Free;
inherited;
end;
procedure TLocalizer.Localize(const AComponent : TComponent);
const
DATASECTION = 'data';
var
INI : TMemINIFile;
ident : TStringList;
values : TStringList;
objects : TStringList;
C1 : Integer;
fcomp : TComponent;
PropInfo : PPropInfo;
isHint : Boolean;
objStr : String;
begin
If Assigned(AComponent) Then
Begin
If FileExists(FLanguageFile) Then
Begin
INI := TMemINIFile.Create(FLanguageFile, TEncoding.UTF8);
If INI.SectionExists(DATASECTION) Then
Begin
ident := TStringList.Create;
values := TStringList.Create;
INI.ReadSection(DATASECTION, ident);
INI.ReadSectionValues(DATASECTION, values);
For C1 := 0 to values.Count - 1 Do
values.Strings[C1] := Trim(Copy(values.Strings[C1], Pos('=', values.Strings[C1]) + 1, Length(values.Strings[C1]) - Pos('=', values.Strings[C1])));
objects := TStringList.Create;
If ident.Count = values.Count Then
For C1 := 0 to ident.Count - 1 Do
Begin
Split('.', ident.Strings[C1], objects);
If objects.Count > 0 Then
Begin
objStr := objects.Strings[0];
isHint := objStr[1] = '#';
If isHint Then
Delete(objStr, 1, 1);
If LowerCase(objStr) = LowerCase(AComponent.Name) Then
Begin
objects.Delete(0);
fcomp := AComponent;
While (objects.Count > 0) and
(fcomp <> nil) Do
Begin
fcomp := fcomp.FindComponent(objects.Strings[0]);
objects.Delete(0);
End;
If fcomp <> nil Then
Begin
If isHint Then
PropInfo := GetPropInfo(fcomp, 'Hint')
else
Begin
PropInfo := GetPropInfo(fcomp, 'Caption');
If PropInfo = nil Then
PropInfo := GetPropInfo(fcomp, 'Text');
End;
If PropInfo <> nil Then
SetStrProp(fcomp, PropInfo, PrepareString(values.Strings[C1]));
End;
End;
End;
End;
objects.Free;
values.Free;
ident.Free;
End;
INI.Free;
End;
End;
end;
procedure TLocalizer.LocalizeResourceStrings;
const
SECTION = 'strresources';
var
INI : TMemINIFile;
begin
If FileExists(FLanguageFile) Then
Begin
INI := TMemINIFile.Create(FLanguageFile, TEncoding.UTF8);
RS_AUTHENTICATING := PrepareString(INI.ReadString(SECTION, 'RS_AUTHENTICATING', RS_AUTHENTICATING));
RS_RESPONSE_UNKNOWN := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_UNKNOWN', RS_RESPONSE_UNKNOWN));
RS_RESPONSE_REGISTER_EMAIL_SENT := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_REGISTER_EMAIL_SENT', RS_RESPONSE_REGISTER_EMAIL_SENT));
RS_RESPONSE_CHANNEL_ADDED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CHANNEL_ADDED', RS_RESPONSE_CHANNEL_ADDED));
RS_RESPONSE_CHANNEL_PASSWORD_CHANGED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CHANNEL_PASSWORD_CHANGED', RS_RESPONSE_CHANNEL_PASSWORD_CHANGED));
RS_RESPONSE_REQUEST_SENT := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_REQUEST_SENT', RS_RESPONSE_REQUEST_SENT));
RS_RESPONSE_CONFIRMED_REQUEST := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CONFIRMED_REQUEST', RS_RESPONSE_CONFIRMED_REQUEST));
RS_RESPONSE_USER_UNBLOCKED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_USER_UNBLOCKED', RS_RESPONSE_USER_UNBLOCKED));
RS_RESPONSE_USER_BLOCKED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_USER_BLOCKED', RS_RESPONSE_USER_BLOCKED));
RS_RESPONSE_COULD_NOT_SEND_EMAIL := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_COULD_NOT_SEND_EMAIL', RS_RESPONSE_COULD_NOT_SEND_EMAIL));
RS_RESPONSE_USERNAME_TAKEN := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_USERNAME_TAKEN', RS_RESPONSE_USERNAME_TAKEN));
RS_RESPONSE_EMAIL_ALREADY_USED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_EMAIL_ALREADY_USED', RS_RESPONSE_EMAIL_ALREADY_USED));
RS_RESPONSE_CAPTCHA_ERROR := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CAPTCHA_ERROR', RS_RESPONSE_CAPTCHA_ERROR));
RS_RESPONSE_REQ_LIMIT_REACHED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_REQ_LIMIT_REACHED', RS_RESPONSE_REQ_LIMIT_REACHED));
RS_RESPONSE_INVALID_KEY := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_KEY', RS_RESPONSE_INVALID_KEY));
RS_RESPONSE_INVALID_USERNAME := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_USERNAME', RS_RESPONSE_INVALID_USERNAME));
RS_RESPONSE_ALREADY_A_FRIEND := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_ALREADY_A_FRIEND', RS_RESPONSE_ALREADY_A_FRIEND));
RS_RESPONSE_INVALID_CONFIRMATION := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_CONFIRMATION', RS_RESPONSE_INVALID_CONFIRMATION));
RS_RESPONSE_INVALID_POSTS := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_POSTS', RS_RESPONSE_INVALID_POSTS));
RS_RESPONSE_INVALID_USER := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_USER', RS_RESPONSE_INVALID_USER));
RS_RESPONSE_NOT_CHANNEL_OWNER := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_NOT_CHANNEL_OWNER', RS_RESPONSE_NOT_CHANNEL_OWNER));
RS_RESPONSE_INVALID_USERPASS := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_USERPASS', RS_RESPONSE_INVALID_USERPASS));
RS_RESPONSE_ALREADY_SENT_REQ := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_ALREADY_SENT_REQ', RS_RESPONSE_ALREADY_SENT_REQ));
RS_RESPONSE_CHANNEL_RESERVED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CHANNEL_RESERVED', RS_RESPONSE_CHANNEL_RESERVED));
RS_RESPONSE_ACCOUNT_NOT_ACTIVATED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_ACCOUNT_NOT_ACTIVATED', RS_RESPONSE_ACCOUNT_NOT_ACTIVATED));
RS_RUN_CLIENT_AS_ADMIN := PrepareString(INI.ReadString(SECTION, 'RS_RUN_CLIENT_AS_ADMIN', RS_RUN_CLIENT_AS_ADMIN));
RS_CANNOT_CONNECT := PrepareString(INI.ReadString(SECTION, 'RS_CANNOT_CONNECT', RS_CANNOT_CONNECT));
RS_WAITING_FOR_GAME := PrepareString(INI.ReadString(SECTION, 'RS_WAITING_FOR_GAME', RS_WAITING_FOR_GAME));
RS_GAME_IN_PROGRESS := PrepareString(INI.ReadString(SECTION, 'RS_GAME_IN_PROGRESS', RS_GAME_IN_PROGRESS));
RS_GAME_ENDED := PrepareString(INI.ReadString(SECTION, 'RS_GAME_ENDED', RS_GAME_ENDED));
RS_WARDIALOG_TITLE := PrepareString(INI.ReadString(SECTION, 'RS_WARDIALOG_TITLE', RS_WARDIALOG_TITLE));
RS_NO_RESPONSE_FROM_SERVER := PrepareString(INI.ReadString(SECTION, 'RS_NO_RESPONSE_FROM_SERVER', RS_NO_RESPONSE_FROM_SERVER));
RS_GAME_PRECREEPS := PrepareString(INI.ReadString(SECTION, 'RS_GAME_PRECREEPS', RS_GAME_PRECREEPS));
RS_DOWNLOAD_DOWNLOADING := PrepareString(INI.ReadString(SECTION, 'RS_DOWNLOAD_DOWNLOADING', RS_DOWNLOAD_DOWNLOADING));
RS_WARCRAFT_REPLAY_NOT_ASSOCIATED := PrepareString(INI.ReadString(SECTION, 'RS_WARCRAFT_REPLAY_NOT_ASSOCIATED', RS_WARCRAFT_REPLAY_NOT_ASSOCIATED));
RS_STARCRAFT_REPLAY_NOT_ASSOCIATED := PrepareString(INI.ReadString(SECTION, 'RS_STARCRAFT_REPLAY_NOT_ASSOCIATED', RS_STARCRAFT_REPLAY_NOT_ASSOCIATED));
RS_INVALID_EMAIL := PrepareString(INI.ReadString(SECTION, 'RS_INVALID_EMAIL', RS_INVALID_EMAIL));
RS_PASSWORD_MISMATCH := PrepareString(INI.ReadString(SECTION, 'RS_PASSWORD_MISMATCH', RS_PASSWORD_MISMATCH));
RS_FILL_ALL_FIELDS := PrepareString(INI.ReadString(SECTION, 'RS_FILL_ALL_FIELDS', RS_FILL_ALL_FIELDS));
RS_PASSWORD_TOO_SHORT := PrepareString(INI.ReadString(SECTION, 'RS_PASSWORD_TOO_SHORT', RS_PASSWORD_TOO_SHORT));
RS_USERNAME_TOO_SHORT := PrepareString(INI.ReadString(SECTION, 'RS_USERNAME_TOO_SHORT', RS_USERNAME_TOO_SHORT));
RS_CHECKING_FOR_UPDATES := PrepareString(INI.ReadString(SECTION, 'RS_CHECKING_FOR_UPDATES', RS_CHECKING_FOR_UPDATES));
RS_REPLAY_DOWNLOADING := PrepareString(INI.ReadString(SECTION, 'RS_REPLAY_DOWNLOADING', RS_REPLAY_DOWNLOADING));
RS_UPDATE_DOWNLOADING := PrepareString(INI.ReadString(SECTION, 'RS_UPDATE_DOWNLOADING', RS_UPDATE_DOWNLOADING));
RS_AGREE_TO_TERMS := PrepareString(INI.ReadString(SECTION, 'RS_AGREE_TO_TERMS', RS_AGREE_TO_TERMS));
INI.Free;
End;
end;
function TLocalizer.GetLanguageInfo(const ALanguageFile : String) : TLanguageInfo;
var
INI : TMemINIFile;
begin
If FileExists(ALanguageFile) Then
Begin
INI := TMemINIFile.Create(ALanguageFile, TEncoding.UTF8);
result.Name := INI.ReadString('info', 'LanguageName', '');
result.LocalName := INI.ReadString('info', 'LocalLanguageName', '');
result.CountryCode := INI.ReadString('info', 'CountryCode', '');
result.Author := INI.ReadString('info', 'Author', '');
INI.Free;
End;
end;
procedure TLocalizer.RefreshLanguageList;
begin
LanguageList.Clear;
EnumerateFiles(FLanguagesDir, FLanguagesFilemask, TRUE, FLanguageList);
end;
function TLocalizer.FindLanguageByName(const ALanguageName : String; var AIndex : Integer) : Boolean;
var
C1 : Integer;
langInfo : TLanguageInfo;
begin
result := FALSE;
AIndex := -1;
For C1 := 0 to FLanguageList.Count - 1 Do
Begin
langInfo := GetLanguageInfo(FLanguageList.Strings[C1]);
If (langInfo.Name = ALanguageName) or
(langInfo.LocalName = ALanguageName) Then
Begin
AIndex := C1;
result := TRUE;
Break;
End;
End;
end;
end.
unit Localization;
interface
uses
Classes;
type
TLanguageInfo = record
Name : String;
LocalName : String;
CountryCode : String;
Author : String;
end;
{$M+}
TLocalizer = class
private
FLanguageFile : String;
FLanguageList : TStringList;
FLanguagesDir : String;
FLanguagesFileMask : String;
public
constructor Create(const ALanguagesDir : String = ''; const ALanguagesFilemask : String = '*.*');
destructor Destroy; override;
procedure Localize(const AComponent : TComponent);
procedure LocalizeResourceStrings;
procedure RefreshLanguageList;
function GetLanguageInfo(const ALanguageFile : String) : TLanguageInfo;
function FindLanguageByName(const ALanguageName : String; var AIndex : Integer) : Boolean;
published
property LanguageFile : String read FLanguageFile write FLanguageFile;
property LanguageList : TStringList read FLanguageList;
property LanguagesDir : String read FLanguagesDir write FLanguagesDir;
end;
{$M-}
implementation
uses
SysUtils, INIFiles, TypInfo, LocalizationStr;
constructor TLocalizer.Create(const ALanguagesDir : String = ''; const ALanguagesFilemask : String = '*.*');
begin
FLanguageFile := '';
FLanguagesDir := ALanguagesDir;
FLanguagesFilemask := ALanguagesFilemask;
FLanguageList := TStringList.Create;
FLanguageList.Clear;
FLanguageList.Sorted := TRUE;
RefreshLanguageList;
end;
destructor TLocalizer.Destroy;
begin
FLanguageList.Free;
inherited;
end;
procedure TLocalizer.Localize(const AComponent : TComponent);
const
DATASECTION = 'data';
var
INI : TMemINIFile;
ident : TStringList;
values : TStringList;
objects : TStringList;
C1 : Integer;
fcomp : TComponent;
PropInfo : PPropInfo;
isHint : Boolean;
objStr : String;
begin
If Assigned(AComponent) Then
Begin
If FileExists(FLanguageFile) Then
Begin
INI := TMemINIFile.Create(FLanguageFile, TEncoding.UTF8);
If INI.SectionExists(DATASECTION) Then
Begin
ident := TStringList.Create;
values := TStringList.Create;
INI.ReadSection(DATASECTION, ident);
INI.ReadSectionValues(DATASECTION, values);
For C1 := 0 to values.Count - 1 Do
values.Strings[C1] := Trim(Copy(values.Strings[C1], Pos('=', values.Strings[C1]) + 1, Length(values.Strings[C1]) - Pos('=', values.Strings[C1])));
objects := TStringList.Create;
If ident.Count = values.Count Then
For C1 := 0 to ident.Count - 1 Do
Begin
Split('.', ident.Strings[C1], objects);
If objects.Count > 0 Then
Begin
objStr := objects.Strings[0];
isHint := objStr[1] = '#';
If isHint Then
Delete(objStr, 1, 1);
If LowerCase(objStr) = LowerCase(AComponent.Name) Then
Begin
objects.Delete(0);
fcomp := AComponent;
While (objects.Count > 0) and
(fcomp <> nil) Do
Begin
fcomp := fcomp.FindComponent(objects.Strings[0]);
objects.Delete(0);
End;
If fcomp <> nil Then
Begin
If isHint Then
PropInfo := GetPropInfo(fcomp, 'Hint')
else
Begin
PropInfo := GetPropInfo(fcomp, 'Caption');
If PropInfo = nil Then
PropInfo := GetPropInfo(fcomp, 'Text');
End;
If PropInfo <> nil Then
SetStrProp(fcomp, PropInfo, PrepareString(values.Strings[C1]));
End;
End;
End;
End;
objects.Free;
values.Free;
ident.Free;
End;
INI.Free;
End;
End;
end;
procedure TLocalizer.LocalizeResourceStrings;
const
SECTION = 'strresources';
var
INI : TMemINIFile;
begin
If FileExists(FLanguageFile) Then
Begin
INI := TMemINIFile.Create(FLanguageFile, TEncoding.UTF8);
RS_AUTHENTICATING := PrepareString(INI.ReadString(SECTION, 'RS_AUTHENTICATING', RS_AUTHENTICATING));
RS_RESPONSE_UNKNOWN := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_UNKNOWN', RS_RESPONSE_UNKNOWN));
RS_RESPONSE_REGISTER_EMAIL_SENT := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_REGISTER_EMAIL_SENT', RS_RESPONSE_REGISTER_EMAIL_SENT));
RS_RESPONSE_CHANNEL_ADDED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CHANNEL_ADDED', RS_RESPONSE_CHANNEL_ADDED));
RS_RESPONSE_CHANNEL_PASSWORD_CHANGED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CHANNEL_PASSWORD_CHANGED', RS_RESPONSE_CHANNEL_PASSWORD_CHANGED));
RS_RESPONSE_REQUEST_SENT := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_REQUEST_SENT', RS_RESPONSE_REQUEST_SENT));
RS_RESPONSE_CONFIRMED_REQUEST := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CONFIRMED_REQUEST', RS_RESPONSE_CONFIRMED_REQUEST));
RS_RESPONSE_USER_UNBLOCKED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_USER_UNBLOCKED', RS_RESPONSE_USER_UNBLOCKED));
RS_RESPONSE_USER_BLOCKED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_USER_BLOCKED', RS_RESPONSE_USER_BLOCKED));
RS_RESPONSE_COULD_NOT_SEND_EMAIL := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_COULD_NOT_SEND_EMAIL', RS_RESPONSE_COULD_NOT_SEND_EMAIL));
RS_RESPONSE_USERNAME_TAKEN := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_USERNAME_TAKEN', RS_RESPONSE_USERNAME_TAKEN));
RS_RESPONSE_EMAIL_ALREADY_USED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_EMAIL_ALREADY_USED', RS_RESPONSE_EMAIL_ALREADY_USED));
RS_RESPONSE_CAPTCHA_ERROR := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CAPTCHA_ERROR', RS_RESPONSE_CAPTCHA_ERROR));
RS_RESPONSE_REQ_LIMIT_REACHED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_REQ_LIMIT_REACHED', RS_RESPONSE_REQ_LIMIT_REACHED));
RS_RESPONSE_INVALID_KEY := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_KEY', RS_RESPONSE_INVALID_KEY));
RS_RESPONSE_INVALID_USERNAME := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_USERNAME', RS_RESPONSE_INVALID_USERNAME));
RS_RESPONSE_ALREADY_A_FRIEND := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_ALREADY_A_FRIEND', RS_RESPONSE_ALREADY_A_FRIEND));
RS_RESPONSE_INVALID_CONFIRMATION := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_CONFIRMATION', RS_RESPONSE_INVALID_CONFIRMATION));
RS_RESPONSE_INVALID_POSTS := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_POSTS', RS_RESPONSE_INVALID_POSTS));
RS_RESPONSE_INVALID_USER := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_USER', RS_RESPONSE_INVALID_USER));
RS_RESPONSE_NOT_CHANNEL_OWNER := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_NOT_CHANNEL_OWNER', RS_RESPONSE_NOT_CHANNEL_OWNER));
RS_RESPONSE_INVALID_USERPASS := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_INVALID_USERPASS', RS_RESPONSE_INVALID_USERPASS));
RS_RESPONSE_ALREADY_SENT_REQ := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_ALREADY_SENT_REQ', RS_RESPONSE_ALREADY_SENT_REQ));
RS_RESPONSE_CHANNEL_RESERVED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_CHANNEL_RESERVED', RS_RESPONSE_CHANNEL_RESERVED));
RS_RESPONSE_ACCOUNT_NOT_ACTIVATED := PrepareString(INI.ReadString(SECTION, 'RS_RESPONSE_ACCOUNT_NOT_ACTIVATED', RS_RESPONSE_ACCOUNT_NOT_ACTIVATED));
RS_RUN_CLIENT_AS_ADMIN := PrepareString(INI.ReadString(SECTION, 'RS_RUN_CLIENT_AS_ADMIN', RS_RUN_CLIENT_AS_ADMIN));
RS_CANNOT_CONNECT := PrepareString(INI.ReadString(SECTION, 'RS_CANNOT_CONNECT', RS_CANNOT_CONNECT));
RS_WAITING_FOR_GAME := PrepareString(INI.ReadString(SECTION, 'RS_WAITING_FOR_GAME', RS_WAITING_FOR_GAME));
RS_GAME_IN_PROGRESS := PrepareString(INI.ReadString(SECTION, 'RS_GAME_IN_PROGRESS', RS_GAME_IN_PROGRESS));
RS_GAME_ENDED := PrepareString(INI.ReadString(SECTION, 'RS_GAME_ENDED', RS_GAME_ENDED));
RS_WARDIALOG_TITLE := PrepareString(INI.ReadString(SECTION, 'RS_WARDIALOG_TITLE', RS_WARDIALOG_TITLE));
RS_NO_RESPONSE_FROM_SERVER := PrepareString(INI.ReadString(SECTION, 'RS_NO_RESPONSE_FROM_SERVER', RS_NO_RESPONSE_FROM_SERVER));
RS_GAME_PRECREEPS := PrepareString(INI.ReadString(SECTION, 'RS_GAME_PRECREEPS', RS_GAME_PRECREEPS));
RS_DOWNLOAD_DOWNLOADING := PrepareString(INI.ReadString(SECTION, 'RS_DOWNLOAD_DOWNLOADING', RS_DOWNLOAD_DOWNLOADING));
RS_WARCRAFT_REPLAY_NOT_ASSOCIATED := PrepareString(INI.ReadString(SECTION, 'RS_WARCRAFT_REPLAY_NOT_ASSOCIATED', RS_WARCRAFT_REPLAY_NOT_ASSOCIATED));
RS_STARCRAFT_REPLAY_NOT_ASSOCIATED := PrepareString(INI.ReadString(SECTION, 'RS_STARCRAFT_REPLAY_NOT_ASSOCIATED', RS_STARCRAFT_REPLAY_NOT_ASSOCIATED));
RS_INVALID_EMAIL := PrepareString(INI.ReadString(SECTION, 'RS_INVALID_EMAIL', RS_INVALID_EMAIL));
RS_PASSWORD_MISMATCH := PrepareString(INI.ReadString(SECTION, 'RS_PASSWORD_MISMATCH', RS_PASSWORD_MISMATCH));
RS_FILL_ALL_FIELDS := PrepareString(INI.ReadString(SECTION, 'RS_FILL_ALL_FIELDS', RS_FILL_ALL_FIELDS));
RS_PASSWORD_TOO_SHORT := PrepareString(INI.ReadString(SECTION, 'RS_PASSWORD_TOO_SHORT', RS_PASSWORD_TOO_SHORT));
RS_USERNAME_TOO_SHORT := PrepareString(INI.ReadString(SECTION, 'RS_USERNAME_TOO_SHORT', RS_USERNAME_TOO_SHORT));
RS_CHECKING_FOR_UPDATES := PrepareString(INI.ReadString(SECTION, 'RS_CHECKING_FOR_UPDATES', RS_CHECKING_FOR_UPDATES));
RS_REPLAY_DOWNLOADING := PrepareString(INI.ReadString(SECTION, 'RS_REPLAY_DOWNLOADING', RS_REPLAY_DOWNLOADING));
RS_UPDATE_DOWNLOADING := PrepareString(INI.ReadString(SECTION, 'RS_UPDATE_DOWNLOADING', RS_UPDATE_DOWNLOADING));
RS_AGREE_TO_TERMS := PrepareString(INI.ReadString(SECTION, 'RS_AGREE_TO_TERMS', RS_AGREE_TO_TERMS));
INI.Free;
End;
end;
function TLocalizer.GetLanguageInfo(const ALanguageFile : String) : TLanguageInfo;
var
INI : TMemINIFile;
begin
If FileExists(ALanguageFile) Then
Begin
INI := TMemINIFile.Create(ALanguageFile, TEncoding.UTF8);
result.Name := INI.ReadString('info', 'LanguageName', '');
result.LocalName := INI.ReadString('info', 'LocalLanguageName', '');
result.CountryCode := INI.ReadString('info', 'CountryCode', '');
result.Author := INI.ReadString('info', 'Author', '');
INI.Free;
End;
end;
procedure TLocalizer.RefreshLanguageList;
begin
LanguageList.Clear;
EnumerateFiles(FLanguagesDir, FLanguagesFilemask, TRUE, FLanguageList);
end;
function TLocalizer.FindLanguageByName(const ALanguageName : String; var AIndex : Integer) : Boolean;
var
C1 : Integer;
langInfo : TLanguageInfo;
begin
result := FALSE;
AIndex := -1;
For C1 := 0 to FLanguageList.Count - 1 Do
Begin
langInfo := GetLanguageInfo(FLanguageList.Strings[C1]);
If (langInfo.Name = ALanguageName) or
(langInfo.LocalName = ALanguageName) Then
Begin
AIndex := C1;
result := TRUE;
Break;
End;
End;
end;
end.
Evo i raznih funkcija koje klasa koristi, a nema ih u samoj klasi. Ja ih pozivam iz drugog unita u kome smestam sve helper funkcije i koji sam includovao u klasu, ali je lakse da izvucem samo funkcije koje se koriste umesto da linkujem ceo unit:
Code:
function PrepareString(const AString : String) : String;
begin
result := AString;
result := StringReplace(result, '\n', #13#10, [rfReplaceAll]);
result := StringReplace(result, '\_', ' ', [rfReplaceAll]);
end;
procedure Split(const ADelimiter : Char; const AInput : String; const AStrings : TStrings);
begin
If Assigned(AStrings) Then
Begin
AStrings.Clear;
AStrings.Delimiter := ADelimiter;
AStrings.DelimitedText := AInput;
End;
end;
function MatchStrings(const AStr1, AStr2 : String; const ACaseSensitive : Boolean) : Boolean;
function MatchPattern(str1, str2 : PWideChar) : Boolean;
begin
If StrComp(str2, '*') = 0 Then
result := TRUE
else
If (str1^ = #0) and
(str2^ <> #0) Then
result := FALSE
else
If str1^ = #0 Then
result := TRUE
else
Case str2^ of
'*': If MatchPattern(str1, @str2[1]) Then
result := TRUE
else
result := MatchPattern(@str1[1], str2);
'?': result := MatchPattern(@str1[1], @str2[1]);
else
If str1^ = str2^ Then
result := MatchPattern(@str1[1], @str2[1])
else
result := FALSE;
end;
end;
begin
If ACaseSensitive Then
result := MatchPattern(PWideChar(AStr1), PWideChar(AStr2)) or
MatchPattern(PWideChar(AStr2), PWideChar(AStr1))
else
result := MatchPattern(PWideChar(LowerCase(AStr1)), PWideChar(LowerCase(AStr2))) or
MatchPattern(PWideChar(LowerCase(AStr2)), PWideChar(LowerCase(AStr1)));
end;
function EnumerateFiles(const APath, AFilemask : String; const ASearchSubdirs : Boolean; var AFiles : TStringList) : Integer;
var
SearchRec : TSearchRec;
IsFound : Boolean;
begin
result := 0;
IsFound := FindFirst(ITB(APath) + '*.*', faAnyFile, SearchRec) = 0;
While IsFound Do
Begin
If (SearchRec.Name <> '.') and (SearchRec.Name <> '..') Then
Begin
If (ASearchSubdirs) and
(SearchRec.Attr and faDirectory = faDirectory) Then
Inc(result, EnumerateFiles(ITB(APath) + SearchRec.Name, AFilemask, ASearchSubdirs, AFiles))
else
If MatchStrings(ExtractFileExt(SearchRec.Name), AFilemask, FALSE) Then
Begin
AFiles.Add(ITB(APath) + SearchRec.Name);
Inc(result);
End;
End;
IsFound := FindNext(SearchRec) = 0;
End;
FindClose(SearchRec);
end;
function PrepareString(const AString : String) : String;
begin
result := AString;
result := StringReplace(result, '\n', #13#10, [rfReplaceAll]);
result := StringReplace(result, '\_', ' ', [rfReplaceAll]);
end;
procedure Split(const ADelimiter : Char; const AInput : String; const AStrings : TStrings);
begin
If Assigned(AStrings) Then
Begin
AStrings.Clear;
AStrings.Delimiter := ADelimiter;
AStrings.DelimitedText := AInput;
End;
end;
function MatchStrings(const AStr1, AStr2 : String; const ACaseSensitive : Boolean) : Boolean;
function MatchPattern(str1, str2 : PWideChar) : Boolean;
begin
If StrComp(str2, '*') = 0 Then
result := TRUE
else
If (str1^ = #0) and
(str2^ <> #0) Then
result := FALSE
else
If str1^ = #0 Then
result := TRUE
else
Case str2^ of
'*': If MatchPattern(str1, @str2[1]) Then
result := TRUE
else
result := MatchPattern(@str1[1], str2);
'?': result := MatchPattern(@str1[1], @str2[1]);
else
If str1^ = str2^ Then
result := MatchPattern(@str1[1], @str2[1])
else
result := FALSE;
end;
end;
begin
If ACaseSensitive Then
result := MatchPattern(PWideChar(AStr1), PWideChar(AStr2)) or
MatchPattern(PWideChar(AStr2), PWideChar(AStr1))
else
result := MatchPattern(PWideChar(LowerCase(AStr1)), PWideChar(LowerCase(AStr2))) or
MatchPattern(PWideChar(LowerCase(AStr2)), PWideChar(LowerCase(AStr1)));
end;
function EnumerateFiles(const APath, AFilemask : String; const ASearchSubdirs : Boolean; var AFiles : TStringList) : Integer;
var
SearchRec : TSearchRec;
IsFound : Boolean;
begin
result := 0;
IsFound := FindFirst(ITB(APath) + '*.*', faAnyFile, SearchRec) = 0;
While IsFound Do
Begin
If (SearchRec.Name <> '.') and (SearchRec.Name <> '..') Then
Begin
If (ASearchSubdirs) and
(SearchRec.Attr and faDirectory = faDirectory) Then
Inc(result, EnumerateFiles(ITB(APath) + SearchRec.Name, AFilemask, ASearchSubdirs, AFiles))
else
If MatchStrings(ExtractFileExt(SearchRec.Name), AFilemask, FALSE) Then
Begin
AFiles.Add(ITB(APath) + SearchRec.Name);
Inc(result);
End;
End;
IsFound := FindNext(SearchRec) = 0;
End;
FindClose(SearchRec);
end;
Ovako bi izgledao LocalizationStr.pas:
Code:
unit LocalizationStr;
interface
var
RS_AUTHENTICATING : String = 'Authenticating';
RS_RESPONSE_UNKNOWN : String = 'Unknown response (%s%d)';
RS_RESPONSE_REGISTER_EMAIL_SENT : String = 'Registration successful! Please check your inbox for confirmation e-mail';
RS_RESPONSE_CHANNEL_ADDED : String = 'Channel added';
RS_RESPONSE_CHANNEL_PASSWORD_CHANGED : String = 'Channel password changed';
RS_RESPONSE_REQUEST_SENT : String = 'Request sent';
RS_RESPONSE_CONFIRMED_REQUEST : String = 'Confirmed request';
RS_RESPONSE_USER_UNBLOCKED : String = 'Unblocked user';
RS_RESPONSE_USER_BLOCKED : String = 'User blocked';
RS_RESPONSE_COULD_NOT_SEND_EMAIL : String = 'Could not send an email';
RS_RESPONSE_USERNAME_TAKEN : String = 'Username already taken';
RS_RESPONSE_EMAIL_ALREADY_USED : String = 'E-Mail already in use';
RS_RESPONSE_CAPTCHA_ERROR : String = 'Invalid CAPTCHA';
RS_RESPONSE_REQ_LIMIT_REACHED : String = 'Request limit reached';
RS_RESPONSE_INVALID_KEY : String = 'Invalid key';
RS_RESPONSE_INVALID_USERNAME : String = 'Invalid username';
RS_RESPONSE_ALREADY_A_FRIEND : String = 'Already a friend';
RS_RESPONSE_INVALID_CONFIRMATION : String = 'Invalid confirmation';
RS_RESPONSE_INVALID_POSTS : String = 'Invalid posts';
RS_RESPONSE_INVALID_USER : String = 'Invalid user';
RS_RESPONSE_NOT_CHANNEL_OWNER : String = 'You''re not owner of the channel';
RS_RESPONSE_INVALID_USERPASS : String = 'Invalid username or password';
RS_RESPONSE_ALREADY_SENT_REQ : String = 'Request already sent';
RS_BUTTON_REPAIR : String = 'Repair';
RS_RESPONSE_CHANNEL_RESERVED : String = 'Channel is reserved';
RS_RESPONSE_ACCOUNT_NOT_ACTIVATED : String = 'Account not activated\nPlease check your E-Mail inbox for activation mail';
RS_RUN_CLIENT_AS_ADMIN : String = 'Please run client as administrator\n(right click on client icon, then click on "Run as administrator")';
RS_CANNOT_CONNECT : String = 'Cannot connect';
RS_WAITING_FOR_GAME : String = 'Waiting for game...';
RS_GAME_IN_PROGRESS : String = 'Game in progress...\n%.2d:%.2d';
RS_GAME_ENDED : String = 'Game ended!';
RS_WARDIALOG_TITLE : String = 'Please select Warcraft III executable file';
RS_NO_RESPONSE_FROM_SERVER : String = 'No response from server';
RS_GAME_PRECREEPS : String = 'Game started!\n(preparing phase)';
RS_DOWNLOAD_DOWNLOADING : String = 'Downloading file...';
RS_WARCRAFT_REPLAY_NOT_ASSOCIATED : String = 'Replay file isnt associated with Warcraft III! This problem usually happens if you copied game files without installing them. Please reinstall the game.';
RS_STARCRAFT_REPLAY_NOT_ASSOCIATED : String = 'Replay file isnt associated with Starcraft II! This problem usually happens if you copied game files without installing them. Please reinstall the game.';
RS_INVALID_EMAIL : String = 'Invalid E-Mail';
RS_PASSWORD_MISMATCH : String = 'Passwords mismatch';
RS_FILL_ALL_FIELDS : String = 'Please fill all fields';
RS_PASSWORD_TOO_SHORT : String = 'Password must be longer than %d characters';
RS_USERNAME_TOO_SHORT : String = 'Username must be longer than %d characters';
RS_CHECKING_FOR_UPDATES : String = 'Checking for updates...';
RS_REPLAY_DOWNLOADING : String = 'Downloading replay...';
RS_UPDATE_DOWNLOADING : String = 'Downloading update...';
RS_AGREE_TO_TERMS : String = 'You must agree to user''s license agreements';
implementation
end.
unit LocalizationStr;
interface
var
RS_AUTHENTICATING : String = 'Authenticating';
RS_RESPONSE_UNKNOWN : String = 'Unknown response (%s%d)';
RS_RESPONSE_REGISTER_EMAIL_SENT : String = 'Registration successful! Please check your inbox for confirmation e-mail';
RS_RESPONSE_CHANNEL_ADDED : String = 'Channel added';
RS_RESPONSE_CHANNEL_PASSWORD_CHANGED : String = 'Channel password changed';
RS_RESPONSE_REQUEST_SENT : String = 'Request sent';
RS_RESPONSE_CONFIRMED_REQUEST : String = 'Confirmed request';
RS_RESPONSE_USER_UNBLOCKED : String = 'Unblocked user';
RS_RESPONSE_USER_BLOCKED : String = 'User blocked';
RS_RESPONSE_COULD_NOT_SEND_EMAIL : String = 'Could not send an email';
RS_RESPONSE_USERNAME_TAKEN : String = 'Username already taken';
RS_RESPONSE_EMAIL_ALREADY_USED : String = 'E-Mail already in use';
RS_RESPONSE_CAPTCHA_ERROR : String = 'Invalid CAPTCHA';
RS_RESPONSE_REQ_LIMIT_REACHED : String = 'Request limit reached';
RS_RESPONSE_INVALID_KEY : String = 'Invalid key';
RS_RESPONSE_INVALID_USERNAME : String = 'Invalid username';
RS_RESPONSE_ALREADY_A_FRIEND : String = 'Already a friend';
RS_RESPONSE_INVALID_CONFIRMATION : String = 'Invalid confirmation';
RS_RESPONSE_INVALID_POSTS : String = 'Invalid posts';
RS_RESPONSE_INVALID_USER : String = 'Invalid user';
RS_RESPONSE_NOT_CHANNEL_OWNER : String = 'You''re not owner of the channel';
RS_RESPONSE_INVALID_USERPASS : String = 'Invalid username or password';
RS_RESPONSE_ALREADY_SENT_REQ : String = 'Request already sent';
RS_BUTTON_REPAIR : String = 'Repair';
RS_RESPONSE_CHANNEL_RESERVED : String = 'Channel is reserved';
RS_RESPONSE_ACCOUNT_NOT_ACTIVATED : String = 'Account not activated\nPlease check your E-Mail inbox for activation mail';
RS_RUN_CLIENT_AS_ADMIN : String = 'Please run client as administrator\n(right click on client icon, then click on "Run as administrator")';
RS_CANNOT_CONNECT : String = 'Cannot connect';
RS_WAITING_FOR_GAME : String = 'Waiting for game...';
RS_GAME_IN_PROGRESS : String = 'Game in progress...\n%.2d:%.2d';
RS_GAME_ENDED : String = 'Game ended!';
RS_WARDIALOG_TITLE : String = 'Please select Warcraft III executable file';
RS_NO_RESPONSE_FROM_SERVER : String = 'No response from server';
RS_GAME_PRECREEPS : String = 'Game started!\n(preparing phase)';
RS_DOWNLOAD_DOWNLOADING : String = 'Downloading file...';
RS_WARCRAFT_REPLAY_NOT_ASSOCIATED : String = 'Replay file isnt associated with Warcraft III! This problem usually happens if you copied game files without installing them. Please reinstall the game.';
RS_STARCRAFT_REPLAY_NOT_ASSOCIATED : String = 'Replay file isnt associated with Starcraft II! This problem usually happens if you copied game files without installing them. Please reinstall the game.';
RS_INVALID_EMAIL : String = 'Invalid E-Mail';
RS_PASSWORD_MISMATCH : String = 'Passwords mismatch';
RS_FILL_ALL_FIELDS : String = 'Please fill all fields';
RS_PASSWORD_TOO_SHORT : String = 'Password must be longer than %d characters';
RS_USERNAME_TOO_SHORT : String = 'Username must be longer than %d characters';
RS_CHECKING_FOR_UPDATES : String = 'Checking for updates...';
RS_REPLAY_DOWNLOADING : String = 'Downloading replay...';
RS_UPDATE_DOWNLOADING : String = 'Downloading update...';
RS_AGREE_TO_TERMS : String = 'You must agree to user''s license agreements';
implementation
end.
Naravno, ovo je sve hardkodovano u programu, tj ako ne postoje language fajlovi, prikazace se ovi hardkodovani stringovi umesto praznih :)
I ovako bi na kraju trebao da izgleda language fajl za ovu klasu:
Code:
[info]
LanguageName = English
LocalLanguageName = English
CountryCode = GB
Author = Marko Paunovic ([email protected])
[data]
ComponentContainer.pmTrayShowClient = Show client
ComponentContainer.pmTraySettings = Settings
ComponentContainer.pmTrayLanguage = Language
ComponentContainer.pmTrayLogout = Logout
ComponentContainer.pmTrayExit = Exit
LoginWindow.frLogin.lbEMail = E-Mail
LoginWindow.frLogin.lbPassword = Password
LoginWindow.frLogin.chbRemember = Remember me
LoginWindow.frLogin.chbAutoLogin = Auto login
LoginWindow.frLogin.btLogin = Login
LoginWindow.frLogin.btRegister = Register
LoginWindow.frRegister.lbHeader = Become a member of Darer community!
LoginWindow.frRegister.lbEmail = E-Mail:
LoginWindow.frRegister.lbPassword = Password:
LoginWindow.frRegister.lbPasswordConfirm = Confirm password:
LoginWindow.frRegister.lbUsername = Username:
LoginWindow.frRegister.lbCountry = Country:
LoginWindow.frRegister.lbCAPTCHA = Security code:
LoginWindow.frRegister.btCancel = Cancel
LoginWindow.frRegister.btRegisterNow = Register now!
LoginWindow.frRegister.chbUserLicense = I agree to the user's
LoginWindow.frRegister.lbLicenseURL = license agreements
SettingsWindow = Settings
SettingsWindow.tsClient = \_\_Client
SettingsWindow.tsDota = \_\_DotA
SettingsWindow.btDetect = Detect
SettingsWindow.lbLanguage = Language
SettingsWindow.lbWarcraftPath = Warcraft III path
SettingsWindow.chbStartup = Startup with Windows
SettingsWindow.chbMinimizeOnLogin = Minimize on login
SettingsWindow.btOK = OK
SettingsWindow.btCancel = Cancel
MainWindow.pmExitButtonLogout = Logout
MainWindow.pmExitButtonExit = Exit
#MainWindow.btSettings = Settings
#MainWindow.btLogout = Logout
[strresources]
RS_RESPONSE_UNKNOWN = Unknown response (%s%d)
RS_RESPONSE_REGISTER_EMAIL_SENT = Registration successful! Check your inbox for activation e-mail
RS_RESPONSE_COULD_NOT_SEND_EMAIL = Could not send an email
RS_RESPONSE_USERNAME_TAKEN = Username already taken
RS_RESPONSE_EMAIL_ALREADY_USED = E-Mail already in use
RS_RESPONSE_CAPTCHA_ERROR = Invalid CAPTCHA
RS_RESPONSE_REQ_LIMIT_REACHED = Request limit reached
RS_RESPONSE_INVALID_KEY = Invalid key
RS_RESPONSE_INVALID_USERNAME = Invalid username
RS_RESPONSE_INVALID_CONFIRMATION = Invalid confirmation
RS_RESPONSE_INVALID_POSTS = Invalid posts
RS_RESPONSE_INVALID_USER = Invalid user
RS_RESPONSE_INVALID_USERPASS = Invalid username or password
RS_RESPONSE_ALREADY_SENT_REQ = Request already sent
RS_RESPONSE_ACCOUNT_NOT_ACTIVATED = Account not activated\nCheck your inbox for activation mail
RS_AUTHENTICATING = Authenticating...
RS_RUN_CLIENT_AS_ADMIN = Please run client as administrator\n(right click on client icon > "Run as administrator")
RS_WAITING_FOR_GAME = Waiting for game...
RS_GAME_IN_PROGRESS = Game in progress...\n%.2d:%.2d
RS_GAME_ENDED = Game ended!
RS_WARDIALOG_TITLE = Select Warcraft III executable file
RS_NO_RESPONSE_FROM_SERVER = No response from server
RS_GAME_PRECREEPS = Game in progress...\n(preparing phase)
RS_DOWNLOAD_DOWNLOADING = Downloading file...
RS_WARCRAFT_REPLAY_NOT_ASSOCIATED = Replay file isnt associated with Warcraft III! This problem usually happens if you copied game files without installing them. Please reinstall the game.
RS_STARCRAFT_REPLAY_NOT_ASSOCIATED = Replay file isnt associated with Starcraft II! This problem usually happens if you copied game files without installing them. Please reinstall the game.
RS_INVALID_EMAIL = Invalid E-Mail
RS_PASSWORD_MISMATCH = Passwords mismatch
RS_FILL_ALL_FIELDS = Please fill all fields
RS_PASSWORD_TOO_SHORT = Password must be longer than %d characters
RS_USERNAME_TOO_SHORT = Username must be longer than %d characters
RS_CHECKING_FOR_UPDATES = Checking for updates...
RS_AGREE_TO_TERMS = You must agree to user's license agreements
[info]
LanguageName = English
LocalLanguageName = English
CountryCode = GB
Author = Marko Paunovic ([email protected])
[data]
ComponentContainer.pmTrayShowClient = Show client
ComponentContainer.pmTraySettings = Settings
ComponentContainer.pmTrayLanguage = Language
ComponentContainer.pmTrayLogout = Logout
ComponentContainer.pmTrayExit = Exit
LoginWindow.frLogin.lbEMail = E-Mail
LoginWindow.frLogin.lbPassword = Password
LoginWindow.frLogin.chbRemember = Remember me
LoginWindow.frLogin.chbAutoLogin = Auto login
LoginWindow.frLogin.btLogin = Login
LoginWindow.frLogin.btRegister = Register
LoginWindow.frRegister.lbHeader = Become a member of Darer community!
LoginWindow.frRegister.lbEmail = E-Mail:
LoginWindow.frRegister.lbPassword = Password:
LoginWindow.frRegister.lbPasswordConfirm = Confirm password:
LoginWindow.frRegister.lbUsername = Username:
LoginWindow.frRegister.lbCountry = Country:
LoginWindow.frRegister.lbCAPTCHA = Security code:
LoginWindow.frRegister.btCancel = Cancel
LoginWindow.frRegister.btRegisterNow = Register now!
LoginWindow.frRegister.chbUserLicense = I agree to the user's
LoginWindow.frRegister.lbLicenseURL = license agreements
SettingsWindow = Settings
SettingsWindow.tsClient = \_\_Client
SettingsWindow.tsDota = \_\_DotA
SettingsWindow.btDetect = Detect
SettingsWindow.lbLanguage = Language
SettingsWindow.lbWarcraftPath = Warcraft III path
SettingsWindow.chbStartup = Startup with Windows
SettingsWindow.chbMinimizeOnLogin = Minimize on login
SettingsWindow.btOK = OK
SettingsWindow.btCancel = Cancel
MainWindow.pmExitButtonLogout = Logout
MainWindow.pmExitButtonExit = Exit
#MainWindow.btSettings = Settings
#MainWindow.btLogout = Logout
[strresources]
RS_RESPONSE_UNKNOWN = Unknown response (%s%d)
RS_RESPONSE_REGISTER_EMAIL_SENT = Registration successful! Check your inbox for activation e-mail
RS_RESPONSE_COULD_NOT_SEND_EMAIL = Could not send an email
RS_RESPONSE_USERNAME_TAKEN = Username already taken
RS_RESPONSE_EMAIL_ALREADY_USED = E-Mail already in use
RS_RESPONSE_CAPTCHA_ERROR = Invalid CAPTCHA
RS_RESPONSE_REQ_LIMIT_REACHED = Request limit reached
RS_RESPONSE_INVALID_KEY = Invalid key
RS_RESPONSE_INVALID_USERNAME = Invalid username
RS_RESPONSE_INVALID_CONFIRMATION = Invalid confirmation
RS_RESPONSE_INVALID_POSTS = Invalid posts
RS_RESPONSE_INVALID_USER = Invalid user
RS_RESPONSE_INVALID_USERPASS = Invalid username or password
RS_RESPONSE_ALREADY_SENT_REQ = Request already sent
RS_RESPONSE_ACCOUNT_NOT_ACTIVATED = Account not activated\nCheck your inbox for activation mail
RS_AUTHENTICATING = Authenticating...
RS_RUN_CLIENT_AS_ADMIN = Please run client as administrator\n(right click on client icon > "Run as administrator")
RS_WAITING_FOR_GAME = Waiting for game...
RS_GAME_IN_PROGRESS = Game in progress...\n%.2d:%.2d
RS_GAME_ENDED = Game ended!
RS_WARDIALOG_TITLE = Select Warcraft III executable file
RS_NO_RESPONSE_FROM_SERVER = No response from server
RS_GAME_PRECREEPS = Game in progress...\n(preparing phase)
RS_DOWNLOAD_DOWNLOADING = Downloading file...
RS_WARCRAFT_REPLAY_NOT_ASSOCIATED = Replay file isnt associated with Warcraft III! This problem usually happens if you copied game files without installing them. Please reinstall the game.
RS_STARCRAFT_REPLAY_NOT_ASSOCIATED = Replay file isnt associated with Starcraft II! This problem usually happens if you copied game files without installing them. Please reinstall the game.
RS_INVALID_EMAIL = Invalid E-Mail
RS_PASSWORD_MISMATCH = Passwords mismatch
RS_FILL_ALL_FIELDS = Please fill all fields
RS_PASSWORD_TOO_SHORT = Password must be longer than %d characters
RS_USERNAME_TOO_SHORT = Username must be longer than %d characters
RS_CHECKING_FOR_UPDATES = Checking for updates...
RS_AGREE_TO_TERMS = You must agree to user's license agreements
Eto, ako neko uspe da razume sve ovo, hteo bih da cujem misljenje, jer sam siguran da se nesto moze poboljsati :)
Tako sam i ja radio, odnosno po imenu pronađem komponentu i zamenim hint ili caption.
Kod hinta ima dve začkoljice, hint koristi uspravnu crtu | za odvajanje... (videti u helpu čega) pa ako taj karakter treba da bude u hintu onda treba zameniti funkciju koja ima veze sa odvajanje koje radi taj karakter.
Isto tako ako treba više redova u hintu to treba posebno obraditi...
Onda kod comboboxa (i još nekih beše komponenti) treba posebno učitavati vrednosti...
Kod hinta ima dve začkoljice, hint koristi uspravnu crtu | za odvajanje... (videti u helpu čega) pa ako taj karakter treba da bude u hintu onda treba zameniti funkciju koja ima veze sa odvajanje koje radi taj karakter.
Isto tako ako treba više redova u hintu to treba posebno obraditi...
Onda kod comboboxa (i još nekih beše komponenti) treba posebno učitavati vrednosti...