Базы данныхИнтернетКомпьютерыОперационные системыПрограммированиеСетиСвязьРазное
Поиск по сайту:
Подпишись на рассылку:

Назад в раздел

Многоязычный интерфейс приложений в Delphi

div.main {margin-left: 20pt; margin-right: 20pt} Многоязычный интерфейс приложений в Delphi
Автор: Денис Колисниченко, dhsilabs@mail.ru
Опубликовано: 08.02.2002
Оригинал: http://www.softerra.ru/review/program/15794/

Наверняка, вам хоть раз в жизни приходилось разрабатывать многоязычное приложение. Например, вам нужно, чтобы ваше приложение «ругалось» как на английском, так и на русском языке. В таком случае, обычно, один язык встраивается в приложение, как правило, английский, а потом пользователю предоставляется возможность выбрать язык интерфейса программы.
Для этих целей существует много коммерческих и бесплатных компонент-переводчиков, однако использовать их довольно неудобно, поскольку, необходимо помещать копию компонента на каждую форму приложения. Я предлагаю совершенно другой подход, а именно – использовать модуль-переводчик, который будет переводить все формы приложения. При достаточно высокой скорости перевода интерфейса, размер программы увеличиться всего на 3Кб (именно столько «весит» модуль)
Алгоритм работы такой: функция TranslateForm обходит все компоненты формы и переводит их на указанный язык, используя для этого специальный словарь. Словарь имеет формат Ini-файла, поэтому, как и для всех остальных Ini-файлов, для этого файла существует ограничение размера – не более 64 Кб, если я, конечно, не ошибаюсь. Решить эту проблему можно достаточно просто – использовать несколько словарей для разных языков.
Приведу раздел объявления нашего модуля (interface):

Пример 1 interface uses SysUtils, Classes, Controls, Forms, Dialogs, Quickrpt, ... ; function Translate(Text : string; Lang : string; Dict : TIniFile):string; procedure TranslateForm(Form : TForm; Lang : string; DictFileName : string);

Процедура TranslateForm, как я уже писал, обходит все компоненты формы, а функция Trasnlate – выполняет перевод. Переводятся текстовые свойства компонент, например, Caption и Hint. При вызове функции нужно указать следующие параметры: Form : TForm; Lang : string; DictFileName : string

Параметр Form определяет форму, которую нужно перевести. Параметр Lang – это язык на который нужно перевести свойство компонента. Тот язык, с которым работает программа в данный момент, будем называть ключевым. Подразумевается, что в данный момент (до перевода) программа работает с ключевым языком, потому что поиск (перевод) слов будет произведен с использованием ключевого языка. Чтобы было понятнее, приведу пример словаря:

Пример 2 [Rus] File=Файл Open=Открыть Translate=Перевести Application=Приложение New=Создать Open=Открыть Text=Текст Save=Сохранить Save As...=Сохранить как... Print=Печать Print Setup=Параметры печати Exit=Выход Edit=Правка Cut=Вырезать Copy=Копировать Paste=Вставить Undo=Отмена View=Вид Status bar=Панель состояния Tool bar=Панель инструментов Tools=Сервис Settings=Параметры ...

Для перевода интерфейса приложения с английского на русский язык нужно вызвать процедуру TrasnlateForm так: TranslateForm(Form1, 'Rus', 'trans.dic');При этом ключевым языком считается английский (см. секцию Rus в примере 2). Аналогично можно создать секцию Eng и использовать русский язык в качестве ключевого.

Для того, чтобы перевести все формы приложения используйте следующие операторы: for i:=0 to Screen.FormCount-1 do TranslateForm(Screen.Forms[i],'Rus','trans.dic');

Если вы хотите изменить язык приложения во время его запуска, отредактируйте файл проекта так: for i:=0 to Screen.FormCount-1 do TranslateForm(Screen.Forms[i],'Rus','trans.dic'); Application.Run;

То есть перевод форм нужно выполнить до выполнения метода Application.Run;

Теперь рассмотрим весь исходный код модуля-переводчика:

