Report display error (Fastreport) in Multi-language software

Asked

Viewed 1,442 times

4

I have the following error in displaying a report made in Fastreport.

Erro Relatório FastReport

This error started to occur after doing the Internationalization of my software using the native features of Delphi XE7 (Project->Languages->Add), when the software runs in native language the report is presented normally, but when any additional language is chosen, the software will display the error message as per the image.

Code to display the report:

frRelatorio.Clear;
frRelatorio.LoadFromFile(IncludeTrailingPathDelimiter(GetCurrentDir) + 'frRelatorio.fr3');
frRelatorio.PrepareReport;
frRelatorio.ShowReport();

Code that changes the language: (Required to Unit reinit the ship).

case cbIdioma.ItemIndex of
  0:
    lang := LANG_PORTUGUESE;
  1:
    lang := LANG_SPANISH;
end;
if LoadNewResourceModule(lang) <> 0 then
  ReinitializeForms;

I hope that this information will be sufficient, if necessary I can set an example with the error, if anyone can help me, already thank you.

ADD Link to download example generating error: https://mega.co.nz/#! qNFRyLAQ! Ygjfjgghabhjw7rvb_1mgqflgsvnggesgubxngzj9ws

  • I put together a very simple example demonstrating the error. https://mega.co.nz/#! qNFRyLAQ! Ygjfjgghabhjw7rvb_1mgqflgsvnggesgubxngzj9ws

  • 1

    @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.

  • 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

  • @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.

  • All right, then, I’ll stand by. Thank you.

1 answer

2

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 FileNewUnit) 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:

inserir a descrição da imagem aqui inserir a descrição da imagem aqui

The example(based on your example) can be downloaded here(Tinyupload) - made in Delphi XE3.

  • 1

    Thanks for your help, I hope Embarcadeiro improves this multi-language native resource. Hug.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.