Компонент для локализации
От: glitch Россия  
Дата: 18.10.03 13:58
Оценка:
Подскажите, какой самый удобный компонент для локализации приложения?
Пробовал LanguageLoader из Globus Lib, но там неудобная структура файла словаря: Строка на языке 1=Строка на языке 2,
т.е. придется делать файлы словаря как RusToEng.lng, EngToRus.lng, RusToDe.lng и т.д. Или нужно было выставлять исходное значение свойства Caption, этим иожно было решить проблему, например:

for(int i=0;i<Form1->ComponentsCount; i++)
{
if(<Компонент имеет свойство Caption, но как это сделать?>)
Form1->Components[i]->Caption=Form1->Components[i]->Name; // <<<----- вот если бы так можно было
}

но так делать нельзя. замаялся уже. народ, помогите.
С уважением,
Александр
Re: Компонент для локализации
От: akasoft Россия  
Дата: 18.10.03 19:15
Оценка:
Здравствуйте, glitch, Вы писали:

G>Подскажите, какой самый удобный компонент для локализации приложения?


По моему, самый удобный — свой собственный. Есть вариант на основе ini-файлов Windows, есть на основе xml. Всё зависит от желания и возможностей.


G>for(int i=0;i<Form1->ComponentsCount; i++)
G>{
G>if(<Компонент имеет свойство Caption, но как это сделать?>)
G>Form1->Components[i]->Caption=Form1->Components[i]->Name; // <<<----- вот если бы так можно было
G>}


На Дельфи

type
    TCrackControl = class (TControl)
    published
        property Caption;
    end;
    
var
    i: Integer;
    C: TControl;
     
begin     
    for i := 0 to Form1.ComponentCount - 1 do
        begin
            C := Form1.Components[i];
            if (C is TLabel) or (C is TForm) then
              TCrackControl(C).Caption := 'Text';
        end;


Есть две основные идеи: настраивать поля для каждого типа контролов отдельно, выделяя TLabel, TButton, etc., либо же определить своего потомка TControl, в котором следует изменить область видимости нужных для модификации свойств.
... << RSDN@Home 1.1 beta 2 >>
Re[2]: Компонент для локализации
От: glitch Россия  
Дата: 18.10.03 20:36
Оценка: :)
Вот, попробовал портировать код под CBuilder (я на нем пишу)
class TCrackControl : public TControl
{
__published:
                __property Caption;
};

int i;
TComponent *Comp=new TComponent(this);
for(i;i<Form1->ComponentCount;i++)
        {
        Comp=Form1->Components[i];
        if(AnsiString(Comp->ClassName())=="TLabel")
                {
                TCrackControl(Comp).Caption="text"; // строка на которую сыпятся все шишки
                }
        }

После компиляции выдает ошибку: Compiler could not generate default constructor for class 'TCrackControl'
И еще одну: VCL Classes must be constructed using operator 'new'

Попробовал заменить TCrackControl(Comp).Caption=="text"; на TControl(Comp).Caption=="text";

Ошибка: TControl::Caption is not accessible

Еще одна попытка, меняю сам класс:

class TCrackControl : public TControl
{
__published:
                __property Caption;
public: __fastcall TCrackControl (TComponent *Comp)
};


Компилируется, но выдает ошибку Linker-а:

Unresolved external 'TCrackControl::' referenced from D:\BORLAND\CBUILDER6\PROJECTS\UNIT1.OBJ
Unresolved external '__fastcall TCrackControl::TCrackControl(Classes::TComponent *)' referenced from
D:BORLAND\CBUILDER6\PROJECTS\UNIT1.OBJ

Где тут ошибка?
С уважением,
Александр
Re: Компонент для локализации
От: Arioch  
Дата: 19.10.03 17:51
Оценка:
The stars so gaily glistened... (Sat, 18 Oct 2003 13:58:31 GMT @623)
...while the fading voice of glitch whispered through the darkness:

g> Подскажите, какой самый удобный компонент для локализации приложения?


Есть XML-based в JVCL — хронически недоделанный.
Есть GNU GetText портированный на Delphi на SourceForge — не поддерживает
смену размеров кнопки, если надпись стала больше и прочее.
Есть нечто Глобусо-подобное в VG Lib 1 (www.vglib.com)

Наконец есть встроенная в Delphi система, но она не дает менять язык после
запуска программы.

