Documentation‎ > ‎

Frequently Asked Questions

Q: Is anybody using this?
Q: Is it productive?
Q: I use the Delphi Integrated Translation Environment (ITE) - should I switch?
Q: Why is this project called dxgettext?
Q: What's the catch? (Why is it free?)
Q: I have a question that is not on this list
2. Considering to use this software
Q: My program is not in English. What do I do?
Q: Can I use this to translate a German language program to English?
Q: Does this support Unicode or widestrings?
Q: Does it work without Unicode or widestrings?
Q: My program uses resourcestrings - can gettext handle this?
3. Something is not being translated
Q: I want to know exactly why something isn't translated
Q: I use TObject derivatives that are not derived from TComponent, how do I translate them?
Q: My 'This is version '+Version+' of my program' is not extracted
Q: Some Delphi things are not translated. How do I translate these?
Q: How do I translate the Delphi runtime library messages?
Q: My menu items are not translated. Why?
Q: I have some 3rd party components without source. How do I translate those?
Q: Something in my forms isn't translated. What do I do?
4. Concepts
Q: How does gettext handle two different translations of the same English word?
Q: How should I choose text domains?
Q: Why are memos extracted line by line?
5. Using it
Q: I want to force my program to use another language than Windows settings, how?
Q: How do I switch language at runtime?
Q: I want to use language XXX but my controls do not support Unicode, what do I do?
6. Errors
Q: In Kylix and CLX apps, gettext('Test') cannot compile
Q: I got an Access Violation. Why?

1. About this project

Q: Is anybody using this?

A: Definitely. The concept, file formats and many of the tools are exactly the same as are used to localize most Linux, KDE, Gnome, Unix software. It is also emerging as a very common translation tool on Windows. Many thousands of programs have been localized using GNU gettext.

Q: Is it productive?

A: Definitely. It goes a long way to reduce the amount of work that has to be done by the translator. Several tools, including KBabel, even provide automated raw translations based on online dictionaries, so that the translator's job is reduced to finding incorrect translations. You'll be amazed at how productive this translation environment is once you get started.

Q: I use the Delphi Integrated Translation Environment (ITE) - should I switch?

A: A switch means that you have to change something, and all changes have a cost. But if you still do development on your application, or if you are starting up something completely new, the chance is very high that a switch pays off quickly in terms of Return of Investment. If you are part of a large programming group, and you use the Delphi ITE, try to ask your Boss how much money you spend on translators, and whether a 50% reduction on these costs for every future release would be a nice thing.

Q: Why is this project called dxgettext?

A: The original GNU gettext software includes a tool named xgettext, that extracts strings from a lot of different file formats, including C and C++ source code. The main tool in this project is the one that extracts strings from Delphi source code, so that tool was named dxgettext.

Q: What's the catch? (Why is it free?)

A: There is no catch. Developing a product is only a very small part of bringing a product to the market. If the authors of this translation system would try to earn money on it, there would a lot of work involved:

  • Raising money to pay us. At least one guy needs to be fulltime on a commercial project

  • Marketing - this costs money when doing it commercially. Nobody wants to pay for software they weren't told about.

  • Documentation - the current documentation is not near anything that a commercial product requires. Much commercial software also sells better if you make printed documentation, which means that you actually have to make printed documentation to make your project succeed.

  • CDs - customer's don't like receiving all software online, some simply want CDs. And they don't want CD-R's, they want real CDs. That costs money.

  • Release process - commercial software requires you to test your software with all possible environments before releasing it. That's a lot of work.

  • Software design - in order to make software sell easily, you need to design the software for it. Screenshots are everything, and GUIs are needed everywhere, and the GUIs need to use the latest GUI features from Microsoft. Sometimes a graphical designer is needed to make things look expensive.

  • Administration - all the above has to be administrated. When money is involved, somebody has to be in charge etc.

What we do now is much easier:

  • No money needed. We use our spare time to do it. If we don't have spare time, nothing is being done on the project.

  • Marketing. When things are free, people talk about it. SourceForge tells about it. We can announce it in newsgroups. We are very well placed on Google, probably because of being on SourceForge. It doesn't cost money and doesn't take time.

  • Documentation - well, documentation is always boring, but people can live with less when they don't pay for it. Hopefully we have enough documentation, otherwise let us know.

  • Release process - the first releases were quite buggy because of lack of testing. But the users commented on it, and in cooperation the quality of the releases have improved a lot, and the last many releases should not have any serious bugs inside. This would never have worked this way commercially, but it does as long as it is free.

  • Software design. Free software only has one goal: Being the best choice for those who use it. Since that's how we prefer software, too, there is no conflict between marketing and programmers on how the software should be.

  • Administration - SourceForge and YahooGroups make much of our administration easier, and both would be unthinkable for commercial projects. We don't need to create a formal organization, because if somebody gets angry at the project he can just take all the source-code and start another project as a branch of this project. Of course we hope that this never happens, but this mechanism means that people actually cooperate.

