hunk ./TemplatesHSPI18n.markdown.lhs 253
->
+
hunk ./TemplatesHSPI18n.markdown.lhs 260
-> mkMessageFor "DemoApp" "Thing" "messages/thing" "en"
+> mkMessageFor "DemoApp" "Thing" "messages/thing" ("en")
hunk ./TemplatesHSPI18n.markdown.lhs 281
->
-> mkMessage "DemoApp" "messages/standard" "en"
+> mkMessage "DemoApp" "messages/standard" ("en")
hunk ./TemplatesHSPI18n.markdown.lhs 320
-It has created a new type for us `DemoAppMessage` where each constructor is derived from the constructors found in the `en.msg` file. The construct names all have the prefix `Msg`. That is just to avoid name collisions with the other constructors in your application.
+It has created a new type for us `DemoAppMessage` where each constructor is derived from the constructors found in the `en.msg` file. The constructor names all have the prefix `Msg`. That is just to avoid name collisions with the other constructors in your application.
hunk ./TemplatesHSPI18n.markdown.lhs 335
-
hunk ./TemplatesHSPI18n.markdown.lhs 337
-The `Problems` constructor in the `en.msg` file appears considerably more complicate than the `Hello` and `Goodbyte` cases:
+The `Problems` constructor in the `en.msg` file appears considerably more complicate than the `Hello` and `Goodbye` cases:
hunk ./TemplatesHSPI18n.markdown.lhs 339
-
+
hunk ./TemplatesHSPI18n.markdown.lhs 345
-There are two things going on here.
+There are a few things going on here.
hunk ./TemplatesHSPI18n.markdown.lhs 347
-
+
hunk ./TemplatesHSPI18n.markdown.lhs 369
-Will convert `n` to a `String` and splice the `String` into the message. The expression inside the `#{ }` must be a pure expression, and it must be a type that is an instance of the `ToMessage` class:
+will convert `n` to a `String` and splice the `String` into the message. The expression inside the `#{ }` must be a pure expression and it must have a type that is an instance of the `ToMessage` class:
hunk ./TemplatesHSPI18n.markdown.lhs 375
->
-> instance ToMessage String
-> instance ToMessage Text
hunk ./TemplatesHSPI18n.markdown.lhs 382
-
+
hunk ./TemplatesHSPI18n.markdown.lhs 400
-Looking at `en.msg` you notice that we need to use `plural_en` twice to make the grammar sound natural.
+Looking at `en.msg` you notice that we need to use `plural_en` twice to make the grammar sound natural. When creating messages is good to use whole phrases and sentences because changes in one part of a sentence can affect other parts of the sentence. Rules about plurals, word order, gender agreement, etc, vary widely from one language to the next. So it is best to assume as little as possible and give the translators as much flexibility as possible.
hunk ./TemplatesHSPI18n.markdown.lhs 425
-> thing_tr "en" TypeError = "type error"
-> thing_tr "en" SegFault = "segmentation fault"
+> thing_tr lang TypeError | lang == "en" = "type error"
+> thing_tr lang SegFault | lang == "en" = "segmentation fault"
hunk ./TemplatesHSPI18n.markdown.lhs 433
-The `mkMessageFor` function allows use to create translations for an existing type:
+The `mkMessageFor` function allows us to create translations for an existing type:
hunk ./TemplatesHSPI18n.markdown.lhs 437
-mkMessageFor ::
- String -- ^ master type
- -> String -- ^ data to translate
- -> FilePath -- ^ path to `.msg` files
- -> Lang -- ^ default language
- -> Q [Dec]
+> mkMessageFor ::
+> String -- ^ master type
+> -> String -- ^ data to translate
+> -> FilePath -- ^ path to `.msg` files
+> -> Lang -- ^ default language
+> -> Q [Dec]
hunk ./TemplatesHSPI18n.markdown.lhs 446
-We can create a set of `.msg` files specific for the `Thing` type like this:
+We can create a set of `.msg` files for the `Thing` type like this (note the file path):
hunk ./TemplatesHSPI18n.markdown.lhs 469
+> -- autogenerated by `mkMessageFor`
hunk ./TemplatesHSPI18n.markdown.lhs 482
+
hunk ./TemplatesHSPI18n.markdown.lhs 504
-The instance will need to know what the clients preferred languages
+The instance will need to know what the client's preferred languages
hunk ./TemplatesHSPI18n.markdown.lhs 511
+>
hunk ./TemplatesHSPI18n.markdown.lhs 515
-Depending on your application, you might be using a different custom server monad. But, that is all we need for this demo.
-
hunk ./TemplatesHSPI18n.markdown.lhs 523
+>
hunk ./TemplatesHSPI18n.markdown.lhs 531
+> pageTemplate :: (EmbedAsChild I18N body) => String -> body -> I18N XML
+> pageTemplate title body =
+> defaultTemplate title ()
+>
+> <% body %>
+>
+> <% mapM (\lang -> - <% lang %>
)
+> (["en", "en-GB", "jbo"] :: [String]) %>
+>
+>
+>
hunk ./TemplatesHSPI18n.markdown.lhs 544
-> defaultTemplate "home" ()
<% MsgHello %>
-
+> pageTemplate "home"
+>
<% MsgHello %>
+>
hunk ./TemplatesHSPI18n.markdown.lhs 549
-> defaultTemplate "goodbye" ()
<% MsgGoodbye %>
-
+> pageTemplate "goodbye"
+>
<% MsgGoodbye %>
+>
hunk ./TemplatesHSPI18n.markdown.lhs 554
-> defaultTemplate "problems" ()
<% MsgProblems n thing %>
+> pageTemplate "problems"
+>
<% MsgProblems n thing %>
+>
hunk ./TemplatesHSPI18n.markdown.lhs 562
+Getting the language preferences from `ReaderT [Lang]` is just one possibility. Your application may already have a place to store session data that you can get the preferences from, or you might just stick the preferences in a cookie.
+
hunk ./TemplatesHSPI18n.markdown.lhs 575
-You should not assume that the `Accept-Language` header is always correct. It is best to allow the user a way to override the `Accept-Language` header. That override could be stored in their user account or in session data. In this example we will just use a `QUERY_STRING` parameter `_LANG` to override the `Accept-Language` header.
+You should not assume that the `Accept-Language` header is always correct. It is best to allow the user a way to override the `Accept-Language` header. That override could be stored in their user account, session data, a cookie, etc. In this example we will just use a `QUERY_STRING` parameter `_LANG` to override the `Accept-Language` header.
hunk ./TemplatesHSPI18n.markdown.lhs 584
-> langs <- bestLanguage <$> acceptLanguage
+> langs <- bestLanguage <$> acceptLanguage
hunk ./TemplatesHSPI18n.markdown.lhs 586
+>
hunk ./TemplatesHSPI18n.markdown.lhs 612
+
+
[Source code for the app is here.]
+
[You will also need to download and unzip the message files here.]
+
+
+
+In this section we showed how to use `HSX` and `Happstack.Server.I18N`, and `shakespeare-i18n` together to provide an i18n solution. However, there are no dependencies between those libraries and modules. So, you can use other solutions to provide translations for `HSX`, or you can use `shakespeare-i18n` with other template systems.
+
+One thing that would make `shakespeare-i18n` better is a utility to help keep the `.msg` files up-to-date. I have describe
my ideas for a tool here. We just need a volunteer to implement it.
+
hunk ./messages/standard/en-GB.msg 1
-Hello: greetings
-Goodbye: seeya
+Hello: all right?
+Goodbye: cheerio
hunk ./messages/standard/jbo.msg 1
-Hello: greetings
-Goodbye: seeya
+Hello: coi
+Goodbye: co'o
hunk ./theme.css 174
+.wide
+{
+ width: 90em;
+}
+
+