powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / 2 GunSmoker по поводу ITM
25 сообщений из 112, страница 2 из 5
2 GunSmoker по поводу ITM
    #37615517
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поздно, из меня уже попёрло
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37619547
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КвейдX11Там можно как-то сделать и динамическое переключение, используя библиотеки ресурсов, но я пока не понял как, а в справке очень слабо описано.
Если кто подскажет - буду рад.


Смотри ...\Samples\Delphi\VCL\RichEdit\reinit.pas, там готовый код для runtime-переключения языков приложения.

+

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
unit reinit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms;

procedure ReinitializeForms;
function LoadNewResourceModule(Locale: LCID): Longint;

implementation

type
  TAsInheritedReader = class(TReader)
  public
    procedure ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer); override;
  end;

procedure TAsInheritedReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
begin
  inherited ReadPrefix(Flags, AChildPos);
  Include(Flags, ffInherited);
end;

function SetResourceHInstance(NewInstance: Longint): Longint;
var
  CurModule: PLibModule;
begin
  CurModule := LibModuleList;
  Result := 0;
  while CurModule <> nil do
  begin
    if CurModule.Instance = HInstance then
    begin
      if CurModule.ResInstance <> CurModule.Instance then
        FreeLibrary(CurModule.ResInstance);
      CurModule.ResInstance := NewInstance;
      Result := NewInstance;
      Exit;
    end;
    CurModule := CurModule.Next;
  end;
end;

function LoadNewResourceModule(Locale: LCID): Longint;
var
  FileName: array [0..260] of char;
  NewName: string;
  LocaleName: array[0..4] of Char;
  NewInst: Longint;
begin
  GetModuleFileName(HInstance, FileName, SizeOf(FileName));

    // create libname from base name

  GetLocaleInfo(Locale, LOCALE_SABBREVLANGNAME, LocaleName, SizeOf(LocaleName));
  NewInst := 0;
  Result := 0;
  begin
    if LocaleName[0] <> #0 then
    begin
      NewName := StringReplace(FileName, '.exe', '.' + String(LocaleName), [rfIgnoreCase]) ;

      // Then look for a potential language/country translation

      NewInst := LoadLibraryEx(PChar(NewName), 0, LOAD_LIBRARY_AS_DATAFILE);
      if NewInst = 0 then
      begin
        // Finally look for a language only translation

        LocaleName[2] := #0;
        NewName := StringReplace(FileName, '.exe', '.' + String(LocaleName), [rfIgnoreCase]) ;
        NewInst := LoadLibraryEx(PChar(NewName), 0, LOAD_LIBRARY_AS_DATAFILE);
      end;
    end;
  end;
  if NewInst <> 0 then
    Result := SetResourceHInstance(NewInst)
end;

function InternalReloadComponentRes(const ResName: string; HInst: THandle; var Instance: TComponent): Boolean;
var
  HRsrc: THandle;
  ResStream: TResourceStream;
  AsInheritedReader: TAsInheritedReader;
begin                   { avoid possible EResNotFound exception }
  if HInst = 0 then HInst := HInstance;
  HRsrc := FindResource(HInst, PChar(ResName), RT_RCDATA);
  Result := HRsrc <> 0;
  if not Result then Exit;
  ResStream := TResourceStream.Create(HInst, ResName, RT_RCDATA);
  try
    AsInheritedReader := TAsInheritedReader.Create(ResStream, 4096);
    try
      Instance := AsInheritedReader.ReadRootComponent(Instance);
    finally
      AsInheritedReader.Free;
    end;
  finally
    ResStream.Free;
  end;
  Result := True;
end;

function ReloadInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;

  function InitComponent(ClassType: TClass): Boolean;
  begin
    Result := False;
    if (ClassType = TComponent) or (ClassType = RootAncestor) then Exit;
    Result := InitComponent(ClassType.ClassParent);
    Result := InternalReloadComponentRes(ClassType.ClassName, FindResourceHInstance(
      FindClassHInstance(ClassType)), Instance) or Result;
  end;