If you want to know more about why Open Source software works, Eric S. Raymond has written a free book about it: The Cathedral and the Bazaar

When Delphi developers cooperate on making Delphi better, we make Delphi a better choice, and thus make us Delphi developers a better choice than those programmers using other tools.

Q: I have a question that is not on this list

A: Send an empty e-mail to dxgettext-subscribe@yahoogroups.com to join our mailing list, and then write your question to dxgettext@yahoogroups.com

You can also send an e-mail directly to the maintainer of this FAQ: Lars@dybdahl.dk

We're always glad to help you out, and always happy to get feedback from our users.

2. Considering to use this software

Q: My program is not in English. What do I do?

A: Very easy, you do this:

  1. Extract all strings from your program as it is now.

  2. Translate your program to English.

  3. Extract all strings from your program afterwards.

  4. Use the msgmergePOT tool to create an English->YourLanguage translation file.

Now you have an English language program with a translation to the language that your program used before.

Q: Can I use this to translate a German language program to English?

A: This is not possible with version 1.1, because it enforces all untranslated messages to use only ascii characters. Version 1.2RC1 and later have support for non-ascii character translations, but you can also have a look at the question above.

Q: Does this support Unicode or widestrings?

A: Yes, this system supports widestrings all along, and actually does it much better than the Delphi ITE. But please note, that Delphi has built-in limitations. Delphi's VCL does not do Unicode, and resourcestring retrieval isn't Unicode either.

But if you get Unicode components and use the features of GNU gettext for Delphi, you can create an all-through Unicode program.

Q: Does it work without Unicode or widestrings?

A: Yes. The gettext() function returns widestring, and Delphi will automatically convert the strings to the local 8-bit character set when you use gettext() where you don't use widestrings otherwise. For instance, if you assign:

 MyButton.Caption:=gettext('New caption');

Then gettext will return a widestring and Delphi will convert that to the local 8-bit character set before it is assigned to the caption.

Q: My program uses resourcestrings - can gettext handle this?

A: Yes. It will automatically extract resourcestrings into the .po files, and it will automatic translate the resourcestrings when they are used in your source code.

3. Something is not being translated

Q: I want to know exactly why something isn't translated

A: As of version 1.1, there is a setting in gnugettext.pas, that will output a lot of details about the translation system into a logfile. Switch on this feature and you can see exactly how the translation system sees the world.

Q: I use TObject derivatives that are not derived from TComponent, how do I translate them?

A: The "TranslateProperties()" function handles all kinds of objects well, even TCollections, as long as they are derived from TPersistent. This includes report components, network components etc.

Q: My 'This is version '+Version+' of my program' is not extracted

A: Dxgettext has some logic, but it can't read Pascal code like the Delphi compiler does. Therefore, in the above example, Version must be defined in the same unit, otherwise dxgettext isn't able to extract it well.

Q: Some Delphi things are not translated. How do I translate these?

A: Get a translation for the library you need to have translated. The homepage provides translations for several libraries and for the Delphi runtime library in several languages, but you can also do it yourself, if you have the source code.

If you get a delphi.mo file with the translations for the Delphi runtime library and the VCL, put it together with your own translation and call:

AddDomainForResourceString ('delphi');

Somewhere in your program before you start translating forms etc.

If you still need support on this subject, please join our mailing list and get instructions there.

Q: How do I translate the Delphi runtime library messages?

A: See this link for instructions.

Q: My menu items are not translated. Why?

A: Please note that a TMainMenu has a property named AutoHotkeys. Set this to maManual, or it will automatically change the captions of the menu items, and thus make it impossible to translate the menus correctly.

Q: I have some 3rd party components without source. How do I translate those?

A: All resourcestrings in the 3rd party components will be translated automatically, so if you can make a list of them and add put them in resourcestrings in your source code, gnugettext.pas will extract the texts and translate them properly.