А вообще — www.torry.ru — там их мнооого. И раз так много, значит
единственной и удобной нет.
--
If i had ears, i'd heard none: WinAMP de-instaled.
http://Arioch.nm.ru/FL/Fidolook_SL.png Mail: the_Arioch<at>nm<dot>ru
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re[2]: Компонент для локализации
От: Anatoly Podgoretsky Эстония http://www.podgoretsky.com
Дата: 19.10.03 18:49
Оценка:
Наконец есть встроенная в Delphi система, но она не дает менять язык после
запуска программы.

Позволяет и с Дельфи поставляется пример как это делать. Очень удобная и
гибкая система.

--
Anatoly Podgoretsky
http://podgoretsky.com
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re[3]: Компонент для локализации
От: Shadowspan Россия  
Дата: 20.10.03 08:24
Оценка:
Здравствуйте, glitch, Вы писали:

G>Вот, попробовал портировать код под CBuilder (я на нем пишу)

G>
G>class TCrackControl : public TControl
G>{
G>__published:
G>                __property Caption;
G>};

G>int i;
G>TComponent *Comp=new TComponent(this);
G>for(i;i<Form1->ComponentCount;i++)
G>        {
G>        Comp=Form1->Components[i];
G>        if(AnsiString(Comp->ClassName())=="TLabel")
G>                {
G>                TCrackControl(Comp).Caption="text"; // строка на которую сыпятся все шишки
G>                }
G>        }
G>


В Delphi конструкция TCrackControl(...) — не конструктор, а преобразование типа. Так что:
((TCrackControl) Comp).Caption = "text"

И будет тебе счастье.
... << RSDN@Home 1.1 beta 2 >>
Re: Компонент для локализации
От: Dimonka Верблюд  
Дата: 20.10.03 08:56
Оценка:
Здравствуйте, glitch, Вы писали:

G>Подскажите, какой самый удобный компонент для локализации приложения?



Мне тоже придётся в ближайшем будущем столкнуться с такой задачей..
Мне видятся два варианта:
купить Multilizer: http://www.multilizer.com/
или обновить Delphi s Pro на Enterprise

Возникает вопрос: Пользовался кто-нибудь Мультилайзером и пользовался ли кто-нибудь встроенными в Delphi Enterprise средствами? Достаточно ли встроенных в Delphi средств? Можно ли разделить работу переводчика и программиста, как это сделано в Мультилайзере?
Re[4]: Компонент для локализации
От: glitch Россия  
Дата: 20.10.03 20:35
Оценка:
S>В Delphi конструкция TCrackControl(...) — не конструктор, а преобразование типа. Так что:
S>
S>((TCrackControl) Comp).Caption = "text"
S>

S>И будет тебе счастье.

Благодарю, всё теперь работает на ура
С уважением,
Александр
Re[2]: Компонент для локализации
От: glitch Россия  
Дата: 20.10.03 20:37
Оценка:
Здравствуйте, akasoft, Вы писали:

A>По моему, самый удобный — свой собственный. Есть вариант на основе ini-файлов Windows, есть на основе xml. Всё зависит от желания и возможностей.



A>
G>>for(int i=0;i<Form1->ComponentsCount; i++)
G>>{
G>>if(<Компонент имеет свойство Caption, но как это сделать?>)
G>>Form1->Components[i]->Caption=Form1->Components[i]->Name; // <<<----- вот если бы так можно было
G>>}
A>


A>На Дельфи


A>
A>type
A>    TCrackControl = class (TControl)
A>    published
A>        property Caption;
A>    end;
    
A>var
A>    i: Integer;
A>    C: TControl;
     
A>begin     
A>    for i := 0 to Form1.ComponentCount - 1 do
A>        begin
A>            C := Form1.Components[i];
A>            if (C is TLabel) or (C is TForm) then
A>              TCrackControl(C).Caption := 'Text';
A>        end;
A>


A>Есть две основные идеи: настраивать поля для каждого типа контролов отдельно, выделяя TLabel, TButton, etc., либо же определить своего потомка TControl, в котором следует изменить область видимости нужных для модификации свойств.


Благодарю, Вы очень мне помогли
С уважением,
Александр
Re: Компонент для локализации
От: Wizard_Ex  
Дата: 21.10.03 13:19
Оценка: 2 (1)
Здравствуйте, glitch, Вы писали:

G>Подскажите, какой самый удобный компонент для локализации приложения?

