gettext-th 0.1.0.1 → 0.1.0.2
raw patch · 3 files changed
+58/−35 lines, 3 files
Files
- README.md +33/−0
- gettext-th.cabal +3/−3
- src/I18N/Gettext/TH.hs +22/−32
+ README.md view
@@ -0,0 +1,33 @@+# gettext-th++The [gettext](https://www.gnu.org/software/gettext/) project provides a library and tools for internationalization and localization of software. Haskell has already support for gettext. It is possible either to use the C-library with FFI ([hgettext](https://hackage.haskell.org/package/hgettext)) or to use a pure Haskell implementation ([haskell-gettext](https://hackage.haskell.org/package/haskell-gettext-0.1.2.0)).++With gettext the executables and the translations are separated and the language strings are looked up at runtime. The [loadCatalog](https://hackage.haskell.org/package/haskell-gettext-0.1.2.0/docs/Data-Gettext.html) of gettext-haskell has to read the translations at runtime with IO.++This is difficult if you transpile your haskell code to javascript, which runs in a browser. To close this gap gettext-th moves the lookup of messages to compile time. A similar approach was taken for [angular-i18n](https://angular.io/guide/i18n-overview) for performance reasons.+This of course has some drawbacks (less flexible and one program per language) and some benefits (simple and performant).++Theoretically gettext-th could also choose between runtime and compile time lookups.++# Warning++gettext-th will use IO at compile time and will write a file.++# How to use it++See for an example in example/hello.++To use gettext-th in your app use it and compile it. It will fail, but it will create the file po/messages.pot.+Run in the po folder:++```sh+msginit+msgfmt en_US.po+```++With that the program compiles. And you can update en_US.po again.++Now copy en_US.po to de_DE.po, translate the messages and run `msgfmt de_DE.po`.+If you recompile (maybe run cabal clean first) the output of your app is in german.++
gettext-th.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: gettext-th-version: 0.1.0.1+version: 0.1.0.2 synopsis: gettext-th can internationalise a haskell program without runtime dependencies @@ -9,7 +9,7 @@ The [gettext](https://www.gnu.org/software/gettext/) project provides a library and tools for internationalization and localization of software. gettext-th allows you to use the gettext tooling without adding any runtime dependencies because texts are exchanged at compile time. But this also means that you have an application per language. bug-reports: https://github.com/chrbauer/gettext-th/issues-+homepage: https://github.com/chrbauer/gettext-th -- The license under which the package is released. license: BSD-3-Clause author: Christoph Bauer@@ -18,7 +18,7 @@ -- A copyright notice. -- copyright: category: i18, Text-extra-source-files: CHANGELOG.md+extra-source-files: CHANGELOG.md, README.md library exposed-modules: I18N.Gettext.TH
src/I18N/Gettext/TH.hs view
@@ -1,5 +1,5 @@ module I18N.Gettext.TH-(gettext, __, gettexts)+(gettext, __) where import Language.Haskell.TH@@ -30,8 +30,8 @@ potFileName = "po/messages.pot" -poFileName :: FilePath-poFileName = replaceExtension potFileName ".po"+-- poFileName :: FilePath+-- poFileName = replaceExtension potFileName ".po" moFileName :: FilePath moFileName = replaceExtension potFileName ".mo"@@ -87,40 +87,25 @@ gettextQ str = do createPotFile loc <- location- runIO $ appendFile potFileName $ unlines [- "",- "#: " ++ (loc_filename loc) ++ ":0", -- TODO line nr or char pos- "msgid \"" ++ str ++ "\"",- "msgstr \"" ++ str ++ "\""- ]+ runIO $ appendFile potFileName $ unlines $ poEntry loc str let trans = TL.toStrict $ G.gettext catalog (packStr str) [| trans |] -gettext :: QuasiQuoter-gettext = QuasiQuoter- { quoteExp = gettextQ- , quotePat = error "Usage as a parttern is not supported"- , quoteType = error "Usage as a type is not supported"- , quoteDec = error "Usage as a decl is not supported"-- }--__ :: QuasiQuoter-__ = gettext-+poEntry :: Loc -> String -> [String]+poEntry loc msg = [+ "",+ "#: " ++ (loc_filename loc) ++ ":0", -- TODO line nr or char pos+ "msgid " ++ show msg,+ "msgstr " ++ show msg + ] gettextsDecs :: String -> Q [Dec] gettextsDecs str = do createPotFile loc <- location let msgs = map splitKeyMsg $ parseLines str - runIO $ appendFile potFileName $ unlines $ concat [[- "",- "#: " ++ (loc_filename loc) ++ ":0", -- TODO line nr or char pos- "msgid " ++ show msg,- "msgstr " ++ show msg - ] | (_, msg) <- msgs ] + runIO $ appendFile potFileName $ unlines $ concat [ poEntry loc msg | (_, msg) <- msgs ] forM msgs $ \ (key, msg) -> let trans = TL.toStrict $ G.gettext catalog (packStr msg) in do@@ -138,8 +123,9 @@ if all isSpace line then go acc lines' else collect (join acc) [line] lines' collect :: ([String] -> [String]) -> [String] -> [String] -> [String]- collect j cl [] = go (j cl) [] - collect j cl lines'@(h@(c:d):t) =+ collect j cl [] = go (j cl) []+ collect j cl ([]:t) = go (j cl) t+ collect j cl lines'@((c:d):t) = if isSpace c then collect j ((dropWhile isSpace d):cl) t else go (j cl) lines' join acc cl = (intercalate "\n" $ reverse cl):acc@@ -153,10 +139,14 @@ where f = reverse . dropWhile isSpace -gettexts :: QuasiQuoter-gettexts = QuasiQuoter- { quoteExp = error "Usage as a decl is not supported" +gettext :: QuasiQuoter+gettext = QuasiQuoter+ { quoteExp = gettextQ , quotePat = error "Usage as a parttern is not supported" , quoteType = error "Usage as a type is not supported" , quoteDec = gettextsDecs }++__ :: QuasiQuoter+__ = gettext+