module Serokell.Util.I18N
( Translations
, fromYaml
, replaceTranslations
, YamlMapKey
, ToReplaceToken(..)
) where
import Data.Aeson.Extra.Map (FromJSONKey (..), getMap)
import Data.Aeson.Types (genericParseJSON, genericToJSON)
import qualified Data.Aeson.Types as AT
import Data.ByteString as BS
import qualified Data.Map.Strict as M
import Data.Text as T
import Data.Yaml (decodeEither)
import Formatting (build, sformat, (%))
import GHC.Generics (Generic, Rep)
import Serokell.Aeson.Options (defaultOptions)
class (Eq a, Ord a, FromJSONKey a) => YamlMapKey a
instance (Generic a, AT.GFromJSON (Rep a)) =>
FromJSONKey a where
parseJSONKey l = genericParseJSON defaultOptions (AT.String l)
instance (Eq a, Ord a, Generic a, AT.GFromJSON (Rep a)) =>
YamlMapKey a
type Translations lang token = M.Map lang (M.Map token T.Text)
fromYaml :: (YamlMapKey lang, YamlMapKey token)
=> BS.ByteString
-> Translations lang token
fromYaml yamlStr =
toLangMap $
either
(error .
T.unpack . sformat ("Error during translation YAML parsing " % build))
id $
decodeEither yamlStr
where
toLangMap = fmap getMap . getMap
class (Ord a, Eq a) => ToReplaceToken a where
toReplaceToken :: a -> T.Text
instance (Ord a, Eq a, Generic a, AT.GToJSON (Rep a)) => ToReplaceToken a where
toReplaceToken = (\(AT.String s) -> s) . genericToJSON defaultOptions
replaceTranslations
:: (ToReplaceToken token, Ord lang)
=> Translations lang token -> lang -> T.Text -> Maybe T.Text
replaceTranslations translations lang text =
M.foldrWithKey
(\token ->
T.replace $ "{{" `T.append` toReplaceToken token `T.append` "}}")
text <$>
lang `M.lookup` translations