module Text.StringTemplates.TextTemplates (getTextTemplates) where
import qualified Data.Map as M
import Text.JSON
import System.Directory
import Data.List
import Data.Maybe
import Control.Monad
getTextTemplates :: FilePath
-> IO (M.Map String [(String, String)])
getTextTemplates :: String -> IO (Map String [(String, String)])
getTextTemplates String
path = do
[String]
dirs <- String -> IO [String]
getDirectoryContents String
path
[Maybe (String, [(String, String)])]
list <- [String]
-> (String -> IO (Maybe (String, [(String, String)])))
-> IO [Maybe (String, [(String, String)])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [String]
dirs ((String -> IO (Maybe (String, [(String, String)])))
-> IO [Maybe (String, [(String, String)])])
-> (String -> IO (Maybe (String, [(String, String)])))
-> IO [Maybe (String, [(String, String)])]
forall a b. (a -> b) -> a -> b
$ \String
d -> do
Bool
isDir <- String -> IO Bool
doesDirectoryExist (String -> IO Bool) -> String -> IO Bool
forall a b. (a -> b) -> a -> b
$ String
path String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
d
if (Bool -> Bool
not Bool
isDir Bool -> Bool -> Bool
|| String
"." String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` String
d)
then Maybe (String, [(String, String)])
-> IO (Maybe (String, [(String, String)]))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (String, [(String, String)])
-> IO (Maybe (String, [(String, String)])))
-> Maybe (String, [(String, String)])
-> IO (Maybe (String, [(String, String)]))
forall a b. (a -> b) -> a -> b
$ Maybe (String, [(String, String)])
forall a. Maybe a
Nothing
else do
[String]
entries <- (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter (\String
s -> String
".json" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` String
s) ([String] -> [String]) -> IO [String] -> IO [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO [String]
getDirectoryContents (String
path String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
d)
[[(String, String)]]
translations <- [String]
-> (String -> IO [(String, String)]) -> IO [[(String, String)]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [String]
entries (\String
e -> String -> IO [(String, String)]
readTranslationFile (String -> IO [(String, String)])
-> String -> IO [(String, String)]
forall a b. (a -> b) -> a -> b
$ String
path String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
d String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
e)
Maybe (String, [(String, String)])
-> IO (Maybe (String, [(String, String)]))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (String, [(String, String)])
-> IO (Maybe (String, [(String, String)])))
-> Maybe (String, [(String, String)])
-> IO (Maybe (String, [(String, String)]))
forall a b. (a -> b) -> a -> b
$ (String, [(String, String)]) -> Maybe (String, [(String, String)])
forall a. a -> Maybe a
Just (String
d,[[(String, String)]] -> [(String, String)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(String, String)]]
translations)
Map String [(String, String)] -> IO (Map String [(String, String)])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Map String [(String, String)]
-> IO (Map String [(String, String)]))
-> Map String [(String, String)]
-> IO (Map String [(String, String)])
forall a b. (a -> b) -> a -> b
$ [(String, [(String, String)])] -> Map String [(String, String)]
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(String, [(String, String)])] -> Map String [(String, String)])
-> [(String, [(String, String)])] -> Map String [(String, String)]
forall a b. (a -> b) -> a -> b
$ (Maybe (String, [(String, String)])
-> (String, [(String, String)]))
-> [Maybe (String, [(String, String)])]
-> [(String, [(String, String)])]
forall a b. (a -> b) -> [a] -> [b]
map Maybe (String, [(String, String)]) -> (String, [(String, String)])
forall a. HasCallStack => Maybe a -> a
fromJust ([Maybe (String, [(String, String)])]
-> [(String, [(String, String)])])
-> [Maybe (String, [(String, String)])]
-> [(String, [(String, String)])]
forall a b. (a -> b) -> a -> b
$ (Maybe (String, [(String, String)]) -> Bool)
-> [Maybe (String, [(String, String)])]
-> [Maybe (String, [(String, String)])]
forall a. (a -> Bool) -> [a] -> [a]
filter Maybe (String, [(String, String)]) -> Bool
forall a. Maybe a -> Bool
isJust [Maybe (String, [(String, String)])]
list
readTranslationFile :: String -> IO [(String,String)]
readTranslationFile :: String -> IO [(String, String)]
readTranslationFile String
file = do
String
mjson <- String -> IO String
readFile (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$ String
file
case String -> Result JSValue
forall a. JSON a => String -> Result a
decode String
mjson of
Ok JSValue
js -> [(String, String)] -> IO [(String, String)]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(String, String)] -> IO [(String, String)])
-> [(String, String)] -> IO [(String, String)]
forall a b. (a -> b) -> a -> b
$ [(String, String)] -> [(String, String)]
forall a. Ord a => [a] -> [a]
sort ([(String, String)] -> [(String, String)])
-> [(String, String)] -> [(String, String)]
forall a b. (a -> b) -> a -> b
$ JSValue -> [(String, String)]
textsFromJSON (JSValue -> [(String, String)]) -> JSValue -> [(String, String)]
forall a b. (a -> b) -> a -> b
$ JSValue
js
Result JSValue
e -> String -> IO [(String, String)]
forall a. HasCallStack => String -> a
error (String -> IO [(String, String)])
-> String -> IO [(String, String)]
forall a b. (a -> b) -> a -> b
$ String
"Can't parse json with message " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Result JSValue -> String
forall a. Show a => a -> String
show Result JSValue
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" for json" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
mjson
textsFromJSON :: JSValue -> [(String,String)]
textsFromJSON :: JSValue -> [(String, String)]
textsFromJSON (JSObject JSObject JSValue
jso) = ((String, JSValue) -> (String, String))
-> [(String, JSValue)] -> [(String, String)]
forall a b. (a -> b) -> [a] -> [b]
map (\(String
a,JSString JSString
js) -> (String
a, JSString -> String
fromJSString JSString
js)) (JSObject JSValue -> [(String, JSValue)]
forall e. JSObject e -> [(String, e)]
fromJSObject JSObject JSValue
jso)
textsFromJSON JSValue
_ = String -> [(String, String)]
forall a. HasCallStack => String -> a
error String
"While decoding JSON with translations"