refactor(glossary): use more template haskell

This commit is contained in:
Gregor Kleen 2019-10-29 16:27:52 +01:00
parent 31a24dbcda
commit 5448804f01
3 changed files with 40 additions and 7 deletions

View File

@ -2,6 +2,7 @@ module Handler.Info where
import Import import Import
import Handler.Utils import Handler.Utils
import Handler.Info.TH
import qualified Data.Map as Map import qualified Data.Map as Map
import qualified Data.CaseInsensitive as CI import qualified Data.CaseInsensitive as CI
@ -84,7 +85,4 @@ getGlossaryR =
$(widgetFile "glossary") $(widgetFile "glossary")
where where
entries = $(i18nWidgetFiles "glossary") entries = $(i18nWidgetFiles "glossary")
msgMap = Map.fromList msgMap = $(glossaryTerms "glossary")
[ ("applicant" , MsgApplicant )
, ("course-participant", MsgCourseParticipant)
]

23
src/Handler/Info/TH.hs Normal file
View File

@ -0,0 +1,23 @@
module Handler.Info.TH
( glossaryTerms
) where
import Import
import Handler.Utils.I18n
import Language.Haskell.TH
import qualified Data.Char as Char
import qualified Data.Map.Strict as Map
import qualified Data.Text as Text
glossaryTerms :: FilePath -> Q Exp
glossaryTerms basename = do
translationsAvailable <- i18nWidgetFilesAvailable' basename
let terms = Map.mapWithKey (\k _ -> "Msg" <> unPathPiece k) translationsAvailable
[e|Map.fromList $(listE . map (\(int, msg) -> tupE [litE . stringL $ repack int, conE $ mkName msg]) $ Map.toList terms)|]
where
unPathPiece :: Text -> String
unPathPiece = repack . mconcat . map (over _head Char.toUpper) . Text.splitOn "-"

View File

@ -1,10 +1,13 @@
module Handler.Utils.I18n module Handler.Utils.I18n
where ( i18nWidgetFile
, i18nWidgetFilesAvailable, i18nWidgetFilesAvailable', i18nWidgetFiles
) where
import Import import Import
import Language.Haskell.TH import Language.Haskell.TH
import Language.Haskell.TH.Syntax (qRunIO) import Language.Haskell.TH.Syntax (qRunIO)
import qualified Language.Haskell.TH.Syntax as TH
import qualified Data.List as List import qualified Data.List as List
import qualified Data.List.NonEmpty as NonEmpty import qualified Data.List.NonEmpty as NonEmpty
@ -47,8 +50,8 @@ i18nWidgetFile basename = do
] ++ [ clause [wildP] (normalB [e| error "selectLanguage returned an invalid translation" |]) [] ] -- Fallback mostly there so compiler does not complain about non-exhaustive pattern match ] ++ [ clause [wildP] (normalB [e| error "selectLanguage returned an invalid translation" |]) [] ] -- Fallback mostly there so compiler does not complain about non-exhaustive pattern match
] [e|selectLanguage availableTranslations' >>= $(varE ws)|] ] [e|selectLanguage availableTranslations' >>= $(varE ws)|]
i18nWidgetFiles :: FilePath -> Q Exp i18nWidgetFilesAvailable' :: FilePath -> Q (Map Text (NonEmpty Text))
i18nWidgetFiles basename = do i18nWidgetFilesAvailable' basename = do
let i18nDirectory = "templates" </> "i18n" </> basename let i18nDirectory = "templates" </> "i18n" </> basename
availableFiles <- qRunIO $ listDirectory i18nDirectory availableFiles <- qRunIO $ listDirectory i18nDirectory
let fileKinds' = fmap (pack . dropExtension . takeBaseName &&& toTranslation . pack . takeBaseName) availableFiles let fileKinds' = fmap (pack . dropExtension . takeBaseName &&& toTranslation . pack . takeBaseName) availableFiles
@ -58,6 +61,15 @@ i18nWidgetFiles basename = do
availableTranslations' <- iforM fileKinds $ \kind -> maybe (fail $ "" <> i18nDirectory <> " has no translations for " <> unpack kind <> "") return . NonEmpty.nonEmpty availableTranslations' <- iforM fileKinds $ \kind -> maybe (fail $ "" <> i18nDirectory <> " has no translations for " <> unpack kind <> "") return . NonEmpty.nonEmpty
return availableTranslations'
i18nWidgetFilesAvailable :: FilePath -> Q Exp
i18nWidgetFilesAvailable = TH.lift <=< i18nWidgetFilesAvailable'
i18nWidgetFiles :: FilePath -> Q Exp
i18nWidgetFiles basename = do
availableTranslations' <- i18nWidgetFilesAvailable' basename
-- Dispatch to correct language (depending on user settings via `selectLanguage`) at run time -- Dispatch to correct language (depending on user settings via `selectLanguage`) at run time
ws <- newName "ws" -- Name for dispatch function ws <- newName "ws" -- Name for dispatch function
letE letE