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