Клубове Дир.бг
powered by diri.bg
търси в Клубове diri.bg Разширено търсене

Вход
Име
Парола

Клубове
Dir.bg
Взаимопомощ
Горещи теми
Компютри и Интернет
Контакти
Култура и изкуство
Мнения
Наука
Политика, Свят
Спорт
Техника
Градове
Религия и мистика
Фен клубове
Хоби, Развлечения
Общества
Я, архивите са живи
Клубове Дирене Регистрация Кой е тук Въпроси Списък Купувам / Продавам 10:51 29.05.24 
Клубове/ Компютри и Интернет / Delphi Всички теми Следваща тема Пълен преглед*
Информация за клуба
Тема Re: Многоезичен интерфейс [re: tolini]
Автор andrew_nikoloff (bugbuster)
Публикувано19.03.07 22:09  



По същество цялата задача се състои в това да си подмениш елементите на интерфейса, които са специфични за езика (надписи, картинки и други). Когато използваш INI файлове най-лесно ще е да имаш по един файл за всеки език. Изборът на език за интерфейса може да става или като потребителят избира един от файловете като го преименува, поставя в определена папка или нещо подобно, или пък в конфигурацията на програмата се задава от кой файл да си чете "преводите".
Съдържанието на INI файла може да ти бъде нещо от сорта на:
[Form1]
Buton1.Caption=Затваряне
Buton1.Hint=Изход от приложението
Label1.Caption=Изход от програмата
Picture1=BG_Logo.bmp
и т.н.
"Превеждането" на интерфейса на приложението в нашия случай може да стане така (по най-тривиалния начин):


procedure TForm1.FormShow(Sender: TObject);
begin
Button1.Caption := iniTranslations.ReadString('Form1', 'Button1.Caption', 'Изход');
Button1.Hint := iniTranslations.ReadString('Form1', 'Button1.Hint', 'Изход от програмата');
Label1.Caption := iniTranslations.ReadString('Form1', 'Label1.Caption', 'Изход');
Picture1.LoadFromFile(iniTranslations.ReadString('Form1', 'Picture1', 'BG_Logo.bmp'));
end;

С този пример само демонстрирам принципа на "превода". За реални приложения той е практически неприложим. Основните му недостатъци са, че при добавянето на компонент във формата програмистът трябва да се сети и да коригира кода за превод, а също така и размерът на кода за една по-сложна форма се получава бая голям и трудно ще се поддържа.
Един възможен изход от ситуацията е всяка форма да може да се превежда сама себе си. Ако имаш обща базова форма (форма, на която останалите да са ти наследници) можеш да си дефинираш един виртуален метод, който да обхожда всички контроли по формата и да ги "превежда". Ако нямаш общ родител - дефинирай си една процедурка някъде в някакво модулче, която да приема за параметър форма и да я превежда.
Обхождането на контролите на формата може да стане, като се ползват пропъртитата Controls и ControlCount. Проблемът обаче е, че ако имаш някакви контейнери (TPanel, TGroupBox, вложени форми и т.н.) техните контроли не влизат в този списък. Решението е ако при обхождането на списъка с контроли попаднем на наследник на TWinControl да обходим и неговите Controls (рекурсивно обхождаме всички контроли по формата). Ето една процедурка, която върши тая работа:

type
TtcCallBackMethod = procedure(Section: String; Control: TControl);

procedure TraverseControls(Section: String; Container: TWinControl; CallBackFunction: TtcCallBackMethod);
var
i: Integer;
Comp: TControl;
begin

for i := 0 to Container.ControlCount - 1 do
begin
Comp := Container.Controls[ i ]; //Все го забравям тоя таг... :-/
if (Comp is TWinControl) and (not (Comp is TCustomForm)) then
TraverseControls(Section, TWinControl(Comp), CallBackFunction);
CallBackFunction(Section, Comp);
end;
end;


Тази процедура ще обходи всичките ти контроли в подадената й форма и за всеки един от тях ще ти извика твоя метод, който си подал като параметър.
Той от своя страна трябва да провери какъв е този контрол и съответно да извлече неговите "преводи" от INI файла. Например:

procedure TranslateControl(Section: String; Control: TControl);
begin
if Control is TButton then
begin
(Control as TButton).Caption := iniTranslations.ReadString(Section, Control.Name + '.Caption', '');
(Control as TButton).Hint := iniTranslations.ReadString(Section, Control.Name + '.Hint', '');
end
else if Control is TImage then
begin
(Control as TImage).Picture.LoadFromFile(iniTranslations.ReadString(Section, Control.Name, ''));
end
else ...
...
...
...
end;

По този начин за да преведеш една форма трябва просто някъде от нея (например в OnShow събитието) да извикаш:

TraverseControls(Name, Self, TranslateControl);

По този код има какво да се подобри. Например в процедурата за "превеждане" на контрол можеш да правиш проверка дали в INI файла има такъв запис и ако го няма - да отбележиш това (например такава е ситуацията, когато в едно "преведено" вече приложение добавиш контрол в някоя форма. Например добавиш нов бутон).
Това решение също така не отчита някои други фактори на професионално направения многоезичен интерфейс. Например ширината на бутоните и т.н. Типичен пример - бутон "OK" на английски и "Потвърждение" на български. Познай дали в българската локализация текста ще се събере в бутона

Надявам се, че не съм те отегчил твърде много

Успех!

Редактирано от andrew_nikoloff на 19.03.07 22:14.



Цялата тема
ТемаАвторПубликувано
* Многоезичен интерфейс tolini   19.03.07 16:08
. * Re: Многоезичен интерфейс vido   19.03.07 18:27
. * Re: Многоезичен интерфейс andrew_nikoloff   19.03.07 22:09
. * Re: Многоезичен интерфейс tolini   20.03.07 08:19
. * Re: Многоезичен интерфейс backinblack   06.04.07 19:26
Клуб :  


Clubs.dir.bg е форум за дискусии. Dir.bg не носи отговорност за съдържанието и достоверността на публикуваните в дискусиите материали.

Никаква част от съдържанието на тази страница не може да бъде репродуцирана, записвана или предавана под каквато и да е форма или по какъвто и да е повод без писменото съгласие на Dir.bg
За Забележки, коментари и предложения ползвайте формата за Обратна връзка | Мобилна версия | Потребителско споразумение
© 2006-2024 Dir.bg Всички права запазени.