Apparently there seems to be no solution to this error that is generated by the class EResNotFound
, this exception is cast when a specific decline, such as a form that cannot be found, a form file(.dfm
), resource archive, etc.
One of the alternatives you can use to circumvent the use of Translation Manager of Delphi, is to use Resource Strings
. Resource Strings are stored as resources and linked to the executable/library so that these resources can be modified without recompiling the program.
To make this work in your multi-language program, you can create a new Unit (go to File
→ New
→ Unit
) in this unit will be placed the translated messages for each language you use in the program. See an example:
unit untTraducoes;
interface
resourcestring
// Mensagens em Inglês
EN_FORM_CAPTION = 'My Program Example';
EN_BTN_INFO_CAPTION = 'Information';
EN_BTN_CLOSE_CAPTION = 'Close';
EN_MEMO_TEXT = 'Some text here';
// Mensagens em Português
PT_FORM_CAPTION = 'Meu Programa Exemplo';
PT_BTN_INFO_CAPTION = 'Informação';
PT_BTN_CLOSE_CAPTION = 'Fechar';
PT_MEMO_TEXT = 'Algum texto aqui';
implementation
end.
First define the following constants as global.
Const
LANG_PT = 'PT'; // Português
LANG_EN = 'EN'; // Inglês
LANGUAGE_CONFIG_NAME = 'appconfig.ini'; // Arquivo onde vai ser guardado o idioma escolhido
LANGUAGE_DEFAULT = 'PT'; // Idioma padrão do programa
Now you can create a method that will check which language the user chooses and apply the translated messages to the desirable components.
procedure ApplyLanguage(Lang: string);
begin
If Length(Lang) = 0 then Exit; // Verifica o comprimento da string
If Lang = LANG_PT then begin // Se for o idioma escolhido, então faça
self.Caption := PT_FORM_CAPTION;
self.BtnInfo.Caption := PT_BTN_INFO_CAPTION;
self.BtnClose.Caption := PT_BTN_CLOSE_CAPTION;
Self.Memo1.Text := PT_MEMO_TEXT;
end else if Lang = LANG_EN then begin
self.Caption := EN_FORM_CAPTION;
self.BtnInfo.Caption := EN_BTN_INFO_CAPTION;
self.BtnClose.Caption := EN_BTN_CLOSE_CAPTION;
Self.Memo1.Lines.Text := EN_MEMO_TEXT;
end;
Application.ProcessMessages;
end;
If you need to save the language chosen by the user, you can save it in a file that saves settings( .ini
), and manipulate this file using Unit functions IniFiles
. See the method below:
// Lembre-se de colocar a unit IniFiles em Uses
procedure ChangeLanguage(Lang: string);
Var
Ini: TIniFile;
begin
if Length(Lang) = 0 then exit;
Try
Ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + LANGUAGE_CONFIG_NAME);
Ini.WriteString('Opcoes', 'Lang', Lang);
ApplyLanguage(Lang);
Finally
Ini.Free;
End;
end;
Now to give the possibility of language choice to the user, put the code below in the event OnSelect()
of ComboBox
:
Var
Lang: string;
begin
Case cbIdioma.ItemIndex Of
0: Lang := LANG_PT; // Português
1: Lang := LANG_EN; // Inglês
else Lang := LANG_PT;
End;
ChangeLanguage(Lang);
Finally we will create the method responsible for verifying which language will be used when initializing the program.
// Lembre-se de colocar a unit IniFiles em Uses
procedure CheckDefaultLanguage;
Var
Ini: TIniFile;
LangOption: string;
begin
Try
// Cria o .ini no Diretório do executável
Ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + LANGUAGE_CONFIG_NAME);
if Ini.SectionExists('Opcoes') = False then
// Se o arquivo ou seção não existir executa a linha abaixo e define o idioma padrão no arquivo
Ini.WriteString('Opcoes', 'Lang', LANGUAGE_DEFAULT);
// Lê o idioma definido no arquivo se não conseguir, devolve o idioma padrão
LangOption := Ini.ReadString('Opcoes', 'Lang', LANGUAGE_DEFAULT);
ApplyLanguage(LangOption); // Aplica o idioma escolhido
Finally
Ini.Free; // Liberamos a instância
End;
end;
At the event OnCreate()
form call the method CheckDefaultLanguage
.
You can make some improvements according to your need, an example, check if a language is available before calling the method ApplyLanguage
.
Some images:
The example(based on your example) can be downloaded here(Tinyupload) - made in Delphi XE3.
I put together a very simple example demonstrating the error. https://mega.co.nz/#! qNFRyLAQ! Ygjfjgghabhjw7rvb_1mgqflgsvnggesgubxngzj9ws
– Alex Schmitt
@Qmechanic73 It seems to me that the problem here is that the file that defines the form, Tfrxpreviewform.RES, was not included in the compilation because its inclusion directive, which usually stands just before the type declarations in the file . PAS (in this case, Tfrxpreviewform.PAS) was not processed. You have to find out why this directive has not been processed - maybe it’s not even there or replaced by something else during a design change.
– Caffé
This error only happens when the language is changed via case cbIdioma.Itemindex of 0: lang := LANG_PORTUGUESE; 1: lang := LANG_SPANISH; end; if Loadnewresourcemodule(lang) <> 0 then Reinitializeforms; OU when language is set in Project->Language->Set Active
– Alex Schmitt
@Qmechanic73 For now I stopped the translation phase, I will refine the software when everything is right, I will create a new project for each language, I believe Embarcadeiro can fix it one day.
– Alex Schmitt
All right, then, I’ll stand by. Thank you.
– Alex Schmitt