hgettext-0.1.30: src/Text/I18N/GetText.hs
-- | This library provides basic internationalization capabilities
module Text.I18N.GetText (
getText,
nGetText,
dGetText,
dnGetText,
dcGetText,
dcnGetText,
bindTextDomain,
textDomain
) where
import Foreign.C.Types
import Foreign.C.String
import Foreign.C.Error
import Foreign.Ptr
import Data.Maybe (fromMaybe)
import System.Locale.SetLocale
foreign import ccall unsafe "libintl.h gettext" c_gettext
:: CString -> IO CString
foreign import ccall unsafe "libintl.h dgettext" c_dgettext
:: CString -> CString -> IO CString
foreign import ccall unsafe "libintl.h dcgettext" c_dcgettext
:: CString -> CString -> CInt -> IO CString
foreign import ccall unsafe "libintl.h ngettext" c_ngettext
:: CString -> CString -> CULong -> IO CString
foreign import ccall unsafe "libintl.h dngettext" c_dngettext
:: CString -> CString -> CString -> CULong -> IO CString
foreign import ccall unsafe "libintl.h dcngettext" c_dcngettext
:: CString -> CString -> CString -> CULong -> CInt -> IO CString
foreign import ccall unsafe "libintl.h bindtextdomain" c_bindtextdomain
:: CString -> CString -> IO CString
foreign import ccall unsafe "libintl.h textdomain" c_textdomain
:: CString -> IO CString
fromCString :: CString -> IO (Maybe String)
fromCString x | x == nullPtr = return Nothing
| otherwise = peekCString x >>= return . Just
fromCStringError :: String -> CString -> IO String
fromCStringError err x | x == nullPtr = throwErrno err
| otherwise = peekCString x
fromCStringDefault :: String -> CString -> IO String
fromCStringDefault d x = fromCString x >>= \r -> return (fromMaybe d r)
fromCStringPluralDefault :: (Eq a, Num a) => String -> String -> a -> CString -> IO String
fromCStringPluralDefault def def_plural n s
| n == 1 = fromCStringDefault def s
| otherwise = fromCStringDefault def_plural s
withCStringMaybe :: Maybe String -> (CString -> IO a) -> IO a
withCStringMaybe Nothing f = f nullPtr
withCStringMaybe (Just str) f = withCString str f
-- |getText wraps GNU gettext function. It returns translated string for the
-- input messages. If translated string not found the input string will be
-- returned.
--
-- The most common usage of this function is to declare function __:
--
-- > __ = unsafePerformIO . getText
--
-- and wrap all text strings into this function, e.g.
--
-- > printHello = putStrLn (__ "Hello")
--
getText :: String -> IO String
getText s =
withCString s $ \s' ->
c_gettext s' >>= fromCStringDefault s
-- |dGetText wraps GNU dgettext function. It works similar to 'getText'
-- but also could take domain name.
--
dGetText :: Maybe String -- ^ domain name, if 'Nothing' ---
-- default domain will be used
-> String -- ^ message id
-> IO String -- ^ return value
dGetText domainname msgid =
withCStringMaybe domainname $ \dn' ->
withCString msgid $ \msg' ->
c_dgettext dn' msg' >>= fromCStringDefault msgid
-- |dcGetText wraps GNU dcgettext function. It works similar to 'dGetText'
-- but also takes category id
dcGetText :: Maybe String -- ^ domain name, if 'Nothing' ---
-- default domain will be used
-> Category -- ^ locale facet
-> String -- ^ message id
-> IO String -- ^ return value
dcGetText domainname cat msgid =
withCStringMaybe domainname $ \dn' ->
withCString msgid $ \msg' ->
c_dcgettext dn' msg' (categoryToCInt cat) >>=
fromCStringDefault msgid
-- |nGetText wraps GNU ngettext function. It translates text string in the
-- user's native language, by lookilng up the approppiate plural form of the
-- message.
--
nGetText :: String -- ^ msgid in singular form
-> String -- ^ msgid in plural form
-> Integer -- ^ number, used to choose appropriate form
-> IO String -- ^ result string, by default if number is 1 than
-- singular form of msgid is returned, otherwise ---
-- plural
nGetText msgid msgid_plural n =
withCString msgid $ \msgid' ->
withCString msgid_plural $ \msgid_plural' ->
c_ngettext msgid' msgid_plural' (fromInteger n) >>=
fromCStringPluralDefault msgid msgid_plural n
-- |dnGetText wraps GNU dngettext function. It works similar to 'nGetText' but
-- also takes domain name
--
dnGetText :: Maybe String -- ^ domain name, if 'Nothing' ---
-- default domain will be used
-> String -- ^ msgid in singular form
-> String -- ^ msgid in plural form
-> Integer -- ^ number, used to choose appropriate form
-> IO String -- ^ result string, by default if number is 1 than
-- singular form of msgid is returned, otherwise ---
-- plural
dnGetText domainname msgid msgid_plural n =
withCStringMaybe domainname $ \dn' ->
withCString msgid $ \msgid' ->
withCString msgid_plural $ \msgid_plural' ->
c_dngettext dn' msgid' msgid_plural' (fromInteger n) >>=
fromCStringPluralDefault msgid msgid_plural n
-- |dcnGetText wraps GNU dcngettext function. It works similar to 'dnGetText' but
-- also takes category id
--
dcnGetText :: Maybe String -- ^ domain name, if 'Nothing' ---
-- default domain will be used
-> Category -- ^ locale facet
-> String -- ^ msgid in singular form
-> String -- ^ msgid in plural form
-> Integer -- ^ number, used to choose appropriate form
-> IO String -- ^ result string, by default if number is 1 than
-- singular form of msgid is returned, otherwise ---
-- plural
dcnGetText domainname cat msgid msgid_plural n =
withCStringMaybe domainname $ \dn' ->
withCString msgid $ \msgid' ->
withCString msgid_plural $ \msgid_plural' ->
c_dcngettext dn' msgid' msgid_plural'
(fromInteger n) (categoryToCInt cat) >>=
fromCStringPluralDefault msgid msgid_plural n
-- |bindTextDomain sets the base directory of the hierarchy
-- containing message catalogs for a given message domain.
--
-- Throws 'IOError' if fails
--
bindTextDomain :: String -- ^ domain name
-> Maybe String -- ^ path to the locale folder or 'Nothing' to return
-- base directory for domain
-> IO String -- ^ return value
bindTextDomain domainname dirname =
withCString domainname $ \domain ->
withCStringMaybe dirname $ \dir ->
c_bindtextdomain domain dir >>= fromCStringError "bindTextDomain fails"
-- |textDomain sets domain for future 'getText' call
--
-- Throws 'IOError' if fails
--
textDomain :: Maybe String -- ^ domain name, if 'Nothing' than returns
-- current domain name
-> IO String -- ^ return value
textDomain domainname =
withCStringMaybe domainname $ \domain ->
c_textdomain domain >>= fromCStringError "textDomain fails"