![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Мультиязычность интерфейса. [D5, WinME, NT4, Win2k, WinXP]
d_xaos © (2007-01-02 14:55:00)Появилась необходимость перевести софтину на другие языки. Решил пойти по пути наименьшего сопротивления:
1) Создал lng файл следующего вормата
название_формы - название_компонента - название_Properties - значение
2) при загрузке считываю считываю строки и в строковых переменных Form_name, component_name, Properties_name, Properties_value имею всё, что надо.
3) При помощи FindComponent можно менять всё, но там надо явно указывать:
With TLabel(Form1.FindComponent(component_name)) do begin
caption:=Some_Value;
hint:=Some_Value;
end;
Вопрос в следующем:
Как имея в переменных нужные значения, поменять свойства компонентов на форме?
Дмитрий Белькевич (2007-01-05 04:35:00) [1]p.p.s. почти ровный. Код отдаю за фри, можете пользовать где хотите (если хоть кто-то на это смотрит), насколько знаю, Igor Izotov его отдавал так же. Буду _очень_ признателен за найденные глюки (код релизный, но мало ли) и дополнения.
Выдирает все (или большинство, если что-то найдете, пишите) строковые свойства всех компонент на всех (или на нужных) формах.
Раньше переводил по словарю, но из-за специфических глюков кодировок американской винды переписан в текущий вид. Нет глюка, который (иногда) проявляется при переводах по словарю - каждое свойство переводиться отдельно, зато при изменении свойств нужно (не забывать) переводить повторно. Проблема достаточно просто решается, но не было времени заниматься. Короче, пробуйте, господа!
Дмитрий Белькевич (2007-01-05 04:23:00) [2]Пробуй то, чем сам перевожу. Если будут вопросы, пиши в мыло. Если найдешь глюки - пиши. Лишние компоненты/библиотеки закомменть.
Юзать в основном модуле (dpr):
Internat: TInternationalization;
for i := 0 to Screen.FormCount - 1 do
Internat.Execute(Screen.Forms[i]);
p.s. очень предпросмотра не хватает. Вот пощу код и думаю - будет нормальный или кривой?
//--------------------------------------------------------//
// //
// Revised: Dmitry Belkevich //
// Version: 1.3 //
// Based on TInternationalisation by Igor Izotov //
// //
// Copyright (c) 2004, 2006 Dmitry Belkevich //
// http://www.makhaon.com //
// //
//--------------------------------------------------------//
//--------------------------------------------------------//
// //
// Author: Igor Izotov //
// Company: proTeam Spb. //
// Version: 1.0 //
// //
// Copyright (c) 2002 proTeam Spb. //
// http://www.rugdesign.spb.ru //
// //
//--------------------------------------------------------//
//--------------------------------------------------------//
// Visual component for Internationalization feature //
// in your application. //
// Just drop this component onto your Form, //
// start your application, close application, //
// copy text from messages_XXX.log file into //
// new created file messages_XXX.prop and edit this //
// file by the adding required strings values like this: //
// Zoom In = Óâåëè÷èòü //
// //
// XXX is an extension defines a local language setting //
// on a working computer //
// //
// En empty file messages_XXX.log means you've finished //
// localization process //
//--------------------------------------------------------//
unit Internationalization;
interface
uses
Classes,
JvPageListTreeView,
JclFileUtils,
ActnMan,
ComCtrls,
DBCtrls,
ExtCtrls,
Forms,
SysUtils,
MakStrUtils,
TypInfo,
StdCtrls,
Buttons,
CoolGrid,
Dialogs,
TBXExtItems,
Controls,
Windows;
type
TInternationalization = object
private
FForm: TForm;
Translated: TStringList;
NotTranslated: TStringList;
public
procedure Execute(Form: TForm);
procedure CheckAndSetComponentPropertyString(var s: string; const PropName: string); overload;
procedure CheckAndSetComponentPropertyString(const prop: string; var cm: TObject); overload;
procedure CheckAndSetComponentPropertyStrings(prop: TStrings;const PropName: string);
function GetString(const CompName, Value: string): string;
end;
implementation
uses DBGridEh;
procedure TInternationalization.CheckAndSetComponentPropertyString(var s: string; const PropName: string);
var
TempInt: integer;
strValue: string;
begin
if (s '') and (s '-') and not TryStrToInt(s, TempInt) then
begin
strValue := GetString(PropName, s);
if strValue '' then
s := strValue;
end;
end;
procedure TInternationalization.CheckAndSetComponentPropertyString(const prop: string; var cm: TObject);
var
TempInt: integer;
strValue: string;
begin
if assigned(GetPropInfo(cm, prop)) then
begin
strValue := GetPropValue(cm, prop);
if (strValue '') and (strValue '-') and not TryStrToInt(strValue, TempInt) then
begin
strValue := GetString(FForm.Name + '.' + (Cm as TComponent).Name + '.' + prop, strValue);
if strValue '' then
SetPropValue(cm, prop, strValue);
end;
end;
end;
procedure TInternationalization.CheckAndSetComponentPropertyStrings(prop: TStrings;const PropName: string);
var
i: Integer;
TempInt: integer;
Strings: TStringList;
strValue: string;
begin
Strings := TStringList.Create;
try
Strings.Assign(prop);
for i := 0 to Strings.Count - 1 do
begin
strValue := Strings[i];
if (strValue '') and (strValue '-') and not TryStrToInt(strValue, TempInt) then
begin
strValue := GetString(Format('%s[%d]', [PropName, i]), strValue);
if strValue '' then
prop[i] := strValue;
end;
end;
finally
Strings.Free;
end;
end;
Дмитрий Белькевич (2007-01-05 04:23:00) [3]
procedure TInternationalization.Execute;
var
prop_file, prop_file_log: string;
i, j, k: Integer;
cm, cm2: TObject;
strValue: string;
s: string;
begin
prop_file := ChangeFileExt(Application.ExeName, '.itf');
prop_file_log := PathGetTempPath + ExtractFileName(ChangeFileExt(Application.ExeName, '.itf'));
if not FileExists(prop_file) then
Exit;
Translated := TStringList.Create;
NotTranslated := TStringList.Create;
Translated.LoadFromFile(prop_file);
if FileExists(prop_file_log) then
NotTranslated.LoadFromFile(prop_file_log);
FForm := Form;
Form.Caption := GetString(FForm.Name + '.Caption', Form.Caption);
for i := 0 to Form.ComponentCount - 1 do
begin
try
cm := Form.Components[i];
CheckAndSetComponentPropertyString('Caption', cm);
CheckAndSetComponentPropertyString('Hint', cm);
CheckAndSetComponentPropertyString('Title', cm);
CheckAndSetComponentPropertyString('Text', cm);
if cm is TLabeledEdit then
begin
strValue := (cm as TLabeledEdit).EditLabel.Caption;
if (strValue <> '') and (strValue <> '-') then
begin
strValue := GetString(FForm.Name + '.' + (Cm as TComponent).Name + '.Caption', strValue);
if strValue <> '' then
(cm as TLabeledEdit).EditLabel.Caption := strValue
end;
end;
if cm is TActionManager then
with TActionManager(cm) do
for j := 0 to ActionBars.Count - 1 do
with ActionBars[j] do
for k := 0 to Items.Count - 1 do
begin
cm2 := Items[k];
end;
if cm is TOpenDialog then
CheckAndSetComponentPropertyString('Filter', cm);
if cm is TSaveDialog then
CheckAndSetComponentPropertyString('Filter', cm);
if cm is TLabeledEdit then
begin
cm2 := TLabeledEdit(cm).EditLabel;
CheckAndSetComponentPropertyString('Caption', cm2);
end;
if cm is TTreeView then
with TTreeView(cm) do
for j := 0 to Items.Count - 1 do
begin
cm2 := Items[j];
CheckAndSetComponentPropertyString('Text', cm2);
end;
if cm is TListView then
with TListView(cm) do
for j := 0 to Columns.Count - 1 do
begin
s := Columns[j].Caption;
CheckAndSetComponentPropertyString(s, FForm.Name + '.' + (Cm as TComponent).Name + '.Columns[' + IntToStr(j) +
'].Caption');
Columns[j].Caption := s;
end;
if cm is TCoolGrid then
with TCoolGrid(cm) do
for j := 0 to Columns.Count - 1 do
begin
s := Columns[j].Title.Caption;
CheckAndSetComponentPropertyString(s, FForm.Name + '.' + (Cm as TComponent).Name + '.Columns[' + IntToStr(j) +
'].Caption');
Columns[j].Title.Caption := s;
end;
if cm is TJvSettingsTreeView then
with TJvSettingsTreeView(cm) do
for j := 0 to Items.Count - 1 do
begin
s := Items[j].Text;
CheckAndSetComponentPropertyString(s, FForm.Name + '.' + (Cm as TComponent).Name + '.Items[' + IntToStr(j) +
'].Caption');
Items[j].Text := s;
end;
if cm is TTBXComboBoxItem then
begin
CheckAndSetComponentPropertyStrings((cm as TTBXComboBoxItem).Strings, FForm.Name + '.' + (Cm as TComponent).Name +
'.Strings');
end;
if cm is TComboBox then
begin
CheckAndSetComponentPropertyStrings((cm as TComboBox).Items, FForm.Name + '.' + (Cm as TComponent).Name +
'.Items');
end;
if cm is TRadioGroup then
begin
CheckAndSetComponentPropertyStrings((cm as TRadioGroup).Items, FForm.Name + '.' + (Cm as TComponent).Name +
'.Items');
end;
if cm is TTabControl then
begin
CheckAndSetComponentPropertyStrings((cm as TTabControl).Tabs, FForm.Name + '.' + (Cm as TComponent).Name +
'.Tabs');
end;
if cm is TDBNavigator then
begin
CheckAndSetComponentPropertyStrings((cm as TDBNavigator).Hints, FForm.Name + '.' + (Cm as TComponent).Name +
'.Hints');
end;
if cm is TDBGridEh then
begin
for j := 0 to (cm as TDBGridEh).Columns.Count - 1 do
begin
strValue := (cm as TDBGridEh).Columns[j].Title.Caption;
if (strValue <> '') and (strValue <> '-') then
begin
strValue := GetString(FForm.Name + '.' + (Cm as TComponent).Name + '.Columns[' + IntToStr(j) + '].Caption',
strValue);
if strValue <> '' then
(cm as TDBGridEh).Columns[j].Title.Caption := strValue;
end;
strValue := (cm as TDBGridEh).Columns[j].Title.Hint;
if (strValue <> '') and (strValue <> '-') then
begin
strValue := GetString(FForm.Name + '.' + (Cm as TComponent).Name + '.Columns[' + IntToStr(j) + '].Hint',
strValue);
if strValue <> '' then
(cm as TDBGridEh).Columns[j].Title.Hint := strValue;
end;
end;
end;
except
end;
end;
Translated.Free;
if NotTranslated.Count > 0 then
NotTranslated.SaveToFile(prop_file_log);
NotTranslated.Free;
end;
function TInternationalization.GetString(const CompName, Value: string): string;
var
i: Integer;
function IndexOf(const Value: string): integer;
var
i: integer;
begin
Result := -1;
for i := 0 to Translated.Count - 1 do
if Pos(Value, Translated[i]) <> 0 then
begin
Result := i;
Break;
end;
end;
begin
i := IndexOf(CompName);
if i = -1 then
begin
NotTranslated.Add(CompName + '=' + Value);
Result := Value;
end
else
begin
Result := Copy(Translated[i], Length(CompName) + 2, MaxInt);
Translated.Delete(i);
end;
end;
end.
azl (2007-01-02 20:28:00) [4]Palladin, это ты к чему?
Palladin (2007-01-02 20:17:00) [5]
> [10] azl ©
с ума сойти, а что ж с простым циклом то справиться не можешь...
azl (2007-01-02 20:05:00) [6]Я делал для своей программы мультиязычный интерфейс. Делал все при помощи ini-файлов.
Создавал ini-файлы с нужным мне языком. Считывал, какие есть языковые файлы для создания списка доступных языков. Потом в программе из списка выбирал нужный мне язык и просто считывал из него и все.
Anatoly Podgoretsky (2007-01-02 18:07:00) [7]> d_xaos (02.01.2007 18:04:08) [8]
Изучай Дельфи в части resourcestring
d_xaos (2007-01-02 18:04:00) [8]Да, а как Translation Manager справляется с поиском в коде всяческих MessageBox и т.д.
d_xaos (2007-01-02 17:55:00) [9]Так первод на мультиязычность - это 3% от общей работы :(
Anatoly Podgoretsky (2007-01-02 17:46:00) [10]> d_xaos (02.01.2007 17:33:05) [5]
Translation Manager и никаких 50 вечеров не потребуется.
d_xaos (2007-01-02 17:33:00) [11]Насчёт времени - это точно. Надо за 50 вечеров перелопатить то, над чем в своё время сидел пол года :(
А есть ли толковые/вменяемые бесплатные компоненты для русификации??
Eraser (2007-01-02 16:39:00) [12]> [3] Джо © (02.01.07 16:26)
согласен,
но очень просто не хочется изобретать велосипед ) ни времени, ни желания нету ))
Джо (2007-01-02 16:26:00) [13]> Вопрос в следующем:
> Как имея в переменных нужные значения, поменять свойства
> компонентов на форме?
Смотри TypInfo.pas.
> [2] Eraser © (02.01.07 15:17)
Лучший компонент — свой собственный! :)
Eraser (2007-01-02 15:17:00) [14]> [1] Anatoly Podgoretsky © (02.01.07 15:04)
чаще всего это не выход. большинство известных мне мультиязычных продуктов используют lng файлы. по ряду причин для небольших шароварных проектов такой вариант на много лучше, чем встроенное средство.
кстати к слову! :) вот тоже планирую реализовать поддержку нескольких языков в проекте, посоветуйте пожалуйста хороший компонент, понимаю, что на torry.net много всего есть, но хочется именно проверенное решение.
Anatoly Podgoretsky (2007-01-02 15:04:00) [15]Это далеко не наименьшее сопротивление.
Хочешь наименьшего сопротивления, то используй встроеный Translation Manager