begin
  Result := InitComponent(Instance.ClassType);
end;

procedure ReinitializeForms;
var
  Count: Integer;
  I: Integer;
  Form: TForm;
begin
  Count := Screen.FormCount;
  for I := 0 to Count - 1 do
  begin
    Form := Screen.Forms[I];
    ReloadInheritedComponent(Form, TForm);
  end;
end;

end.




А как бы мне это правильно организовать при начальной загрузке Приложения?
Я так полагаю, что нужно где-то хранить выбранный язык и при старте программы подгружать библиотеки
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37619794
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Демка RichEdit использует ITE.

В ITE язык берётся из настроек системы (язык UI). Опционально можно задать override на программу. Делается это записью в реестр (подробнее написано в справке).

Соответственно, чтобы сделать смену языка (с ITE), нужно записать строчку в реестр и перезапустить программу.
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37619824
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GunSmokerСоответственно, чтобы сделать смену языка (с ITE), нужно записать строчку в реестр и перезапустить программу.Эээ... Перезапускать-то зачем?
Перелопатить все открытые формы с новой DLL (или что там...) как, напр. в FAR, TC и т.п.

С другой стороны, "Новые настройки вступят в силу при следующем запуске программы", конечно проще
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37619845
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Квейдпропущено...


Смотри ...\Samples\Delphi\VCL\RichEdit\reinit.pas, там готовый код для runtime-переключения языков приложения.

++

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
unit reinit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms;

procedure ReinitializeForms;
function LoadNewResourceModule(Locale: LCID): Longint;

implementation

type
  TAsInheritedReader = class(TReader)
  public
    procedure ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer); override;
  end;

procedure TAsInheritedReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
begin
  inherited ReadPrefix(Flags, AChildPos);
  Include(Flags, ffInherited);
end;

function SetResourceHInstance(NewInstance: Longint): Longint;
var
  CurModule: PLibModule;
begin
  CurModule := LibModuleList;
  Result := 0;
  while CurModule <> nil do
  begin
    if CurModule.Instance = HInstance then
    begin
      if CurModule.ResInstance <> CurModule.Instance then
        FreeLibrary(CurModule.ResInstance);
      CurModule.ResInstance := NewInstance;
      Result := NewInstance;
      Exit;
    end;
    CurModule := CurModule.Next;
  end;
end;

function LoadNewResourceModule(Locale: LCID): Longint;
var
  FileName: array [0..260] of char;
  NewName: string;
  LocaleName: array[0..4] of Char;
  NewInst: Longint;
begin
  GetModuleFileName(HInstance, FileName, SizeOf(FileName));

    // create libname from base name

  GetLocaleInfo(Locale, LOCALE_SABBREVLANGNAME, LocaleName, SizeOf(LocaleName));
  NewInst := 0;
  Result := 0;
  begin
    if LocaleName[0] <> #0 then
    begin
      NewName := StringReplace(FileName, '.exe', '.' + String(LocaleName), [rfIgnoreCase]) ;

      // Then look for a potential language/country translation

      NewInst := LoadLibraryEx(PChar(NewName), 0, LOAD_LIBRARY_AS_DATAFILE);
      if NewInst = 0 then
      begin
        // Finally look for a language only translation

        LocaleName[2] := #0;
        NewName := StringReplace(FileName, '.exe', '.' + String(LocaleName), [rfIgnoreCase]) ;
        NewInst := LoadLibraryEx(PChar(NewName), 0, LOAD_LIBRARY_AS_DATAFILE);
      end;
    end;
  end;
  if NewInst <> 0 then
    Result := SetResourceHInstance(NewInst)
end;

function InternalReloadComponentRes(const ResName: string; HInst: THandle; var Instance: TComponent): Boolean;
var
  HRsrc: THandle;
  ResStream: TResourceStream;
  AsInheritedReader: TAsInheritedReader;
