Index: [Article Count Order] [Thread]

Date: Thu, 07 Oct 2004 18:07:47 +0900
From: Satoru Takabayashi <satoru@namazu.org>
Subject: [webrickja:120] Re: Accept-Language: の対応
To: webrickja@notwork.org
Message-Id: <m3vfdmq4kc.wl@namazu.org>
In-Reply-To: <20041007.171137.607952698.gotoyuzo@sawara.does.notwork.org>
References: <m33c0swbj8.wl@namazu.org>	<20041007.171137.607952698.gotoyuzo@sawara.does.notwork.org>
X-Mail-Count: 00120

GOTOU Yuuzou:
 
> でも、script_nameを書き換えるのはよくないような気がします。
> 例えば、#{DocumentRoot}/foo/index.html.jaがあるときの、/foo/
> へのアクセスは、
> 
>   filename:    #{DocumentRoot}/foo/index.index.ja
>   script_name: /foo/index.html.ja
>   path_info:   nil
> 
> になって、#{DocumentRoot}/foo/bar.cgi.jaがあるときの、
> /foo/bar.cgi/bazへのアクセスは、
> 
>   filename:    #{DocumentRoot}/foo/bar.cgi.ja
>   script_name: /foo/bar.cgi.ja
>   path_info:   /baz
> 
> になるのがいいと思いますが、どうでしょう。

はい、それがいいと思います。

[webrickja:118] のコードでは、set_filename を何度も呼び出すた
め script_name の値がどんどんおかしくなってしまうという問題
がありました。


> #{DocumentRoot}/foo.htmlと#{DocumentRoot}/foo.html.jaがある
> ときの/foo.htmlへのアクセスは、#{DocumentRoot}/foo.html.jaが
> 優先されてもいいような気がするのですが、そういうものではない
> んですね。

はい。 Apache では foo.html が優先されるので真似しました。


> > もしよければ、WEBrick 本体の FileHandler で Accept-Language:
> > に対応していただけると助かります。FileHandler のオプションに
> > :AcceptLanguage => true を指定するとAccept-Language を見る、
> > といった感じで指定できると便利だと思います。
> 
> いつも有効だと困るケースってありますかねえ。

foo.html が存在しないときに foo.html.{en,ja,...} の存在をいち
いち確認するコストがもったいないと考える人はいるかもしれませ
ん。


> 言語名の登録とフォールバックの優先順位を兼ねて、
> 
>   :AcceptableLanguages => ["en", "ja"]
> 
> とかできるといいのかもしれません。

なるほど、両方を兼ねて登録できるのはいいですね。これが空だっ
たら Multiviews 的な動作をしない、というふうにするといいかも
しれません。ファイルの存在を確認するのはここで指定された言語
だけに限定すればよさそうです。


ところで、[webrickja:118] のコードでは
@config[:DirectoryIndex] に対応するのを忘れてました。
手元では下のような方法で強引に対応しました。

WEBrick 本体をいじらずに Accept-Language に対応するのはやはり
少々無理があるようです。


module WEBrick::HTTPUtils
  module_function
  def mime_type(filename, mime_tab)
    suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
    # support multiview files such as index.html.en, foo.html.ja
    suffix2 = (/\.(\w+)\.[\w-]+$/ =~ filename && $1.downcase)
    mime_tab[suffix1] || mime_tab[suffix2] || "application/octet-stream"
  end
end

module WEBrick
  class HTTPRequest
    def parse_accept_language
      if self["Accept-Language"]
        tmp = []
        parts = self["Accept-Language"].split(/,\s*/)
        parts.each {|part|
          if m = /^([\w-]+)(?:;q=([\d]+(?:\.[\d]+)))?$/.match(part)
            lang = m[1]
            q = (m[2] or 1).to_f
            tmp.push([lang, q])
          end
        }
        @accept_language = 
          tmp.sort_by {|lang, q| q}.map {|lang, q| lang}.reverse
      else
        @accept_language = ["en"] # FIXME: should be customizable?
      end
    end

    def accept_language
      unless @accept_language
        parse_accept_language
      end
      return @accept_language
    end
  end
end

module WEBrick::HTTPServlet
  class MultilingualFileHandler < FileHandler
    def set_filename(req, res)
      original_path_info = req.path_info
      original_directory_index = @config[:DirectoryIndex]
      @config[:DirectoryIndex] += @config[:DirectoryIndex].map {|index| 
        req.accept_language.map {|lang| index + "." + lang }
      }.flatten
      begin
        return super(req, res)
      rescue HTTPStatus::NotFound => e
        req.accept_language.each {|lang|
          begin
            req.path_info = original_path_info + "." + lang
            return super(req, res)
          rescue HTTPStatus::NotFound
          end
        }
        raise e
      ensure
        @config[:DirectoryIndex] = original_directory_index
      end
    end
  end
end