Accept-Language
がある。これは、ブラウザが扱うことができる言語情報をサーバに対して知らせるために定義されている。この値は具体的には
Accept-Language: ja
Accept-Language: en
Accept-Language: ja,en; q=0.5
などのように言語情報とそれらの優先順位を含んでいる。Netscape CommunicatorやInternet Explorerはもともと多言語対応がされており、優先的に使用したい言語を指定することができる。既定値は日本語版のブラウザでは
Accept-Language: ja
であり、英語版のブラウザ
Accept-Language: en
となっている。従って、サーバ側ではこのヘッダ情報によって表示するコンテンツの内容を切り替えることができる。(この仕組みはコンテンツ・ネゴシエーションと呼ばれる。)
1. 言語モードを日本語にする
2. IF Accept-Charsetの値が存在する
AND
Accept-Charsetの値が'en'で始まる THEN
2.1 言語モードを英語にする
ENDIF
文字コードセット=言語
とみなすことで事足りているからである。ところが日本では、文字コードセットこそJIS X 0201+ JIS X 0208という組み合わせでほぼ網羅されているが、マルチバイト符号化をする必要があり、符号化も合わせて意識しなければならない。具体的には
ISO-2022-JP
EUC-JP
Shift_JIS
という3種類の符号化方式が使われている。そこで、上記のcharset属性にはこれらの「符号化方式」を指定することになっている。
つまり、「Shift_JIS符号化方式のHTMLファイルを送信する」場合 には
Content-Type: text/html; charset=Shift_JIS
というヘッダ情報を送れば良い。ServletではServletResponseクラスのAPIとしてsetContentType()が用意されているので、
response.setContentType("text/html; charset=Shift_JIS");
のようにAPIを呼び出しておく。
| ※ | Servletの実装によっては、setContentType()でセットされた言語情報をその後の文字処理に影響を及ぼすことがある。たとえば、OracleのJDBCはデータベースとのデータのやりとりに、ここで設定された言語情報が使われるので、ページ中のできるだけ早いタイミングでContent-Typeを設定しておくことが望ましい。 |
<%@ page contentType="text/html; charset=Shift_JIS" %>のように記述するページディレクティブで判定するようである。つまり、Shift_JIS符号化方式で書かれている.jspファイルでは上記のようにページディレクティブを指定することによって、正しく符号化方式を判定して文字化けを防いでいる。
| ※ | Apache+JservやTomcatの実装ではここがうまくハンドリングされていないようで、設定などで工夫する必要があるようである。 |
日本語(Shift_JIS)を既定値とする場合のJSPソースの例:
<%@ page contentType="text/html; charset=Shift_JIS" %>
<HTML>
<HEAD><TITLE>Content negotiation sample</TITLE></HEAD>
<BODY>
<%
int LANG_JA = 0;
int LANG_EN = 1;
int lang = LANG_JA;
String langStr = request.getHeader("accept-language");
if (langStr != null && langStr.startsWith("en")) {
lang = LANG_EN;
response.setContentType("text/html; charset=iso-8859-1");
}
if (lang == LANG_EN) {
%>
<DIV ALIGN="CENTER"><H1>English</H1></DIV>
<%
} else {
%>
<DIV ALIGN="CENTER"><H1>日本語</H1></DIV>
<%
}
%>
</BODY>
</HTML>
このページにブラウザからアクセスしてみると、ブラウザで設定してある言語指定によって表示が切り替わることが確認できるはずである。
ただ、ページ中で言語を意識すべき箇所が現れる度に上記のif (lang == ...) のような記述を埋め込むのは、ソースの見通しが悪いし、あまり格好が良くない。ここは以下のようにJSPタグで制御したいものである。
<lang:en>
<DIV ALIGN="CENTER"><H1>English</H1></DIV>
</lang:en>
<lang:ja>
<DIV ALIGN="CENTER"><H1>日本語</H1></DIV>
</lang:ja>
実は、JSP1.1以上ではtaglibというJSPタグを拡張できる仕組みがあり、これを利用することで上記のような表現が可能である。しかし、不幸にしてOracle iAS 1.0のJSPは1.0であり、タグの拡張がサポートされていない。替りにJMLが用意されていて、<jml:...>という形の拡張タグを使うことができる。このJMLタグの中に
<jml:if>というものがあるので、これを利用すると
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib uri="oracle.jsp.parse.OpenJspRegisterLib" prefix="jml" %>
<HTML>
<HEAD><TITLE>Content negotiation sample</TITLE></HEAD>
<BODY>
<%
int LANG_JA = 0;
int LANG_EN = 1;
int lang = LANG_JA;
%>
<jml:if condition="lang == LANG_EN">
<DIV ALIGN="CENTER"><H1>English</H1></DIV>
</jml:if>
<jml:if condition="lang == LANG_JA">
<DIV ALIGN="CENTER"><H1>日本語</H1></DIV>
</jml:if>
</BODY>
</HTML>
のように記述することができる。しかし、これでは最初の例のようにJava Scriptletで書くのとほとんど変わりない割に、Oracle JSPだけでしか動かないプログラムとなってしまうため、移植性が低い。Oracle iASでしか使わないプログラムだからといって移植性を犠牲にすることは目先のことしか考えていない。移植性の低いプログラムはプラットホームのバージョンの違いにすら敏感だからである。特に、JSP1.0と1.1との差は非常に大きく、開発の効率が格段によくなるにも関わらず、JSP1.0しか使えないiAS 1.0を使いつづけなければならないのが、こうした移植性を考慮せずに開発したプログラムが足枷となるとしたら大変つまらないことである。