
Sorry, I accidently hit CTRL-Return which sent the message prematurely. Here is the rest again: On Thu, 2002-08-15 at 20:21, Sven Moritz Hallberg wrote:
[...]
After some pondering, I think we should base i18n on the first snippet's approach:
- There will be a data type representing a "message" which will be displayed to the user. The message is then translated to a string in a given language.
- The languages are, this appears natural to me, values of a data type again. We can have ctors for everything there are ISO codes for or so. In order to be extensible, a ctor taking a string argument appears suitable.
I suspect we can build all the convenience we need on top of this easy and clear to understand basis. For instance, if we want the string lookup way of things, one can just use String as the message type, like this: type Msg = String trans De "There is no space left on the storage device." = "Der Datentraeger ist voll." trans En = id The choice is up to the application developer. I'd personally tend to use a real data type, because that lets me do this: data Msg = ... | MessagesWaiting n | ... trans En MessagesWaiting n = "You have "++(show n)++m++" waiting." where m | n==1 = " message" | otherwise = " messages" trans De MessagesWaiting n | n==1 = "Sie haben eine neue Nachricht." | otherwise = "Es warten "++(show n)++" Nachrichten auf Sie." I can't think of a more contrived example right now, but I'm sure many exist. Also note that (once there is some sort of locale-aware show) one will get the benefits of that coherently across all messages. Reading translation tables from files is of course important. How about Read msg => readTransTable :: String -> IO (msg -> String) which takes a filename and yields a translation function? This would work for any data type in the Read class, String already is and a custom type could simply derive Read. Again, sorry for the accidental double post. :/ Regards, Sven Moritz