What methods and tools are there for i18n of Haskell programs? (I.e. I want output in several languages, with the language configurable at runtime, and I want to add languages without recompilation.) a typical source text (for my application) is here http://141.57.11.163/cgi-bin/cvsweb/tool/src/Graph/Circle/Plain.hs?rev=1.2 it contains (German) text strings all over the place. In Java/Eclipse, I would "Source -> Externalize Strings" and this replaces each string by something like Messages.getString("Foobar.0") where Messages is a global variable (constructed at program start from reading a properties file) In Haskell, I see at least two problems: a) reading the file is in IO b) there are no "global variables". implicit parameters perhaps? c) when I'm trying to be clever, I use "deriving Show/Read" or similar. then i18n should rename the constructors/accessors? I rather not. http://141.57.11.163/cgi-bin/cvsweb/tool/src/Grammatik/Type.hs.drift?rev=1.6 Best regards, -- -- Johannes Waldmann -- Tel/Fax (0341) 3076 6479/80 -- ---- http://www.imn.htwk-leipzig.de/~waldmann/ -------
Hi there is a project for i18n on sourceforge. It contains for example bindings to the gettext library which could be helpful. I'm not sure though how up to date this project is (project page looks very empty). The code is still available in the sourceforge cvs repository: http://haskell-i18n.cvs.sourceforge.net/haskell-i18n/ Another possibility is to load the lookup tables in the IO monad and then use a Reader Monad to make your lookup table available in your code. regards Stefan 2006/11/15, Johannes Waldmann <waldmann@imn.htwk-leipzig.de>:
What methods and tools are there for i18n of Haskell programs?
(I.e. I want output in several languages, with the language configurable at runtime, and I want to add languages without recompilation.)
a typical source text (for my application) is here http://141.57.11.163/cgi-bin/cvsweb/tool/src/Graph/Circle/Plain.hs?rev=1.2 it contains (German) text strings all over the place.
In Java/Eclipse, I would "Source -> Externalize Strings" and this replaces each string by something like Messages.getString("Foobar.0") where Messages is a global variable (constructed at program start from reading a properties file)
In Haskell, I see at least two problems: a) reading the file is in IO b) there are no "global variables". implicit parameters perhaps? c) when I'm trying to be clever, I use "deriving Show/Read" or similar. then i18n should rename the constructors/accessors? I rather not. http://141.57.11.163/cgi-bin/cvsweb/tool/src/Grammatik/Type.hs.drift?rev=1.6
Best regards, -- -- Johannes Waldmann -- Tel/Fax (0341) 3076 6479/80 -- ---- http://www.imn.htwk-leipzig.de/~waldmann/<http://www.imn.htwk-leipzig.de/%7Ewaldmann/>-------
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
A comment on gettext, On Nov 15, 2006, at 17:35, Stefan Aeschbacher wrote:
Hi
there is a project for i18n on sourceforge. It contains for example bindings to the gettext library which could be helpful. I'm not sure though how up to date this project is (project page looks very empty). The code is still available in the sourceforge cvs repository:
I think gettext would be a very nice thing to use in Haskell. At the moment, it is slightly inefficient to lookup a string in order to substitute it for a translation. For instance, say l_ is your translations function, saying (l_ "Translate this") is compiled into a C string constant, that GHC then turns lazily into a list of characters, which l_ then turns into an array in C land to pass to the gettext function, which, in turn, returns a new C string array that has to be turned into a Haskell string again. So I'm glad Lennart proposed to turn String into a class which would then make it possible to pass a pointer to a contant C string to gettext. Axel.
Stefan
2006/11/15, Johannes Waldmann <waldmann@imn.htwk-leipzig.de >:
(I.e. I want output in several languages, with the language configurable at runtime, and I want to add languages without recompilation.)
a typical source text (for my application) is here MailScanner warning: numerical links are often malicious: http://141.57.11.163/cgi-bin/cvsweb/tool/src/Graph/Circle/Plain.hs? rev=1.2 it contains (German) text strings all over the place.
In Java/Eclipse, I would "Source -> Externalize Strings" and this replaces each string by something like Messages.getString("Foobar.0") where Messages is a global variable (constructed at program start from reading a properties file)
In Haskell, I see at least two problems: a) reading the file is in IO b) there are no "global variables". implicit parameters perhaps? c) when I'm trying to be clever, I use "deriving Show/Read" or similar. then i18n should rename the constructors/accessors? I rather not. MailScanner warning: numerical links are often malicious: http://141.57.11.163/cgi-bin/cvsweb/tool/src/Grammatik/Type.hs.drift? rev=1.6
Best regards, -- -- Johannes Waldmann -- Tel/Fax (0341) 3076 6479/80 -- ---- http://www.imn.htwk-leipzig.de/~waldmann/ -------
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
Johannes Waldmann wrote:
What methods and tools are there for i18n of Haskell programs?
(I.e. I want output in several languages, with the language configurable at runtime, and I want to add languages without recompilation.)
a typical source text (for my application) is here http://141.57.11.163/cgi-bin/cvsweb/tool/src/Graph/Circle/Plain.hs?rev=1.2 it contains (German) text strings all over the place.
In Java/Eclipse, I would "Source -> Externalize Strings" and this replaces each string by something like Messages.getString("Foobar.0") where Messages is a global variable (constructed at program start from reading a properties file)
In Haskell, I see at least two problems: a) reading the file is in IO b) there are no "global variables". implicit parameters perhaps? c) when I'm trying to be clever, I use "deriving Show/Read" or similar. then i18n should rename the constructors/accessors? I rather not. http://141.57.11.163/cgi-bin/cvsweb/tool/src/Grammatik/Type.hs.drift?rev=1.6
Fortunately, a) is unavoidable in general :) But assuming that the language loading only happens at startup, I'd go for an unsafePerformIO: module Main where main = do language <- getArgs initInternationalization language ... module Internationalization where initInternationalization lang = do ... writeIORef stringTable ... {-# NOINLINE stringTable #-} stringTable :: IORef (Data.Map String String) stringTable = unsafePerformIO $ newIORef $ Map.empty {-# NOINLINE getString #-} getString :: String -> String getString = unsafePerformIO $ do map <- readIORef stringTable return $ \s -> fromJust' s $ lookup s map where fromJust' (Just x) _ = x fromJust' Nothing s = "[untranslated message] " ++ s You can use (getString) just as you would use (Messages.getString("...")). Note that the language is fixed after first call to getString and it's not wise to call getString before initInternationalization. There is no way to change the language after startup which is probably what you want. If not, then you just have to float (\s ->) out of unsafePerformIO: getString = \s -> unsafePerformIO $ do ... return $ fromJust' ... Of course, you can also integrate the initialization into (getString). Regards, apfelmus
participants (4)
-
apfelmus@quantentunnel.de -
Axel Simon -
Johannes Waldmann -
Stefan Aeschbacher