module Distribution.Simple.I18N.GetText
( installGetTextHooks
, gettextDefaultMain
) where
import Distribution.PackageDescription
import Distribution.Simple
import Distribution.Simple.InstallDirs as I
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Setup
import Distribution.Simple.Utils
import Distribution.Verbosity
import Control.Arrow (second)
import Control.Monad
import Data.List (nub, unfoldr)
import Data.Maybe (fromMaybe, listToMaybe)
import System.Directory
import System.Exit
import System.FilePath
import System.Process
import Internal
gettextDefaultMain :: IO ()
gettextDefaultMain = defaultMainWithHooks $ installGetTextHooks simpleUserHooks
installGetTextHooks :: UserHooks
-> UserHooks
installGetTextHooks uh =
uh { confHook = \a b -> do
lbi <- (confHook uh) a b
return (updateLocalBuildInfo lbi)
, postInst = \args iflags pd lbi -> do
postInst uh args iflags pd lbi
installPOFiles (fromFlagOrDefault maxBound (installVerbosity iflags)) lbi
, postCopy = \args cflags pd lbi -> do
postCopy uh args cflags pd lbi
installPOFiles (fromFlagOrDefault maxBound (copyVerbosity cflags)) lbi
}
updateLocalBuildInfo :: LocalBuildInfo -> LocalBuildInfo
updateLocalBuildInfo l =
let sMap = getCustomFields l
[domDef, catDef] = map ($ sMap) [getDomainDefine, getMsgCatalogDefine]
dom = getDomainNameDefault sMap (getPackageName l)
tar = targetDataDir l
[catMS, domMS] = map (uncurry formatMacro) [(domDef, dom), (catDef, tar)]
in (appendCPPOptions [domMS,catMS] . appendExtension [EnableExtension CPP]) l
installPOFiles :: Verbosity -> LocalBuildInfo -> IO ()
installPOFiles verb l =
let sMap = getCustomFields l
destDir = targetDataDir l
dom = getDomainNameDefault sMap (getPackageName l)
installFile file = do
let fname = takeFileName file
let bname = takeBaseName fname
let targetDir = destDir </> bname </> "LC_MESSAGES"
createDirectoryIfMissing True targetDir
ph <- runProcess "msgfmt" [ "--output-file=" ++ (targetDir </> dom <.> "mo"), file ]
Nothing Nothing Nothing Nothing Nothing
ec <- waitForProcess ph
case ec of
ExitSuccess -> return ()
ExitFailure n -> warn verb ("'msgfmt' exited with non-zero status (rc = " ++ show n ++ ")")
in do
filelist <- getPoFilesDefault sMap
mapM_ installFile filelist
forBuildInfo :: LocalBuildInfo -> (BuildInfo -> BuildInfo) -> LocalBuildInfo
forBuildInfo l f =
let a = l{localPkgDescr = updPkgDescr (localPkgDescr l)}
updPkgDescr x = x{library = updLibrary (library x),
executables = updExecs (executables x)}
updLibrary Nothing = Nothing
updLibrary (Just x) = Just $ x{libBuildInfo = f (libBuildInfo x)}
updExecs x = map updExec x
updExec x = x{buildInfo = f (buildInfo x)}
in a
appendExtension :: [Extension] -> LocalBuildInfo -> LocalBuildInfo
appendExtension exts l =
forBuildInfo l updBuildInfo
where updBuildInfo x = x{defaultExtensions = updExts (defaultExtensions x)}
updExts s = nub (s ++ exts)
appendCPPOptions :: [String] -> LocalBuildInfo -> LocalBuildInfo
appendCPPOptions opts l =
forBuildInfo l updBuildInfo
where updBuildInfo x = x{cppOptions = updOpts (cppOptions x)}
updOpts s = nub (s ++ opts)
formatMacro :: Show a => [Char] -> a -> [Char]
formatMacro name value = "-D" ++ name ++ "=" ++ (show value)
targetDataDir :: LocalBuildInfo -> FilePath
targetDataDir l =
let dirTmpls = installDirTemplates l
prefix' = prefix dirTmpls
data' = datadir dirTmpls
dataEx = I.fromPathTemplate $ I.substPathTemplate [(PrefixVar, prefix')] data'
in dataEx ++ "/locale"
getPackageName :: LocalBuildInfo -> String
getPackageName = fromPackageName . packageName . localPkgDescr
getCustomFields :: LocalBuildInfo -> [(String, String)]
getCustomFields = customFieldsPD . localPkgDescr
findInParametersDefault :: [(String, String)] -> String -> String -> String
findInParametersDefault al name def = (fromMaybe def . lookup name) al
getDomainNameDefault :: [(String, String)] -> String -> String
getDomainNameDefault al d = findInParametersDefault al "x-gettext-domain-name" d
getDomainDefine :: [(String, String)] -> String
getDomainDefine al = findInParametersDefault al "x-gettext-domain-def" "__MESSAGE_CATALOG_DOMAIN__"
getMsgCatalogDefine :: [(String, String)] -> String
getMsgCatalogDefine al = findInParametersDefault al "x-gettext-msg-cat-def" "__MESSAGE_CATALOG_DIR__"
getPoFilesDefault :: [(String, String)] -> IO [String]
getPoFilesDefault al = toFileList $ findInParametersDefault al "x-gettext-po-files" ""
where toFileList "" = return []
toFileList x = liftM concat $ mapM matchFileGlob $ split' x
split' x = concatMap lines $ concatMap words $ unfoldr (\b -> fmap (const . (second $ drop 1) . break (==',') $ b) . listToMaybe $ b) x