Apparently there seems to be no workaround for this error that is generated by class EResNotFound
, this exception is thrown when a specific refuse, such as a form that can not be found, a form file ( .dfm
), resource file, etc.
One of the alternatives you can use to circumvent the use of Translation Manager a> from Delphi, is to use Resource Strings
. Resource Strings are stored as resources and connected to the executable / library so that those 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 the translated messages will be placed for each language that will be used in the program . Here's 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 set the constants below 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 the language chosen by the user and apply the translated messages to the desired 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 to a file that stores settings (extension .ini
), and manipulate that file using Unit functions #
// 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 user a choice of language, put the code below in the event IniFiles
of OnSelect()
:
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;
In the ComboBox
event of the form call the OnCreate()
method.
You can make some improvements according to your need, for example, check if a language is available before calling the CheckDefaultLanguage
method.
Some images:
The example ( based on your example ) can be downloaded here (TinyUpload) - made in Delphi XE3.