Drupal 6. Please note that most of this is sound advice but that some of it is still being debated as far as what is best practice, specifically how to ensure that exportable structures are translatable. I encourage you to leave and read the comments.
Drupal's Core Function:
If you have written a module, you should be familiar with t(). Almost every interace string you write in your module should be wrapped with
t(). This function creates a mechanism so that the core module, locale, can offer translations for non-English languages. Without using the
t() function, Drupal would have no idea what strings are translatable and this would be very limiting for sites that were not in English (or not just in English).
The limiting nature of
t() is that there is no identification on strings. This means that Drupal is not really keeping track of changes in a string and there is no way to remove old strings that are no longer needed on the site. This is a bad thing for user-defined strings, strings that are entered into the interface, for example the title of a menu item, since it can change often.
The i18n Module
The i18n module (i18n is used based on the number of characters in the word internationalization), offers a set of modules to make Drupal a much better platform for multilingual sites. It offers the ability to translate some of the main structures of Drupal, like menus, taxonomies, blocks, and variables, as well as a more usable interface for translating.
The i18n module also offers a mechanism for translating strings that are based on identifiers for strings. The
i18nstrings($name, $string, $langcode = NULL) function allows for better management of user-defined strings.
Translatable Strings in Code
Though this problem is solved in core, it is still valid to point out in all of this. Interface strings (and other messages) that are defined in code, need to be translatable.
Interface strings and messages that are inputted by the user need to be able to be translated. These almost always live in the database. The main issue here is that there needs to be a mechanism to identify each inputted string so that changes can be maintained properly.
With modules that utilize a flexible plugin architecture or other dynamic system, one big issue is how to track what fields (or other data points) need to be translatable. This is very important to ensure that making something translatable is not hard-coded.
Recently (well, Views has done this well for a while), there has been a lot of work towards making Drupal structures that have the ability to be imported and exported. The main benefit of this is that it allows for setting-type structures to live in and be maintained in code. In turn, this means that a data structure that may contain interface strings and messages can be stored in either code or in the database.