Database applications

Preventing unwanted translations

When you create a database application, there will be a lot of component properties that you don't want to be translated when using Translatecomponent(). Typically, the field names, table names and even database names of a database have meaningful translations, and the translation file from the translator may include translations for field names. Also, SQL statements should not be translated. They will get extracted, but if the translator modifies them, it would most likely break your program if this translation would be applied.

Therefore, it is very important, that you consult the appendix called How to handle specific classes> to see what ignores you should add to your application. Make sure that these ignores are executed before the first call to TranslateComponent(). The list in that appendix may not be complete - especially not if you use database components that are not mentioned. Therefore you must have a look at your components and make sure, that all properties, that should not be translated, have a corresponding TP_GlobalIgnoreClassProperty() call.

DisplayLabel property explained

Delphi is very good for creating a single-language database application, fast, if the application only needs one language. A typical single-language application uses field names that are easily understood, like "Name", "Address" etc. Let's assume that you use a query component with an SQL statement like this:

select * from customer order by Name

In this case, the name of the Name field of the customer table will propagate through all components, will become the column heading of a TDBGrid etc. Your grid column for names will read "Name". This is desired in an English language application, but absolutely not in all other languages.

The solution is to modify the .DisplayLabel property of the TField components, that your dataset possesses. Every TDataset descendant has a .Fields[] property that refers to the fields in the dataset, and all these field components are descendants of TField, which has the TField.DisplayLabel property.

Delphi provides two ways to modify this DisplayLabel property: At runtime and at design time, which leads to two different ways of handling the localization of it.

Setting displaylabel at runtime

The runtime assignment solution is to assign a displaylabel at runtime like this:

procedure TForm1.Query1AfterOpen(DataSet: TDataSet);
begin
  Dataset.FieldByName('Name').DisplayLabel:=_('Name');
end;

This way, the field names are always the same in the database and the entire application, but the user will see a localized name. This works for all dataset type components, including table components, TClientDataset etc.

Display label at design time

Creating design-time DisplayLabel properties goes like this:

By doing this, the field names will be present in the DFM files, and will therefore be extracted for the translator to be translated. Now, TranslateComponent() will translate the TField.DisplayLabel values:

procedure TForm1.FormCreate(Sender: TObject);
begin
  TranslateComponent (self);
  Query.Open;
end;

Multiple field name translations

Sometimes it is very handy to have field names translated to something else than what you put into the .DisplayLabel property. For instance, you may want to have a short version for exported ASCII files, another version for exporting XML files, one version for reports, and again another version for the .DisplayLabel property.

This is easily done by using several po files (which is the same as multiple text domains). The part of your program that writes a column header to an ascii file might look like this:

write (mytextfile,dgettext('fieldnames',myfield.FieldName));

This will find the field name in the fieldnames.mo file and output the translation. The fieldnames.po template can be written by hand (using notepad), or sometimes be extracted from a datamodule. Often, the number of field names is so low that the quickest solution is to write the po file by hand.