Localization of data that is generated dynamically
It was a difficult question to summarize, so we may need to edit it a bit.
Background
About four years ago, we had to translate our asp.net application for our clients in Mexico. Extensibility and scalability was not a big concern at the time (oh yeah, I just said those awful words) because we only have US and Mexican clients.
Instead of using resource files, we have replaced every single static text in our application with some type of server control (such as an asp.net label). We store every English word in a SQL database. We've added the ability to translate English text into another language, as well as the ability to add cultural overrides. For example, hello can be translated into ¡hola! in one language and redefine to ¡bueno!in another culture. The business has full control over these translations because it will build management utilities for them to control everything. The translation is called when we find that the user has a different browser culture than en-us. Each form descends from a base form that iterates through each server control and performs translation (translation data is stored as data in an application variable for culture). I am still amazed at how quickly the control iteration goes.
Problem
Businesses are very happy with how translations work. In addition to the static content I mentioned above, the business now wants some data to be translated as well. System notes are a good example of the translation they want. Example "Sent email #XXXX for customer" - Business wants the text "Sent email to customer" to be translated based on their browser culture.
I've read a couple of other posts on SO that talk about localization, but they don't address my problem. How do you translate a phrase that is dynamically generated? I could easily read the English text and translate "Sent", "Letter", "to" and "Customer", but I guarantee it will look silly to the end user because it is a phrase. The dynamic part of the system-generated note will skew any glances we take over the phrase if we saved the phrase in English, except for dynamic text.
One thought I had ... We don't have a system note type table. I guess we could create one that had placeholders for dynamic data and the translation engine would ignore the placeholders. The problem with this approach is that our SQL server database is a replication of the old database of choice and we really don't know all the types of phrases generated by the system (they are deep in the pic codebase, in subroutines, control files, etc.) .). Things like notes, tickers, and reasons for refusing payments are stored differently. Trying to normalize this data proved to be a daunting task. It would be a tremendous effort to go back and define and modify every selection program that generated the message.
This question is very close; but I am not dealing only with system status messages, but rather with an infinite number of phrases and types of phrases that have no central generation mechanism.
Any ideas?
a source to share
No bottleneck — what you call the (missing) “center generation engine” —is an architectural problem in this situation. Ideally, rebuilding the architecture to put such a bottleneck in place (so you can continue to use your generic culture-specific database approach for passing messages, just with "placeholders" like #XXXX in your example) ... The best thing.
If this is simply not feasible, you can place a bottleneck at the other end of the pipe — when the message is to be released. At this point or a few points, you need to try to match the (English) string that is to be released with a series of well thought out regexes (with "placeholders" usually like (.*?)
...) and thereby identify the appropriate key for the database lookup. Yes, it still is a lot of work, but at least it should be feasible without the problems you mention in the legacy translated selection code.
a source to share
As a last resort, I suppose you could try something like linking the assignment to Google if you don't have a translation of the specific phrase and sealing the translation for later use.
Saving translations for later versions provides both a data collection point for building a message catalog and a crude (if sometimes ridiculously wonky ) dynamically built translation starter set. After starting the process, keep track of which translations were viewed and how often each was impressed. Frequently sent machine translations may be revised and refined.
a source to share
We use the technique you suggest with insertion points.
"Sent email # {0: Email Num} to customer {1: Customer full name}"
What could be (in reverse order, Latin Pig):
"Ustomercay {1: customer's full name}) at least eterlay # {0: Letter Num}"
Note that this handles cases where the specific target language changes the insertion order, etc. It does not handle subtleties like first, second, etc. that should be handled by application logic / more expressions:
"This is your warning {0: first, second, third}
a source to share
Dynamic machine translation is not suitable for a product that you really expect people to pay money for. The only way to do this is with static templates containing insertion points (as shown by Cade Roo in his answer).
There is no way around the careful refactoring of your code to make this possible. The alternative is to do nothing with these phrases (this is what you are doing now and it works well, doesn't it?). Usually a translation is no better than an embarrassing bad translation.
a source to share