~alcinnz/bureaucromancy

122e87dc812cf8b4840858229f863c88b0d25b98 — Adrian Cochrane a year ago 696da31
Get internationalization infrastructure working!
2 files changed, 55 insertions(+), 2 deletions(-)

M bureaucromancy.cabal
A src/Text/HTML/Form/I18n.hs
M bureaucromancy.cabal => bureaucromancy.cabal +2 -2
@@ 68,7 68,7 @@ library
        Text.HTML.Form.Colours, Text.HTML.Form.Validate

    -- Modules included in this library but not exported.
    -- other-modules:
    other-modules:  Text.HTML.Form.I18n

    -- LANGUAGE extensions used by modules in this package.
    -- other-extensions:


@@ 78,7 78,7 @@ library
            file-embed-lzma >=0.0.1 && <1, file-embed >=0.0.15 && < 0.1, mtl >2 && <3,
            bytestring >=0.11 && <1, text >=2 && <3, containers >=0.6 && <1,
            xml-conduit >= 1.9 && <2, network-uri >=2.6 && <3, regex-tdfa >=1.3 && <2,
            filepath >=1.4 && <2, directory >=1.2 && <2,
            filepath >=1.4 && <2, directory >=1.2 && <2, aeson,
            hourglass >= 0.2.12 && < 0.3, tz >= 0.1 && < 0.2

    -- Directories containing source files.

A src/Text/HTML/Form/I18n.hs => src/Text/HTML/Form/I18n.hs +53 -0
@@ 0,0 1,53 @@
{-# LANGUAGE TemplateHaskell #-}
module Text.HTML.Form.I18n(strings, i18n, stringsJSON) where

import Data.FileEmbed (embedDir, makeRelativeToProject)
import Data.Text.Encoding (decodeUtf8Lenient)
import Data.Text (unpack, pack)
import Data.ByteString (ByteString)

import qualified Data.Aeson.KeyMap as KM
import Data.Aeson.Key as K
import Data.Aeson (Value(String, Object))

import Data.List (isPrefixOf)
import Data.Maybe (fromMaybe)

files :: [(FilePath, ByteString)]
files = $(embedDir =<< makeRelativeToProject "i18n")
bs2str :: ByteString -> String
bs2str = unpack . decodeUtf8Lenient

strings :: String -> [(String, String)]
strings = fromMaybe [] . flip lookup [(k, parseKVs $ bs2str v) | (k, v) <- files]

i18n :: String -> String -> String
i18n lang key = fromMaybe key $ lookup key $ strings lang

stringsJSON :: String -> Value
stringsJSON = Object . KM.fromList . map inner . strings
  where inner (k, v) = (K.fromString k, String $ pack v)

------
--- Support
------

parseKVs :: String -> [(String, String)]
parseKVs = map inner . filter (isPrefixOf "#") . filter null . map strip . lines
  where inner line = let (key, val) = break (==':') line in (strip key, strip val)

-- | Removes any whitespace at the start or end of a string
strip :: String -> String
strip = lstrip . rstrip

-- | Same as 'strip', but applies only to the left side of the string.
lstrip :: String -> String
lstrip s = case s of
                  [] -> []
                  (x:xs) -> if elem x " \t\r\n"
                            then lstrip xs
                            else s

-- | Same as 'strip', but applies only to the right side of the string.
rstrip :: String -> String
rstrip = reverse . lstrip . reverse