如何使用格式化打印在Haskell中为CGI显示UTF-8?

时间:2012-07-23 17:42:03

标签: haskell utf-8 cgi printf

我有一个代码

module Main where

import Text.Printf

main = printf "%s%s" ("Content-type: text/html; charset=utf-8\n\n" :: String ) ("And немного русского" :: String)

如果我在终端执行它,我就会得到我想要的东西:

Content-type: text/html; charset=utf-8

And немного русского

但是当我尝试将其作为cgi-program执行时,我只有And(因为在这个词之后我有西里尔字符并且不想显示它们。)

当我使用putStr $ fromStringData.ByteString.Char8中的Data.ByteString.UTF8时没有问题,因此我认为我的LAMPP服务器没有问题。我还在httpd.conf中包含了AddDefaultCharset utf-8

我想要做的就是阅读包含%s%d等特殊符号的模板文件,然后在printf的帮助下更换它们(符号)与我所需要的,取决于查询字符串和显示。

我这样做只是为了好玩,我希望这个问题只能用纯Haskell解决。

2 个答案:

答案 0 :(得分:7)

让CGI程序依赖于语言环境可能适合也可能不适合;例如如果您生成的HTML有一个编码标题,表示它是UTF-8,那么您应该独立于系统区域设置生成UTF-8。

与语言环境无关的方法是在打印任何内容之前设置stdout的编码:

import System.IO

main = do
    hSetEncoding stdout utf8
    printf "%s%s" ("Content-type: text/html; charset=utf-8\n\n" :: String ) ("And немного русского" :: String)

您的代码:

/tmp $ echo $LANG
de_DE.utf8
/tmp $ ./Test2
Content-type: text/html; charset=utf-8

And немного русского
/tmp $ LANG=C ./Test2 
Content-type: text/html; charset=utf-8

And Test2: <stdout>: commitBuffer: invalid argument (invalid character)

修改后的代码:

/tmp $ ./Test2
Content-type: text/html; charset=utf-8

And немного русского
/tmp $ LANG=C ./Test2 
Content-type: text/html; charset=utf-8

And немного русского

答案 1 :(得分:0)

非常好的解决方案是在httpd.conf,.htaccess或httpd-vhosts.conf(在LAMPP中)中设置环境变量LANG,方法是将字符串SetEnv LANG en_US.UTF-8放在其中一个文件中。

在httpd.conf中,您可以为所有服务器设置此变量。

要使用.htaccess文件进行设置,必须在vhosts.conf中启用此商机

<Directory "<.htaccess directory>">
    AllowOverride All
</Directory>

然后,您将能够使用SetEnv在set目录中使用.htaccess文件更改变量。

在vhosts.conf中,您只需在SetEnv LANG en_US.UTF-8块中添加字符串VirtualHost

此解决方案允许您使用UTF-8和其他没有库的数据,例如Data.ByteString.Char8。

再次谢谢你。!