Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

ExCode.ru - программирование на высоком уровне - выпуск 16


Информационный Канал Subscribe.Ru

ExCode.ru - программирование на высоком уровне
Выпуск №16 ( 2005.11.12 )
Здравствуйте, уважаемые подписчики!

За эту неделю сайт значительно прееобразился, в основном за счет множества новых статей. Поэтому всех приглашаю заходить и читать. А так же приглашаю в наш кодерский магазин, где вы можете купить DVD или CD с различным софтом для программистов.


Новости копьютерного мира:
2005-11-08    Урезанная версия Oracle - бесплатно
Oracle выпустила урезанную версию своей базы данных. Бесплатная версия нацелена на разработчиков, студентов, начинающих пользователей и на сообщество Open Source.

2005-11-07    Пойманы румынские eBay-жулики
Преступная группировка из трех румын попалась на жульничестве с клиентами eBay. Мошенники орудовали на британском филиале eBay, успев за время своей деятельности похитить в общей сложности свыше 300 тыс. фунтов.

2005-11-08    Основатель eBay пожертвовал $100 млн. нуждающимся
Основатель всемирно известного интернет-аукциона eBay Пьер Омидьяр (Pierre Omidyar) со своей супругой, Пэм Омидьяр, пожертвовали $100 млн. Университету Тафтс. Эти деньги, как предполагается, будут использованы для выдачи ссуд жителям развивающихся стран, желающим начать собственный бизнес.

2005-11-08    IBM и Sun Microsystems совместно поддержат формат OpenDocument
Компании IBM и Sun Microsystems 4 ноября организовали частную встречу с целью сплотить и скоординировать свои усилия в поддержку нового формата OpenDocument, который способен стать новым, революционным стандартом в электронном документообороте.

2005-11-08    Microsoft предупредила, что никакого Windows XP SP3 не выпускала
Представители Microsoft выступили с предупреждением против появившейся недавно в Сети "третьей версии пакетов обновлений" для WinXP, впервые упомянутой сайтом TheHotfix.net, заявившем, что "неофициальный пакет обновлений" состоит из подборки заплаток, выпущенных самой компанией.

2005-11-08    Заплатка Sony способна покалечить Windows
Некоторое время тому назад компанию Sony BMG обвинили в том, что с целью защитить свои диски от несанкционированного копирования она использует специальную программу, которая без ведома пользователей устанавливается на их ПК.

2005-11-08    IBM и Sun Microsystems совместно поддержат формат OpenDocument
Компании IBM и Sun Microsystems 4 ноября организовали частную встречу с целью сплотить и скоординировать свои усилия в поддержку нового формата OpenDocument, который способен стать новым, революционным стандартом в электронном документообороте.

2005-11-07    В Сети появилась программа для "разблокирования" музыки с iTunes
Программа HotRecorder, недавно появившаяся в Сети, позволяет легко конвертировать музыкальные файлы форматов iTunes и музыкального сервиса Yahoo во вполне нормально читаемые МР3.

2005-11-07    Интернет убивает газеты
MediaDailyNews сообщает, что конец 2005 года - один из самых худших дней в истории газет. Развитие Интернета и ранее оказывало не слишком благоприятное влияние на бумажные газеты, а в последний год влияние это можно назвать и вовсе катастрофическим.

2005-11-07    Продажи серверов растут, а доходы падают
По сведениям Gartner, на территории Латинской Америки во втором квартале текущего года отмечен заметный прирост объемов продаж серверов. Однако, несмотря на 17% рост этого показателя в сравнении с итогами второго квартала 2004 года, доходы от этого напротив, снизились - почти на 11%.

Статья номера:

Поддержка многоязычного интерфейса


Подчас бывает актуально встроить в разрабатываемую программу поддержку нескольких языков. Существует множество средств и компонентов для осуществления подобных задач. У всех этих средств один недостаток - они слишком сложны и тяжеловесны. Предлагаем рассмотреть, как можно обеспечить поддержку многоязычности используя более простой и прозрачный метод.

Первое, что нужно выяснить - это язык, на котором разрабатывать интерфейс первоначально. Есть веские причины за то, чтобы использовать для этого именно тот язык, на котором написана эта статья. Дело в том, что русский язык менее лаконичен других европейских языков. При переводе на английский или немецкий 90% фраз будет компактнее и интерфейс вашей программы искажен не будет.