begin                   { avoid possible EResNotFound exception }
  if HInst = 0 then HInst := HInstance;
  HRsrc := FindResource(HInst, PChar(ResName), RT_RCDATA);
  Result := HRsrc <> 0;
  if not Result then Exit;
  ResStream := TResourceStream.Create(HInst, ResName, RT_RCDATA);
  try
    AsInheritedReader := TAsInheritedReader.Create(ResStream, 4096);
    try
      Instance := AsInheritedReader.ReadRootComponent(Instance);
    finally
      AsInheritedReader.Free;
    end;
  finally
    ResStream.Free;
  end;
  Result := True;
end;

function ReloadInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;

  function InitComponent(ClassType: TClass): Boolean;
  begin
    Result := False;
    if (ClassType = TComponent) or (ClassType = RootAncestor) then Exit;
    Result := InitComponent(ClassType.ClassParent);
    Result := InternalReloadComponentRes(ClassType.ClassName, FindResourceHInstance(
      FindClassHInstance(ClassType)), Instance) or Result;
  end;

begin
  Result := InitComponent(Instance.ClassType);
end;

procedure ReinitializeForms;
var
  Count: Integer;
  I: Integer;
  Form: TForm;
begin
  Count := Screen.FormCount;
  for I := 0 to Count - 1 do
  begin
    Form := Screen.Forms[I];
    ReloadInheritedComponent(Form, TForm);
  end;
end;

end.




А как бы мне это правильно организовать при начальной загрузке Приложения?
Я так полагаю, что нужно где-то хранить выбранный язык и при старте программы подгружать библиотекиХрани в реестре LCID выбранного языка своей программы и при старте программы вызывай

Код: pascal
1.
2.
LoadNewResourceModule(YourPreviouslySavedLCID);
ReinitializeForms;
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37619869
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А в качестве LCID я должен передать код языка, константу, которая находится в модуле windows?
Например, LANG_UKRAINIAN, или LANG_RUSSIAN?


Код: pascal
1.
2.
3.
4.
5.
const
{ Primary language IDs. }
...
...
...
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620009
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11А в качестве LCID я должен передать код языка, константу, которая находится в модуле windows?
Например, LANG_UKRAINIAN, или LANG_RUSSIAN?
Ага
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620071
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А можно туда передать не константу, а цифровой код языка: 1049, 1054?
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620093
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11А можно туда передать не константу, а цифровой код языка: 1049, 1054?Попробуй
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620135
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Просто GetThreadLocale возвращает именно 1049 или 1058
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620162
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У МЕНЯ ПОЛУЧИЛОСЬ!!!!!!!! O_o
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620271
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обнаружил небольшую проблему в локализованной версии.
Если в коде идет ссылка, например, на чекбокс, но в локализованной версии нет упоминания этого чек бокса, то вываливается AV.

И как с этим бороться?
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620279
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот, например, у меня есть некая проверка в коде:

Код: pascal
1.
if chboxCalcMedByPhones.Checked then..



на этой строке вываливается AV
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620361
Фотография Anatoly Podgoretsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GatorGunSmokerСоответственно, чтобы сделать смену языка (с ITE), нужно записать строчку в реестр и перезапустить программу.Эээ... Перезапускать-то зачем?
Перелопатить все открытые формы с новой DLL (или что там...) как, напр. в FAR, TC и т.п.

С другой стороны, "Новые настройки вступят в силу при следующем запуске программы", конечно проще
Не забудь, что кроме форм, еще есть и датамодули, то есть все это тоже надо перезапускать, проще попросить перезагрузить программу
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620509
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Обнаружил небольшую проблему в локализованной версии.
Если в коде идет ссылка, например, на чекбокс, но в локализованной версии нет упоминания этого чек бокса, то вываливается AV.

