haskell-servant / servant

Servat is a Haskell DSL for describing, serving, querying, mocking, documenting web applications and more!
https://docs.servant.dev/
1.82k stars 412 forks source link

Minimal I18n support #769

Open 2chilled opened 7 years ago

2chilled commented 7 years ago

I wonder if there is a general interest in having minimal i18n support. I implemented a combinator which reads the language out of a cookie and, if missing, out of "Accept-Language" header. In addition, there is a very simple function Lang -> Header to create the cookie.

This is something we need for every application providing a web ui. With a bit of guidance I could send you a small PR.

alpmestan commented 7 years ago

I would not mind something that facilitates i18n either in servant core or the new servant-contrib package. Feel free to however use this issue to expand/brainstorm on the design and on examples of what you and maybe other people need from that kind of combinator.

jkarni commented 7 years ago

It would be great if the combinator did negotiation (http-media should have the support for that, and we already depend on it for content-type negotiation), and if the content is unacceptable had the option of either responding with 406 or passed to the handlers the fact that nothing matched [0]. If something did match, the handlers would get the language that matched, and the Content-Language header would automatically be set to that. So I imagine something like:

data Langs (langs :: [Lang])
data Lang (language :: Symbol) (locale :: Symbol)

newtype Language = Language Text

instance (HasServer api ctx, ...) => HasServer (Lang langs :> api) where
   type ServerT (Lang langs :> api) m =  Language -> ServerT api m

--- In API:
type MyAPI = Langs [Lang "en" "*", Lang "fr" "CH"] :> Get '[JSON] SomeData

How does that sound?

(Could you say more about the cookie? That feels like something applications-specific, but maybe I'm missing something!)

[0] MDN recommends the latter.