Для поддержки нескольких языков предлагается следующий простой подход. Интерфейс оформляется на родном языке - русском. Для всех остальных языков составляется словарь в виде:


Строка на языке 1=Строка на языке 2
Строка на языке 1=Строка на языке 2

Например:


Файл=File
Выход=Exit
Отмена=Cancel

И так для всех ресурсов приложения. Словарь поместим в отдельный текстовый файл.

Далее, нам необходимо для каждого текстового свойства любого компонента приложения поискать перевод в нашем словаре. Здесь не обойтись без Delphi RTTI. Через Component.ClassInfo получим ссылку на информацию типа, а затем GetTypeData(TypeInf) даст нам указатель на структуру с его описанием.


TypeInf := Component.ClassInfo;
AName := TypeInf^.name; 
TypeData := GetTypeData(TypeInf); 
NumProps := TypeData^.PropCount; 

Далее проходимся по всем свойствам данного (классового) типа:


GetMem(PropList, NumProps * sizeof(pointer));

try
  GetPropInfos(TypeInf, PropList);

  for i := 0 to NumProps-1 do
  begin
    PropName := PropList^[i]^.name;

    PropTypeInf := PropList^[i]^.PropType^;
    PropInfo := PropList^[i];


    case PropTypeInf^.Kind of
      tkString, tkLString: //... это то, что нам нужно
        if PropName <> ′Name′ then { Переводить свойство Name не следует }
        begin
          { Получение значения свойства и поиск перевода в словаре }
          StringPropValue := GetStrProp(Component, PropInfo);
          SetStrProp(Component, PropInfo, TranslateString(StringPropValue));
        end;
 ...
 ...

Отдельный случай - списки TStrings и коллекции типа TTReeNodes и TListItems. Их придется обработать персонально.


tkClass:
begin
  PropObject := GetObjectProp(Component, PropInfo{, TPersistent});

  if Assigned(PropObject)then
  begin
    { Для дочерних свойств-классов вызов просмотра свойств }
    if (PropObject is TPersistent) then
      UpdateComponent(PropObject as TPersistent);

    { Индивидуальный подход к некоторым классам }
    if (PropObject is TStrings) then
    begin
      for j := 0 to (PropObject as TStrings).Count-1 do
        TStrings(PropObject)[j] := TranslateString(TStrings(PropObject)[j]);
    end;
    if (PropObject is TTreeNodes) then
    begin
      for j := 0 to (PropObject as TTreeNodes).Count-1 do
        TTreeNodes(PropObject).Item[j].Text :=
        TranslateString(TTreeNodes(PropObject).Item[j].Text);
    end;
    if (PropObject is TListItems) then
    begin
      for j := 0 to (PropObject as TListItems).Count-1 do
        TListItems(PropObject).Item[j].Caption
        := TranslateString(TListItems(PropObject).Item[j].Caption);
    end;
{ Здесь можно добавить обработку остальных классов }
end; 

end;

Объединяя все написанное, получим компонент для перевода строковых ресурсов.


unit glLanguageLoader;

interface
{$I glDEF.INC}

uses
  Windows, Messages, SysUtils, Classes, Graphics,
  Controls, Forms, Dialogs, comctrls, grids;

type
  TLanguageLoaderOptions = set of (lofTrimSpaces);
  {опция удаления начальных и завершающих пробелов}

  TglLanguageLoader = class(TComponent)
  private
    sl: TStringList;
    FOptions: TLanguageLoaderOptions;
    function TranslateString(sString: string): string;
  protected
    procedure UpdateComponent(Component: TPersistent); virtual;
  public
    {main function}
    procedure LoadLanguage(Component: TComponent; FileName: string);
  published
    property Options: TLanguageLoaderOptions read FOptions write FOptions;
  end;

  procedure LoadLanguage(Component: TComponent; FileName: string;
  Options: TLanguageLoaderOptions);
  procedure register;

implementation

uses
  TypInfo, dsgnintf;

procedure register;
begin
  RegisterComponents(′Gl Components′, [TglLanguageLoader]);
end;

{Ф-ия для загрузки словаря без предварительного создания компонента}
procedure LoadLanguage(Component: TComponent; FileName: string;
Options: TLanguageLoaderOptions);
var
  LanguageLoader: TglLanguageLoader;