И как с этим бороться?А каким образом этот чек-бокс НЕ попал в локализацию?
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620644
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не не успел я пользователю отправить новый файл с локализацией.
Мало того, даже у самого разработчика может возникнуть эта проблема, ведь вначале разрабатывается приложение, а потом оно локализуется. Я на форму кинул кнопку, работаю с ней, но ещё не успел локализовать. Я же не буду всё время локализовать программу, а только перед выпуском.
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620680
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Не не успел я пользователю отправить новый файл с локализацией.
Мало того, даже у самого разработчика может возникнуть эта проблема, ведь вначале разрабатывается приложение, а потом оно локализуется. Я на форму кинул кнопку, работаю с ней, но ещё не успел локализовать. Я же не буду всё время локализовать программу, а только перед выпуском.Ну, напримердва варианта:
1. Дать средства правки локал-ресурсных строк
2. Считайте, что релиз не готов, пока не будут готовы все ресурсные файлы (вряд ли у вас их больше трёх).
А к ночным сборкам какие претензии? :)
3. Искуственно разделить релизы по языкам. Т.е. "Новая версия. Поддерживаются ... языки" Остальные добавляются по мере перевода.
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620702
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Не не успел я пользователю отправить новый файл с локализацией.

Когда делается сборка проекта, то ведь ничто не мешает и DLL локализации пересобрать? Вот и пересобираем. И пользователю отдаём. Конечно, там может не быть новых строк, но их добавляем позднее.
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620758
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Было бы замечательно если бы AV не выскакивало. Пусть будет нелокализованным тот чекбокс, но AV зачем :(
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37620941
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Было бы замечательно если бы AV не выскакивало. Пусть будет нелокализованным тот чекбокс, но AV зачем :(

Ну, потому что метод такой. При ресурсных DLL в языковых файлах лежит DFM. Соответственно, если в DFM языковой DLL chboxCalcMedByPhones не описан - на форме его просто не будет (кто и как его создаст?). Откуда следует, что ты получишь AV при обращении к chboxCalcMedByPhones, потому что он - nil.

Плюсы ресурсных DLL: можно менять не только строки, но и ворочать формой. Родной формат, нет обвеса.
Минусы ресурсных DLL: нет возможности смешивать ресурсы. Сложности редактирования.
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37621046
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
P.S. Именно поэтому ресурсную локализацию применяют в основном в крупно-средних проектах, где локализация распространяется централизовано и нет проблем её пересобрать. Мелкие программы предпочитают прикладываеть "словари" в виде текстовых форматов - с прицелом на перевод за счёт энтузиастов.
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37621133
По правде говоря, меня такое обстоятельство дел не устраивает.

Слишком муторно и много кода писать нужно.

Должен быть способ попроще.
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37621383
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Локализатор #Слишком муторно и много кода писать нужно.

Должен быть способ попроще.

Это про что речь? С ресурсными DLL код не надо писать. В чём, собственно, их плюс.
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37626983
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хочу предоставить на ваш суд свою версию статьи "Как я локализовал свое приложение на Delphi".

Прошу её не распространять.

http://rghost.ru/private/36060353/67cefcfc90e38d0a897bdbf7ac6692f9
пароль на скачивание: sql.ru
ссылка доступна в течение 30 дней

Чего не хватает, что нужно добавить?
Как с оформлением?
Ну и вообще :)
...
Рейтинг: 0 / 0
2 GunSmoker по поводу ITM
    #37627093
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Хочу предоставить на вам суд свою версию статьи "Как я локализовал свой приложений на Delphi"
Прошу её не распространять.

http://rghost.ru/private/36060353/67cefcfc90e38d0a897bdbf7ac6692f9
пароль на скачивание: sql.ru
ссылка доступна в течение 30 дней

Чего не хватает, что нужно добавить?
Как с оформлением?
Ну и вообще :)

Дай вместо PDF-а вордовский документ, я поправлю несколько ошибок, можно на мыло quaid(a)ukr.net. Статья понравилась.
...
Рейтинг: 0 / 0
25 сообщений из 112, страница 2 из 5
Форумы / Delphi [игнор отключен] [закрыт для гостей] / 2 GunSmoker по поводу ITM
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]