Re: [Yesod] Yesod i18n, defaultLayout, and ihamlet

73 views
Skip to first unread message

Felipe Almeida Lessa

unread,
Jun 6, 2013, 4:42:39 PM6/6/13
to yesodweb
First of all, I didn't try solving your problem and am just going to
state what I remember from my experience creating my current
defaultLayout.

I remember that the type of widgetToPageContent is restrictive in the
sense that you can't do exactly what you want. AFAIR, the easiest
workaround is to use

mr <- getMessageRender

and instead of _{MsgApplicationName}, use #{mr MsgApplicationName}.
That'll allow you to avoid the "i" version.

HTH,

On Thu, Jun 6, 2013 at 4:55 PM, G. Ralph Kuntz, MD <grku...@gmail.com> wrote:
> Crosspost from StackOverFlow (no answers):
>
> I am trying to convert the tutorial code in Chapter 2 of the forthcoming
> "Play for Scala" book from Scala to Haskell (using Yesod). I am getting an
> error trying to "internationalize" my `defaultLayout`. I am (purposely) not
> using a scaffolded Yesod site because I am trying to understand the
> internals. Here is my code:
>
> {-# LANGUAGE FlexibleInstances
> , MultiParamTypeClasses
> , OverloadedStrings
> , QuasiQuotes
> , TemplateHaskell
> , TypeFamilies #-}
>
> module Main where
>
> import Text.Hamlet (ihamlet)
> import Yesod
> import Yesod.Static
>
> staticFiles "static"
>
> data PlayTutorial = PlayTutorial
> { getStatic :: Static
> }
>
> mkMessage "PlayTutorial" "messages" "en"
>
> mkYesod "PlayTutorial" [parseRoutes|
> / RootR GET
> /static StaticR Static getStatic
> |]
>
> instance Yesod PlayTutorial where
> defaultLayout contents = do
> PageContent title headTags bodyTags <- widgetToPageContent $ do
> addStylesheet $ StaticR stylesheets_bootstrap_css
> addStylesheet $ StaticR stylesheets_main_css
> contents
>
> ihamletToRepHtml [ihamlet|
> $doctype 5
>
> <html>
> <head>
> <title>#{title}
> ^{headTags}
> <body>
> <div ."screenshot">
> <div ."navbar navbar-fixed-top">
> <div ."container">
> <a ."brand" href=@{RootR}>
> _{MsgApplicationName}
> <div ."container">
> ^{bodyTags}
> |]
>
> getRootR :: Handler RepHtml
> getRootR = defaultLayout [whamlet|Hello, World!|]
>
> main :: IO ()
> main = do
> static@(Static settings) <- static "static"
> warp 8080 $ PlayTutorial static
>
> The error I get trying to build or run it with `runhaskell` is
>
> src/Main.hs:34:31:
> Couldn't match type `Text.Blaze.Internal.MarkupM ()'
> with `[(Data.Text.Internal.Text,
> Data.Text.Internal.Text)]
> -> Data.Text.Internal.Text'
> Expected type: Text.Hamlet.Render (Route PlayTutorial)
> Actual type: Text.Hamlet.Translate (Route PlayTutorial)
> In the first argument of `headTags', namely `_mrender_a7j2'
> In a stmt of a 'do' block: headTags _mrender_a7j2 _urender_a7j1
> In the expression:
> do { id
> ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
> "<!DOCTYPE html>\
> \<html><head><title>");
> id (toHtml title);
> id
> ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
> "</title>");
> headTags _mrender_a7j2 _urender_a7j1;
> .... }
>
> The error occurs on the `ihamlet` code.
>
> I believe that `headTags` is a `HtmlUrl`. I also think I need to convert
> that to a `HtmlUrlI18n`, but can't figure out how.
>
> Can I do the same thing (define `defaultLayout`) as a widget (using
> `whamlet`) then convert it to a `PageContent` using `widgetToPageContent`,
> then to a `RepHtml` (not sure how), instead of using `ihamlet`? Will that
> solve the i18n problem?
>
> I have tried Googling for a couple of hours but cannot find any extensive
> examples that create a new `defaultLayout` with i18n.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Yesod Web Framework" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to yesodweb+u...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>



--
Felipe.

Michael Snoyman

unread,
Jun 6, 2013, 6:42:13 PM6/6/13
to yeso...@googlegroups.com
Your intuition is correct. Let's look at the types:

    type HtmlUrl url = Render url -> Html
    type HtmlUrlI18n msg url = Translate msg -> Render url -> Html

HtmlUrl is a function taking just a Render url and giving an Html. HtmlUrlI18n takes both a Translate msg and a Render url to give you that Html. So what you want to do is ignore the Translate msg bit. I believe `const` is the answer you're looking for.

G. Ralph Kuntz, MD

unread,
Jun 6, 2013, 8:50:10 PM6/6/13
to yeso...@googlegroups.com
Michael -

Sorry, but specifically where should the 'const' be placed? During my Googling, I saw that you answered similarly to another question, but I tried placing 'const' in various places in the code and still got errors.

Thanks, Ralph

Michael Snoyman

unread,
Jun 7, 2013, 2:07:48 AM6/7/13
to yeso...@googlegroups.com
Try: ^{const headTags}


G. Ralph Kuntz, MD

unread,
Jun 7, 2013, 6:43:00 AM6/7/13
to yeso...@googlegroups.com, mic...@snoyman.com
That worked. Thank you.

G. Ralph Kuntz, MD

unread,
Jun 7, 2013, 6:44:49 AM6/7/13
to yeso...@googlegroups.com, mic...@snoyman.com
Is it reasonable to consider deprecating `ihamlet` and enhancing `hamlet` to support of of the i18n functionality? Will it put an undue burden on the developer who wants a single-language site?

On Friday, June 7, 2013 6:43:00 AM UTC-4, G. Ralph Kuntz, MD wrote:
That worked. Thank you.

Michael Snoyman

unread,
Jun 7, 2013, 6:47:42 AM6/7/13
to yeso...@googlegroups.com
You hit the nail on the head: having hamlet always take two arguments would be a major inconvenience. We go even farther in the opposite direction: shamlet is simply hamlet without *any* parameters, to make it more convenient to use.


G. Ralph Kuntz, MD

unread,
Jun 8, 2013, 1:50:43 PM6/8/13
to yeso...@googlegroups.com, mic...@snoyman.com
Michael-

I posted a synopsis of your replies to my StackOverFlow question.

Again, thanks.
Reply all
Reply to author
Forward
0 new messages