G>Пробовал LanguageLoader из Globus Lib, но там неудобная структура файла словаря: Строка на языке 1=Строка на языке 2,
G>т.е. придется делать файлы словаря как RusToEng.lng, EngToRus.lng, RusToDe.lng и т.д. Или нужно было выставлять исходное значение свойства Caption, этим иожно было решить проблему, например:

G>for(int i=0;i<Form1->ComponentsCount; i++)

G>{
G>if(<Компонент имеет свойство Caption, но как это сделать?>)
G>Form1->Components[i]->Caption=Form1->Components[i]->Name; // <<<----- вот если бы так можно было
G>}

G>но так делать нельзя. замаялся уже. народ, помогите.


Попробуйте использовать RTTI + маленько фантазии

приведу пример — готовый рабочий юнит, автоматизированный перевод формы без всяких заморочек

unit translate;

interface

uses SysUtils, Classes, Forms, IniFiles, ActnList;


function TranslateProp(Dict : TIniFile; ASection, AIdent1, AIdent2 : string;
                                                var AValue : string): boolean;

procedure TranslateFormControls(AForm : TForm; ADictFileName : string;
                              isTranslateCaption : boolean = True);


implementation

uses TypInfo, Msg;

//Возвращаем строку где ## заменяются назад как и було ентерами(переводами строк)
function GetTextWithReturn(AText: String): string;
begin
  Result:=StringReplace(AText, '##', #13+#10,[rfReplaceAll]+[rfIgnoreCase]);
end;

//если в строке есть перевод каретки то его заменяем на ##
// для чего - в ини-файл без этого никак
function SetTextWithReturn(AText: String): string;
begin
  Result:=StringReplace(AText, #13+#10, '##',[rfReplaceAll]+[rfIgnoreCase]);
end;



function TranslateProp(Dict : TIniFile; ASection, AIdent1, AIdent2 : string;
                                                var AValue : string): boolean;
begin
  Result:=False;
  try
    if AIdent1='' then Exit;
    AValue:=Dict.ReadString(ASection, AIdent1+'.'+AIdent2, '');
    if AValue='' then Dict.WriteString(ASection, AIdent1+'.'+AIdent2, '')
      else Result:=True;
  except
  end;
end;


procedure TranslateFormControls(AForm : TForm; ADictFileName : string;
                              isTranslateCaption : boolean = True);
var Dict : TIniFile;
    I : Integer;
    Obj : TComponent;
    PropInfo1 : PPropInfo;
    PropInfo2 : PPropInfo;
    AValue : string;
begin
  try
    Dict:=TIniFile.Create(ExtractFilePath(ParamStr(0))+ADictFileName);

    if not FileExists(ExtractFilePath(ParamStr(0))+ADictFileName) then Exit;

{Если нужно переводить заголовок формы то}
    if isTranslateCaption and TranslateProp(Dict, AForm.Name ,'Form','Caption', AValue) then
          AForm.Caption:=AValue;

    { Переводим заголовки компонентов формы}
    for I:=0 to AForm.ComponentCount-1 do
    begin
      Obj:=AForm.Components[i];
      PropInfo1:=GetPropInfo(Obj.ClassInfo, 'Action');
      if (PropInfo1=nil) or
        ((PropInfo1<>nil) and (PropInfo1.PropType^.Kind = tkClass)
          and (GetObjectProp(Obj, 'Action', TAction)=nil)) then
      begin
        PropInfo2:=GetPropInfo(Obj.ClassInfo, 'Caption');
        if PropInfo2<>nil then
        begin
          if (PropInfo2^.PropType^.Kind=tkLString) and ((GetStrProp(Obj, 'Caption')<>'')
          and (GetStrProp(Obj, 'Caption')<>'-')) then
           if TranslateProp(Dict, AForm.Name ,Obj.Name, 'Caption', AValue) then
             SetStrProp(Obj, PropInfo2, AValue);
        end;

        PropInfo2:=GetPropInfo(Obj.ClassInfo, 'Hint');
        if PropInfo2<>nil then
        begin
          if (PropInfo2^.PropType^.Kind=tkLString) and (GetStrProp(Obj, 'Hint')<>'')then
           if TranslateProp(Dict, AForm.Name ,Obj.Name,'Hint', AValue) then
             SetStrProp(Obj, PropInfo2, GetTextWithReturn(AValue));
        end;
      end;

      PropInfo2:=GetPropInfo(Obj.ClassInfo, 'Title');
      if PropInfo2<>nil then
      begin
        if (PropInfo2^.PropType^.Kind=tkLString) and (GetStrProp(Obj, 'Title')<>'')then
         if TranslateProp(Dict, AForm.Name ,Obj.Name,'Title', AValue) then
           SetStrProp(Obj, PropInfo2, AValue);
      end;

      PropInfo2:=GetPropInfo(Obj.ClassInfo, 'Filter');
      if PropInfo2<>nil then
      begin
        if (PropInfo2^.PropType^.Kind=tkLString) and (GetStrProp(Obj, 'Filter')<>'')then
         if TranslateProp(Dict, AForm.Name ,Obj.Name,'Filter', AValue) then
           SetStrProp(Obj, PropInfo2, AValue);
      end;
    end;


    Dict.Free;
  except
//    ShowMessage('Language file is not loaded!');
  end;
end;


Для перевода формы в OnCreate вставьте
TranslateFormControls(Self,LanguageFileName);

//procedure TranslateFormControls(AForm : TForm; ADictFileName : string;
// isTranslateCaption : boolean = True);
где
LanguageFileName — имя файла с переводом, должен находится в том же каталоге что и EXE
параметр isTranslateCaption нужен для того чтобы заголовок формы не переводить (иногда нужно)
Файл перевода — это обычный ини-файл, имя и расширение — по вашему вкусу
откомпилите и запустите программу,для того чтобы в с файлом перевода что-то произошло нужно открыть ту форму в которой есть вызов TranslateFormControls (если это главная форма, то все естественно произойдет при запуске)
потом откройте файл с названием LanguageFileName текстовым редактором.
откройте и увидите: о чудо, перед вами заготовка для перевода
а смысл процедуры такой, она проверяет если у контрола есть свойство Caption то она считывает одноименный параметр из файла перевода, если в такого параметра в файле перевода нет, то она его создаст с пустым значением,
и так с некоторыми другими свойствами
потом открываете текстовым редактором и вперед, даешь перевод,
исключение здесь составляет только следующее:
процедура не переводит объекты с Caption:='-', то есть сепараторы в меню // зачем их переводить
и если у объекта есть не пустое свойство Action, // она все равно Actionы все переведет, нет смысла переводит control который Caption и некоторые другие свойства получает от Action


Пользуйте однако!
Примечание: Юнит приведен маленько в подрезанном виде //убраны специфичные функции, абсолютно здесь не нужные.
если что и не работает подправьте, а то я мог чего-нибудь вырезать лишнего

на http://www.galera.narod.ru программа CDBase использует этот юнит
юнит написан недавно как раз для целей перевода, но несколько не удобен в плане
если называть объекты по своему, то переводчик не разберет чего и где
если называть понятно для переводчика, то программисту неудобно
(в CDBase как раз второй случай, сильно запущенный)
поэтому юнит хочется переделать, есть несколько задумок,
если кто хочет присоединиться, буду рад обменяться дельными мысля'ми.
пишите galera@narod.ru
Re[2]: Компонент для локализации
От: Wizard_Ex  
Дата: 21.10.03 13:23
Оценка:
Забыл уточнить

функция TranslateProp используется только юнитом
translate
в секцию interface попала случайно
Re[3]: Компонент для локализации
От: Wizard_Ex  
Дата: 21.10.03 13:37
Оценка:

И прошу
uses TypInfo, Msg;
исправить на

uses TypInfo;

Вроде все
Re[2]: Компонент для локализации
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 21.10.03 16:05
Оценка: 2 (1)
Здравствуйте, Dimonka, Вы писали:

D>Достаточно ли встроенных в Delphi средств?

Да.

D>Можно ли разделить работу переводчика и программиста, как это сделано в Мультилайзере?

Да. Внешнее приложение etmXX.exe. Предварительный просмотр форм (если нужно, например, расщирить/сузить размер компонетов, ...). Можно менять не только строки, но и, например, Font.CharecterSet.
Re[3]: Компонент для локализации
От: Dimonka Верблюд  
Дата: 28.11.03 11:32
Оценка:
Здравствуйте, Mystic, Вы писали:

D>>Можно ли разделить работу переводчика и программиста, как это сделано в Мультилайзере?

M>Да. Внешнее приложение etmXX.exe. Предварительный просмотр форм (если нужно, например, расщирить/сузить размер компонетов, ...). Можно менять не только строки, но и, например, Font.CharecterSet.

Ещё один вопрос — с какой версии Дельпхи все эти чудеса доступны?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.