But if you cannot make a list, or if the 3rd party component contains form resources (like those in a dfm file), you could compile your program with separate packages and include the translation for that package together with the package.

If your application uses the xyz package and is translated to German (language code "de"), you might end up with the following files:

appdir\application.exe                   (your program) 
appdir\locale\de\LC_MESSAGES\default.mo  (the translation of your program) 
appdir\locale\de\LC_MESSAGES\delphi.mo   (the translation of the Delphi VCL) 
winsysdir\xyz.bpl                        (the xyz package) 
winsysdir\xyz.de                         (the translation of the xyz package)

Q: Something in my forms isn't translated. What do I do?

A: The extraction tool doesn't extract all properties from forms in order to make the life for the translators much easier. But even though it extracts a lot of texts, not all text may be translated once you run the program. You can solve this by assigning the text in the Form's OnCreate event like this:

component.property:=gettext('This text wasn''t translated in the first place');

4. Concepts

Q: How does gettext handle two different translations of the same English word?

A: Experience with thousands of programs shows, that this is extremely rare. When it does happen, it is usually an error. There are a few ways out, though, and the easiest one is to put that text into another domain. Another solution is to add a whitespace and then programmatically remove it again. This will make the text differ from the other English word.

Q: How should I choose text domains?

A: Most applications only use one text domain, and this set of tools assumes that that text domain is named "default". Normally, only very large projects need multiple text domains, and since it is fairly easy to split a domain into two, you shouldn't worry until your project gets too big for one domain, and then you will probably know by the structure of your project, how to divide the domain into smaller domains. Many projects that have several executables, still only use one single domain for all the applications, because it reduces the amount of work that is needed by the translator.

Q: Why are memos extracted line by line?

A: Delphi stores memos as a list of strings in dfm files, and does not put any information into the dfm files to tell that these strings come from a TStrings object. Therefore, it is not possible for the string extraction tools to see, that these strings should be assembled into one, big, multiline string in the po file. And since the po file doesn't contain the full memo text as one string, but as several lines, the TranslateComponent() procedure cannot do anything else than translate the memos line by line.

Another problem is that some programmers use the TMemo.Lines.Objects[] array to store objects. When you translate such a memo, it is important not to destroy these objects, which would be the case if a translation was assigned to the TMemo.Lines.Text property. By assigning translations to each TMemo.Lines.Strings[] index, this is avoided.

There is way to make it all work, though: Instead of putting the memo contents into the user interface at design time, you can assign the string at runtime like this:

MyMemo.Lines.Text:=
  _('This is a demo of my multiline memo translation, where '+
    'the entire memo is translated as one big message.'+sLineBreak+
    'This message even contains a programmed line break using '+
    'the sLineBreak constant, which is equivalent to #13#10 in '+
    'Delphi and #10 in Kylix.');

Here, the string extractor will take the entire string as one big message, the translator will translate it all as one big message, and at runtime it will be assigned as one big message.

5. Using it

Q: I want to force my program to use another language than Windows settings, how?

A: Insert this line as the first in your .dpr main program block:

UseLanguage ('fr');

Here, 'fr' means french. Please note that you can not just switch to a language that uses characters that isn't supported in your Windows. Switching to greek, russian or chinese without the proper fonts etc. won't work.

There is also another possibility: You can set the environment variable "LANG" to the desired language code, e.g. "set LANG=fr". This will override the detection of the Windows language settings.

Q: How do I switch language at runtime?

A: See the source of the TntSample application that is included in the download for Delphi.

Q: I want to use language XXX but my controls do not support Unicode, what do I do?

A: The gettext functions return widestrings, which will automatically be converted to the local character set by Delphi when you assign it to Control properties of type string or ansistring. This way, the local 8-bit characterset will be support automatically.

But if you really should need Unicode support in your controls, look for TNT controls. They are free and do Unicode on Windows NT/2000/XP.

6. Errors

Q: In Kylix and CLX apps, gettext('Test') cannot compile

A: In CLX, each form has a gettext() function that will be chosen instead of gnugettext.gettext(). Use _() instead:

a:=_('Test');

Q: I got an Access Violation. Why?

A: One of the forms that you translate using TranslateComponent() probably has a component that doesn't like one of its properties translated or has been programmed very badly and cannot be analyzed by TranslateComponent(). The solution is to ignore this component. See the list at the appendix called How to handle specific classes> for more information, or contact our e-mail list for further information. If you send an e-mail on that list you will most likely get your problem solved quickly.

Comments