Пример 3. Файл trans.pas unit trans; interface uses SysUtils, Classes, Controls, Forms, Dialogs, Quickrpt, QRCtrls, StdCtrls, Buttons, ComCtrls, ExtCtrls, DBCtrls, DB, DBGrids, Menus, Grids, Mask, IniFiles; function Translate(Text : string; Lang : string; Dict : TIniFile):string; procedure TranslateForm(Form : TForm; Lang : string; DictFileName : string); implementation { Непосредственный перевод текста } function Translate(Text : string; Lang : string; Dict : TIniFile):string; var s : string; begin Result:=Text; S:=Dict.ReadString(Lang, Text, ''); if S='' then Dict.WriteString(Lang, Text, ''); if S<>'' then Result:=S; end; procedure TranslateForm(Form : TForm; Lang : string; DictFileName : string); var Dict : TIniFile; I,J : Integer; Obj : TObject; begin { Открываем словарь. Перед вызовом функции Translate словарь должен быть открыт! } Dict:=TIniFile.Create(DictFileName); if not fileexists(DictFileName) then ShowMessage('No exists' + DictFileName); Form.Caption:=Translate(Form.Caption, Lang, Dict); Application.Title:=Translate(Application.Title, Lang, Dict); { Переводим компоненты формы} For I:=0 to Form.ComponentCount-1 do Begin Obj:=Form.Components[i]; if Obj is TMenuItem then begin TMenuItem(Obj).Caption:=Translate(TMenuItem(Obj).Caption, Lang, Dict); TMenuItem(Obj).Hint:=Translate(TMenuItem(Obj).Hint, Lang, Dict); end; if Obj is TButton then begin TButton(Obj).Caption:=Translate(TButton(Obj).Caption, Lang, Dict); TButton(Obj).Hint:=Translate(TButton(Obj).Hint, Lang, Dict); end; if Obj is TBitBtn then begin TBitBtn(Obj).Caption:=Translate(TBitBtn(Obj).Caption, Lang, Dict); TBitBtn(Obj).Hint:=Translate(TBitBtn(Obj).Hint, Lang, Dict); end; if Obj is TSpeedButton then begin TSpeedButton(Obj).Caption:=Translate(TSpeedButton(Obj).Caption, Lang, Dict); TSpeedButton(Obj).Hint:=Translate(TSpeedButton(Obj).Hint, Lang, Dict); end; if Obj is TPanel then begin TPanel(Obj).Caption:=Translate(TPanel(Obj).Caption, Lang, Dict); TPanel(Obj).Hint:=Translate(TPanel(Obj).Hint, Lang, Dict); end; if Obj is TGroupBox then begin TGroupBox(Obj).Caption:=Translate(TGroupBox(Obj).Caption, Lang, Dict); TGroupBox(Obj).Hint:=Translate(TGroupBox(Obj).Hint, Lang, Dict); end; if Obj is TLabel then begin TLabel(Obj).Caption:=Translate(TLabel(Obj).Caption, Lang, Dict); TLabel(Obj).Hint:=Translate(TLabel(Obj).Hint, Lang, Dict); end; if Obj is TStaticText then begin TStaticText(Obj).Caption:=Translate(TStaticText(Obj).Caption, Lang, Dict); TStaticText(Obj).Hint:=Translate(TStaticText(Obj).Hint, Lang, Dict); end; if Obj is TQRLabel then begin TQRLabel(Obj).Caption:=Translate(TQRLabel(Obj).Caption, Lang, Dict); TQRLabel(Obj).Hint:=Translate(TQRLabel(Obj).Hint, Lang, Dict); end; if Obj is TEdit then TEdit(Obj).Hint:=Translate(TEdit(Obj).Hint, Lang, Dict); if Obj is TMaskEdit then TMaskEdit(Obj).Hint:=Translate(TMaskEdit(Obj).Hint, Lang, Dict); if Obj is TMemo then TMemo(Obj).Hint:=Translate(TMemo(Obj).Hint, Lang, Dict); if Obj is TRadioGroup then begin TRadioGroup(Obj).Caption:=Translate(TRadioGroup(Obj).Caption, Lang, Dict); TRadioGroup(Obj).Hint:=Translate(TRadioGroup(Obj).Hint, Lang, Dict); for J:=0 to TRadioGroup(Obj).Items.Count-1 do begin TRadioGroup(Obj).Items[j]:=Translate(TRadioGroup(Obj).Items[j], Lang, Dict); end; end; if Obj is TCheckBox then begin TCheckBox(Obj).Caption:=Translate(TCheckBox(Obj).Caption, Lang, Dict); TCheckBox(Obj).Hint:=Translate(TCheckBox(Obj).Hint, Lang, Dict); end; if Obj is TField then TField(Obj).DisplayLabel:=Translate(TField(Obj).DisplayLabel, Lang, Dict); if Obj is TTabSheet then begin TTabSheet(Obj).Caption:=Translate(TTabSheet(Obj).Caption, Lang, Dict); TTabSheet(Obj).Hint:=Translate(TTabSheet(Obj).Hint, Lang, Dict); end; if Obj is TOpenDialog then TOpenDialog(Obj).Title:=Translate(TOpenDialog(Obj).Title, Lang, Dict); if Obj is TSaveDialog then TSaveDialog(Obj).Title:=Translate(TSaveDialog(Obj).Title, Lang, Dict); if Obj is TPrintDialog then TPrintDialog(Obj).Title:=Translate(TPrintDialog(Obj).Title, Lang, Dict); if Obj is TPrinterSetupDialog then TPrinterSetupDialog(Obj).Title:=Translate(TPrinterSetupDialog(Obj).Title, Lang, Dict); End; { освобождаем память} Dict.Free; end; end.

Естественно, перед использованием модуля его нужно добавить в оператор uses: uses ..., trans;

Примечания

1. Теперь нужно отметить особенность функции Translate. Если слова нет в словаре, она его автоматически добавляет. Потом вам только останется самому ввести перевод этого слова!

2. Напомню, что поиск словаря, так как он является ini-файлом, по умолчанию производится в каталоге C:Windows (точнее, в каталоге, возвращаемом функцией GetWindowsDirectory), поэтому предварительно нужно поместить туда словарь или явно указать имя файла. При этом удобно использовать функцию ExtractFileDir так: ExtractFileDir(Application.EXEName+'trans.dic')

3. Исходный код модуля-переводчика может распространятся согласно положениям лицензии GPL, текст которой вы можете прочитать на моем сайте – http://dkws.narod.ru/.

Посмотрим, что у нас вышло, как говорится, «до» (см. рисунок 1) и «после» (см. рисунок 2).

 

Рисунок 1. «До»

 

Рисунок 2. «После»




  • Главная
  • Новости
  • Новинки
  • Скрипты
  • Форум
  • Ссылки
  • О сайте




  • Emanual.ru – это сайт, посвящённый всем значимым событиям в IT-индустрии: новейшие разработки, уникальные методы и горячие новости! Тонны информации, полезной как для обычных пользователей, так и для самых продвинутых программистов! Интересные обсуждения на актуальные темы и огромная аудитория, которая может быть интересна широкому кругу рекламодателей. У нас вы узнаете всё о компьютерах, базах данных, операционных системах, сетях, инфраструктурах, связях и программированию на популярных языках!
     Copyright © 2001-2024
    Реклама на сайте