[web-devel] [Yesod] rendering different templates for different languages
Max Cantor
mxcantor at gmail.com
Mon Feb 21 07:40:17 CET 2011
Of course, you just pointed out one of the big difficulties with i18n. I dont think you're wife would take kindly to you referring to her in the male gender. so now, you need the person's gender too. i18n is hard :( the whole would should switch to esperanto.
max
On Feb 21, 2011, at 2:25 PM, Michael Snoyman wrote:
> A proper i18n solution is high on my wish list right now, but I've
> purposely avoided implementing one so far since I'd rather wait until
> I think we have a good solution as opposed to implementing an
> acceptable solution now. But let me share my ideas, it might help you
> out here.
>
> In general, it's very uncommon that you need a completely separate set
> of templates for each language. Your markup, classes, styles, and
> logic will likely be identical for each language, and creating a
> separate template for each will just result in a lot of pain in the
> long run. Instead, you're likely better off having a single template
> and just translating strings.
>
> I've blogged about this before[1]. My idea is to use a datatype for
> your translatable strings, and then have a function that takes a
> language and a value and returns the translated string. A simple
> example:
>
> data Strings = Hello | Person String Int
> toEnglish Hello = "Hello"
> toEnglish (Person name age) = name ++ " is " ++ show age ++ "
> years old" -- obviously need to check if person is 1 year old and
> correct
>
> toHebrew Hello = "שלום"
> toHebrew (Person name age) = name ++ " הוא בן " ++ show age ++ " שנים"
>
> The nice thing about this approach is you have the full power of
> Haskell to address typical translation issues, such as pluralization,
> word order and gender matching. (As a counter example, at work, we use
> XSLT for this, and then you get the full power of XSLT for solving the
> problem ::cringe::.)
>
> You can then use the languages[2] function from Yesod to help you out:
>
> getRenderString = chooseFunc `fmap` languages
> where
> chooseFunc [] = toEnglish -- default language
> chooseFunc ("en":_) = toEnglish
> chooseFunc ("he":_) = toHebrew
> chooseFunc (_:x) = chooseFunc x
>
> Then you can write a handler function like:
>
> getPersonR name age = do
> render <- getRenderString
> defaultLayout [$hamlet|
> <h1>#{render Hello}
> <p>#{render $ Person name age}
> |]
>
> Which will work for English and Hebrew just fine. Ideally, I would
> like to add support to Hamlet for this directly, involving a String
> rendering function similar to the URL rendering function already in
> place. But for the moment, this should work.
>
> I'd love to hear peoples opinions about this.
>
> Michael
>
> [1] http://docs.yesodweb.com/blog/i18n-in-haskell
> [2] http://hackage.haskell.org/packages/archive/yesod-core/0.7.0.1/doc/html/Yesod-Request.html#v:languages
>
> On Sun, Feb 20, 2011 at 11:19 PM, Dmitry Kurochkin
> <dmitry.kurochkin at gmail.com> wrote:
>> Hi all.
>>
>> I want a handler to render different templates for different languages.
>> I have getCurrentLanguage function and now I try to do something like:
>>
>> getRootR = do
>> currentLanguage <- getCurrentLanguage
>> defaultLayout $ do
>> addWidget $(widgetFile $ currentLanguage ++ "/homepage")
>>
>> This results in:
>>
>> GHC stage restriction: `currentLanguage'
>> is used in a top-level splice or annotation,
>> and must be imported, not defined locally
>>
>> This makes sense to me, because TH is calculated at compile time. I
>> would like to hear ideas how to work around this restriction. Perhaps
>> there is an existing solution in Yesod?
>>
>> At the moment, the best I could think of is smth like this:
>>
>> getRootR = do
>> currentLanguage <- getCurrentLanguage
>> defaultLayout $ do
>> case currentLanguage of
>> "en" -> addWidget $(widgetFile "en/homepage")
>> ... and so on for each language ...
>>
>> Obviously, this is not a solution taking in account that there are many
>> languages and many handlers.
>>
>> I was considering creating a global (template file name -> rendered
>> template) map. But I am not sure this is really feasible.
>>
>> Regards,
>> Dmitry
>>
>> _______________________________________________
>> web-devel mailing list
>> web-devel at haskell.org
>> http://www.haskell.org/mailman/listinfo/web-devel
>>
>
> _______________________________________________
> web-devel mailing list
> web-devel at haskell.org
> http://www.haskell.org/mailman/listinfo/web-devel
More information about the web-devel
mailing list