localize-0.2.0.0: Text/Localize.hs
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, ExistentialQuantification, DeriveDataTypeable #-}
-- | This is the main module of the @localize@ package.
-- It contains definitions of general use and reexport generally required internal modules.
module Text.Localize
(
-- $description
--
-- * Most used functions
__, __n, __f,
-- * Basic functions
translate, translateN, translateNFormat,
lookup, withTranslation,
-- * Reexports
module Text.Localize.Types,
module Text.Localize.Load,
module Text.Localize.Locale
) where
import Prelude hiding (lookup)
import Control.Applicative
import Control.Monad
import qualified Data.Map as M
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import qualified Data.Text.Lazy as T
import qualified Data.Text.Lazy.Encoding as TLE
import qualified Data.Text.Encoding as TE
import Data.String
import Data.List hiding (lookup)
import Data.Monoid
import Data.Typeable
import qualified Data.Gettext as Gettext
import qualified Data.Text.Format.Heavy as F
import Data.Text.Format.Heavy.Parse (parseFormat)
import Text.Localize.Types
import Text.Localize.Load
import Text.Localize.Locale
-- $description
--
-- This is the main module of the @localize@ package. In most cases, you have to import only
-- this module. In specific cases, you may also want to import Text.Localize.IO or Text.Localize.State.
--
-- All functions exported by @localize@ package work with any instance of the
-- @Localized@ type class. There are two simple examples of this type class
-- implementation provided in separate modules (IO and State); however, in
-- complex applications it may be more convinient to implement @Localized@
-- instance for the monadic stack you already have.
--
-- Example of usage is:
--
-- @
-- import qualified Data.Text as T
-- import qualified Data.Text.Lazy.IO as TLIO
-- import Text.Localize
--
-- newtype MyMonad a = MyMonad {unMyMonad :: ... }
-- deriving (Monad)
--
-- instance Localized MyMonad where
-- ...
--
-- runMyMonad :: Translations -> MyMonad a -> IO a
-- runMyMonad = ...
--
-- hello :: T.Text -> MyMonad ()
-- hello name = do
-- liftIO $ TLIO.putStrLn =<< __ "Your name: "
-- liftIO $ hFlush stdout
-- name <- liftIO $ TLIO.getLine
-- greeting <- __f "Hello, {}!" (Single name)
-- liftIO $ TLIO.putStrLn greeting
--
-- main :: IO ()
-- main = do
-- translations <- locateTranslations $ linuxLocation "hello"
-- runMyMonad translations hello
--
-- @
--
-- See also working examples under @examples/@ directory.
--
-- | Look up for translation. Returns source string if translation not found.
lookup :: Translations -> LanguageId -> TranslationSource -> T.Text
lookup t lang bstr =
case M.lookup lang (tMap t) of
Nothing -> toText bstr
Just gmo -> Gettext.gettext gmo bstr
-- | Execute function depending on current translation catalog and context.
withTranslation :: Localized m
=> (b -> r) -- ^ Function to be executed if there is no
-- translation for current language loaded.
-> (Gettext.Catalog -> Maybe Context -> b -> r) -- ^ Function to be executed on current catalog.
-> (b -> m r) -- ^ Function lifted into @Localized@ monad.
withTranslation dflt fn b = do
t <- getTranslations
lang <- getLanguage
ctxt <- getContext
case M.lookup lang (tMap t) of
Nothing -> return $ dflt b
Just gmo -> return $ fn gmo ctxt b
-- | Translate a string.
translate :: (Localized m) => TranslationSource -> m T.Text
translate orig = do
t <- getTranslations
lang <- getLanguage
mbContext <- getContext
case M.lookup lang (tMap t) of
Nothing -> return $ toText orig
Just gmo ->
case mbContext of
Nothing -> return $ Gettext.gettext gmo orig
Just ctxt -> return $ Gettext.cgettext gmo ctxt orig
-- | Short alias for @translate@.
__ :: (Localized m) => TranslationSource -> m T.Text
__ = translate
-- | Translate a string, taking plural forms into account.
translateN :: (Localized m)
=> TranslationSource -- ^ Single form in original language
-> TranslationSource -- ^ Plural form in original language
-> Int -- ^ Number
-> m T.Text
translateN orig plural n = do
t <- getTranslations
lang <- getLanguage
mbContext <- getContext
case M.lookup lang (tMap t) of
Nothing -> return $ toText orig
Just gmo ->
case mbContext of
Nothing -> return $ Gettext.ngettext gmo orig plural n
Just ctxt -> return $ Gettext.cngettext gmo ctxt orig plural n
-- | Translate a string and substitute variables into it.
-- Data.Text.Format.Heavy.format syntax is used.
translateFormat :: (Localized m, F.VarContainer vars)
=> TranslationSource -- ^ Original formatting string
-> vars -- ^ Substitution variables
-> m T.Text
translateFormat orig vars = do
fmtStr <- translate orig
case parseFormat fmtStr of
Left err -> fail $ show err
Right fmt -> return $ F.format fmt vars
-- | Short alias for @translateFormat@.
__f :: (Localized m, F.VarContainer c) => TranslationSource -> c -> m T.Text
__f = translateFormat
-- | Translate a string, taking plural forms into account,
-- and substitute variables into it.
-- Data.Text.Format.Heavy.format syntax is used.
translateNFormat :: (Localized m, F.VarContainer vars)
=> TranslationSource -- ^ Single form of formatting string in original language
-> TranslationSource -- ^ Plural form of formatting string in original language
-> Int -- ^ Number
-> vars -- ^ Substitution variables
-> m T.Text
translateNFormat orig plural n vars = do
fmtStr <- translateN orig plural n
case parseFormat fmtStr of
Left err -> fail $ show err
Right fmt -> return $ F.format fmt vars
-- | Short alias for @translateNFormat@.
__n :: (Localized m, F.VarContainer c) => TranslationSource -> TranslationSource -> Int -> c -> m T.Text
__n = translateNFormat