begin
  LanguageLoader := TglLanguageLoader.Create(nil);
  try
    LanguageLoader.LoadLanguage(Component, FileName);
  finally
    LanguageLoader.Free;
  end;
end;

{ TglLanguageLoader }

{ Загрузка словаря, обход указанного компонента и }
{ всех его дочерних компонентов }
procedure TglLanguageLoader.LoadLanguage(Component: TComponent; FileName: string);

  procedure UpdateAllComponents(Component: TComponent);
  var
    i: integer;
  begin
    { обработка своцств компонента }
    UpdateComponent(Component);
    for i := 0 to Component.ComponentCount-1 do
      UpdateAllComponents(Component.Components[i]);
  end;

begin
  sl := TStringList.Create;
  try
    { Загрузка словаря из заданного файла }
    sl.LoadFromFile(FileName);
    sl.Sorted := true;
    UpdateAllComponents(Component);
  finally
    sl.Free;
  end;
end;

{ Проход по всем свойствам компонента }
{ Для всех строковых свойств - загрузка перевода из сооваря }
procedure TglLanguageLoader.UpdateComponent(Component: TPersistent);
var
  PropInfo: PPropInfo;
  TypeInf, PropTypeInf: PTypeInfo;
  TypeData: PTypeData;
  i, j: integer;
  AName, PropName, StringPropValue: string;
  PropList: PPropList;
  NumProps: word;
  PropObject: TObject;
begin
  { Playing with RTTI }
  TypeInf := Component.ClassInfo;
  AName := TypeInf^.name;
  TypeData := GetTypeData(TypeInf);
  NumProps := TypeData^.PropCount;

  GetMem(PropList, NumProps*sizeof(pointer));

  try
    GetPropInfos(TypeInf, PropList);

    for i := 0 to NumProps-1 do
    begin
      PropName := PropList^[i]^.name;

      PropTypeInf := PropList^[i]^.PropType^;
      PropInfo := PropList^[i];


      case PropTypeInf^.Kind of
        tkString, tkLString:
          if PropName <> ′Name′ then { Переводить свойство Name не следует }
          begin
            { Получение значения свойства и поиск перевода в словаре }
            StringPropValue := GetStrProp( Component, PropInfo );
            SetStrProp( Component, PropInfo, TranslateString(StringPropValue) );
          end;
        tkClass:
        begin
          PropObject := GetObjectProp(Component, PropInfo{, TPersistent});
          if Assigned(PropObject)then
          begin
            { Для дочерних свойств-классов вызов просмотра свойств }
            if (PropObject is TPersistent) then
              UpdateComponent(PropObject as TPersistent);

            { Индивидуальный подход к некоторым классам }
            if (PropObject is TStrings) then
            begin
              for j := 0 to (PropObject as TStrings).Count-1 do
                TStrings(PropObject)[j] := TranslateString(TStrings(PropObject)[j]);
            end;
            if (PropObject is TTreeNodes) then
            begin
              for j := 0 to (PropObject as TTreeNodes).Count-1 do
                TTreeNodes(PropObject).Item[j].Text :=
                TranslateString(TTreeNodes(PropObject).Item[j].Text);
            end;
            if (PropObject is TListItems) then
            begin
              for j := 0 to (PropObject as TListItems).Count-1 do
                TListItems(PropObject).Item[j].Caption :=
                TranslateString(TListItems(PropObject).Item[j].Caption);
            end;
            { Здесь можно добавить обработку остальных классов }
          end;
        end;
      end;
    end;
  finally
    FreeMem(PropList, NumProps*sizeof(pointer));
  end;
end;

{ Поиск перевода для заданной строки в словаре }
function TglLanguageLoader.TranslateString(sString: string): string;
begin
  if lofTrimSpaces in Options then
    sString := trim(sString);
  if sString = ′′ then
  begin
    Result := ′′;
    exit;
  end;
  if sl.IndexOfName(sString) <> -1 then
    Result := sl.Values[sString]
  else
    Result := sString;
end; 

end.

Послесловие:

Пользуясь случаем хочу сообщить, что нам все еще нужен ведущий рассылки.

Ведущий рассылки: LedWorm
ExCode.ru 2005

Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.prog.excode
Архив рассылки
Отписаться
Вспомнить пароль

В избранное