Я уже где-то говорил, и не устану повторять: для решения той или иной задачи существует несколько способов. Вдаваться в полемику в пользу того или иного мне не интересно. Лишь обозначу, что для решения задачи локализации можно использовать библиотеку, т.е. Dll-ку, а можно - файл настроек. Обязательно найдутся охотники по ратовать за использование реестра Windows. Это, еще раз повторю - дело вкуса. В каждом из способов есть свои достоинства и свои недостатки.
Известно, что файл настроек может иметь вот такую структуру:
[Название секции]
Имя переменной1=Значение переменной1
Имя переменной2=Значение переменной2
...
Имя переменнойN=Значение переменнойN
Т.е. в разных файлах можно одной и той же переменной присваивать различные значения. Указав такую переменную в качестве, допустим, надписи на кнопке, мы сможем получить надписи на различных языках, если при загрузке формы брать данные из определенного заранее файла.
Заниматься переводом подписей на всех без исключения элементах управления я не стану: долго и нудно. Покажу лишь на примере главного меню формы MainFrm, как это реализуется.
Чтобы файлы языковой поддержки не путались с файлами настроек (ini), предлагаю дать им расширение *.lng.
Вот примерное содержимое двух файлов для отображения интерфейса программы "Расходы" на русском и английском языках:
Rus.lng
[MainFrm]
MainFormCap=Расходы (главная форма)
Menu_File=&Файл
Menu_File_Exit=&Выход
Menu_Data=&Данные
Menu_Data_Edit=&Ввести
Menu_Data_Insert=&Новая запись
Menu_Data_Filter=&Фильтр
Menu_Data_Credit=&Кредиты
Menu_Data_Export=&Экспорт
Menu_Data_Import=&Импорт
Menu_Reports=&Отчетные формы
Menu_Reports_Reverse_statement=&Оборотная ведомость
Menu_Reports_Turnovers_account=&Обороты по счету
Menu_Reports_Cost_Analysis_All=&Анализ затрат (все)
Menu_Reports_Cost_Analysis_Gruops=Анализ затрат (по &группам)
Menu_Reports_Cost_Analysis_Trends=Анализ &тенденций
Menu_Codifiers=&Кодификаторы
Menu_Codifiers_Accounts=&Счета
Menu_Codifiers_Group_costs=&Группы затрат
Menu_Codifiers_Memorial_warrants=&Мемориальные ордера
Menu_Codifiers_Valuta=&Валюты
Menu_Service=&Настройки
Menu_Service_SelectDisk=Выбор &диска (пути к базе данных)
Menu_Service_Language=&Выбор языка
Menu_Service_Clear=&Очистка БД
Menu_Help=&Справка
Menu_Help_About=&О программе
Eng.lng
[MainFrm]
MainFormCap=Expenses (Main form)
Menu_File=&File
Menu_File_Exit=&Exit
Menu_Data=&Data
Menu_Data_Edit=&Edit
Menu_Data_Insert=&New Record
Menu_Data_Filter=&Filter
Menu_Data_Credit=&Credits
Menu_Data_Export=&Export
Menu_Data_Import=&Import
Menu_Reports=&Reports
Menu_Reports_Reverse_statement=&Reverse statement
Menu_Reports_Turnovers_account=&Turnovers account
Menu_Reports_Cost_Analysis_All=&Cost analysis (All)
Menu_Reports_Cost_Analysis_Gruops=Cost analysis (&gruops)
Menu_Reports_Cost_Analysis_Trends=Check &Trends
Menu_Codifiers=&Codifiers
Menu_Codifiers_Accounts=&Accounts
Menu_Codifiers_Group_costs=&Group costs
Menu_Codifiers_Memorial_warrants=&Memorial warrants
Menu_Codifiers_Valuta=&Valuta
Menu_Service=&Service
Menu_Service_SelectDisk=&Select path
Menu_Service_Language=&Language
Menu_Service_Clear=&Clear data
Menu_Help=&Help
Menu_Help_About=&About prog
Файлы эти создаются как и файлы ini в любом текстовом редакторе, например: в блокноте.
Важно: имена переменных в этих файлах и количество строк, а следовательно и количество переменных, в этих файлах должно совпадать.
Кстати, в Rashod.ini должна пополниться секция:
[Constants]
LangFileName=Rus.lng
- пусть уж программа стартует с привычного нам языка, чтоб самих себя не испугать :-)
На этом предварительные танцы с бубнами и беличьими хвостиками закончены. Открываем проект "Rashod".
И первое, что необходимо сделать - создать процедуру, устанавливающую локализацию, назову ее SetLang (не забудьте декларировать ее в секции private):
procedure TMainFrm.SetLang();
Var
ini: TIniFile;
begin
// Настройка интерфейса программы (по выбранному языку)
ini:=TiniFile.Create(GetCurrentDir + '\'+Lang);
MainFrm.Caption:=Ini.ReadString('MainFrm','MainFormCap','');
N_File.Caption:=Ini.ReadString('MainFrm','Menu_File','');
N_Exit.Caption:=Ini.ReadString('MainFrm','Menu_File_Exit','');
N_Data.Caption:=Ini.ReadString('MainFrm','Menu_Data','');
N_Edit.Caption:=Ini.ReadString('MainFrm','Menu_Data_Edit','');
N12_Ins.Caption:=Ini.ReadString('MainFrm','Menu_Data_Insert','');
N10_Filter.Caption:=Ini.ReadString('MainFrm','Menu_Data_Filter','');
N_Credit.Caption:=Ini.ReadString('MainFrm','Menu_Data_Credit','');
N_ExportToMDB.Caption:=Ini.ReadString('MainFrm','Menu_Data_Export','');
N_Import.Caption:=Ini.ReadString('MainFrm','Menu_Data_Import','');
N_Reports.Caption:=Ini.ReadString('MainFrm','Menu_Reports','');
N3.Caption:=Ini.ReadString('MainFrm','Menu_Reports_Reverse_statement','');
N4.Caption:=Ini.ReadString('MainFrm','Menu_Reports_Turnovers_account','');
N_Analiz.Caption:=Ini.ReadString('MainFrm','Menu_Reports_Cost_Analysis_All','');
N_AnalizGroup.Caption:=Ini.ReadString('MainFrm','Menu_Reports_Cost_Analysis_Gruops','');
N_Analiz_Trends.Caption:=Ini.ReadString('MainFrm','Menu_Reports_Cost_Analysis_Trends','');
N_Kodifikators.Caption:=Ini.ReadString('MainFrm','Menu_Codifiers','');
N1.Caption:=Ini.ReadString('MainFrm','Menu_Codifiers_Accounts','');
N_ExpGr.Caption:=Ini.ReadString('MainFrm','Menu_Codifiers_Group_costs','');
N2.Caption:=Ini.ReadString('MainFrm','Menu_Codifiers_Memorial_warrants','');
N_Val.Caption:=Ini.ReadString('MainFrm','Menu_Codifiers_Valuta','');
N_Serv.Caption:=Ini.ReadString('MainFrm','Menu_Service','');
N7_SelectDisk.Caption:=Ini.ReadString('MainFrm','Menu_Service_SelectDisk','');
N_Serv_SelLang.Caption:=Ini.ReadString('MainFrm','Menu_Service_Language','');
N12_ServClear.Caption:=Ini.ReadString('MainFrm','Menu_Service_Clear','');
N_Help.Caption:=Ini.ReadString('MainFrm','Menu_Help','');
N_About.Caption:=Ini.ReadString('MainFrm','Menu_Help_About','');
ini.Free;
end;
Общий смысл этой процедуры, думаю, не вызывает вопросов, поскольку, о работе с ini фалами я уже рассказывал ранее: открыли, считали нужные данные, присвоив их целевым надписям на элементах управления формы, освободились от ini файла.
Необходимая переменная Lang, хранящая имя языкового файла, должна быть объявлена в секции interface модуля формы. А вот значение в нее попадет в момент создания формы (Create), откуда - из Rashod.ini:
procedure TMainFrm.FormCreate(Sender: TObject);
var
ini: TIniFile;
begin
// Подключение и считывание из файла настроек ini
ini:=TiniFile.Create(GetCurrentDir + '\Rashod.ini');
Lang:=Ini.ReadString('Constants','LangFileName','');
ini.Free;
SetLang;
...
- И что? - скажете Вы после компиляции проекта, - никаких изменений нет.
Видимых изменений нет. Попробуйте поменять в Rashod.ini Rus.lng на Eng.lng и еще раз запустить программу.
Можно радоваться?
Рано.
Хотелось бы, чтобы была возможность менять языковую настройку из самой программы.
Для этого нужно придумать обработку соответствующего пункта меню (Настройки - Выбор языка):
procedure TMainFrm.N_Serv_SelLangClick(Sender: TObject); // Настройка. Выбор языка
var
ini: TIniFile;
begin
// Настройка фильтра файлов определенного типа в окне диалога
OpenDialog1.Filter:='Файлы языковой поддержки|*.lng';
// Выбор файла на диске
If not OpenDialog1.Execute
then // Отмена выбора
begin
exit;
end;
// Извлекается
Lang:=OpenDialog1.FileName; // Полный путь
Lang:=ExtractFileName(Lang); // Только имя файла
// Запись в соответствующую секцию Rashod.ini, чтобы
// в следующий раз программа стартовала с этими настройками
ini:=TiniFile.Create(GetCurrentDir + '\Rashod.ini');
Ini.WriteString('Constants','LangFileName',Lang);
ini.Free;
// Смена надписей на элементах управления
SetLang;
end;
В комментариях я постарался дать необходимые пояснения. Вот теперь программа "Rashod" еще больше стала похожа на "взрослую" :-)
Я не затрагиваю так или иначе вопросы оптимизации уже написанного кода - это отдельная непростая история. Но здесь меня просто подмывает сделать оговорку:
вместо двух строк
Lang:=OpenDialog1.FileName; // Полный путь
Lang:=ExtractFileName(Lang); // Только имя файла
можно написать одну
Lang:=ExtractFileName(OpenDialog1.FileName);
Иногда приходится жертвовать красотой ради наглядности :-)
Если остались вопросы - пожалуйте на страницу "Обратная связь"
Не получается задекларировать SetLang в секции private, ошибка, покажите как на примере
ОтветитьУдалитьТа же фигня, как задекларировать? Какие параметры у процедуры???
ОтветитьУдалить