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

如何使用格式化打印在Haskell for CGI中显示UTF-8?,haskell,utf-8,cgi,printf,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 немного русского 但当我试图将其作

我有密码

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程序执行时,我只有
(因为在这个单词之后我有西里尔字母,它们不想显示)

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

我要做的就是读取带有特殊符号的模板文件,如
%s
%d
等,然后在
printf
的帮助下,根据查询字符串和显示,用我需要的符号替换它们(符号)


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

让CGI程序依赖于语言环境可能合适,也可能不合适;e、 g.如果生成的HTML有一个编码头表示它是UTF-8,那么您应该独立于您的系统语言环境生成UTF-8

独立于区域设置的方法是在打印任何内容之前设置标准输出的编码:

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)

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

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

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

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

允许超越所有
然后,您将能够使用SetEnv在set目录中使用.htaccess文件更改变量

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

此解决方案允许您使用UTF-8和其他不带库的文件,如Data.ByteString.Char8


再次感谢你,n.m

检查Apache服务器运行的区域设置。我想象deaktop环境有
*.utf-8
。为了快速检查,您可以运行一个CGI脚本,只执行
locale
命令。我有以下列表:LANG=LANGUAGE=LC\u CTYPE=“POSIX”LC\u NUMERIC=“POSIX”LC\u TIME=“POSIX”LC\u COLLATE=“POSIX”LC\u MONETARY=“POSIX”LC\u MESSAGES=“POSIX”LC\u PAPER=“POSIX”LC\u NAME=“POSIX”LC_TELEPHONE=“POSIX”LC_MEASUREMENT=“POSIX”LC_IDENTIFICATION=“POSIX”LC_ALL=这是预期的。Haskell IO尝试使用区域设置的编码,在POSIX区域设置的情况下为ASCII。ASCII没有西里尔字符,所以在输出时跳过它们。通过设置LANG环境变量(在Apache中使用mod_env),可以尝试在CGI程序上强制使用UTF8语言环境(如果LAMP服务器上安装了任何语言环境)。或者,您可以将
printf
添加到字符串中,并使用例如
System.IO.UTF8
输出该字符串,无需进行区域设置操作。我确信,为您自己的问题添加答案的正确方法就是将其作为实际答案添加。你应该接受最能解决问题的答案,而不是将标题改为包含“已解决”一词。然后答案计数变为黄色,这样人们可以看到问题已经解决。这比我的建议更好。我完全忘记了
hsetencode
:-(
<Directory "<.htaccess directory>">
    AllowOverride All
</Directory>