From 0077e0b98af7b70e40dcf9c43b2360ee521d52b9 Mon Sep 17 00:00:00 2001 From: Astro Date: Fri, 10 Apr 2015 00:40:58 +0200 Subject: [PATCH] i18n support --- Foundation.hs | 34 +++++++++++ Handler/Buy.hs | 31 +++++----- Handler/CashCheck.hs | 6 +- Handler/Common.hs | 25 --------- Handler/Home.hs | 4 +- Handler/Modify.hs | 20 +++---- Handler/NewUser.hs | 22 ++++---- Handler/Payout.hs | 11 ++-- Handler/Restock.hs | 24 ++++---- Handler/Select.hs | 13 +++-- messages/de.msg | 75 +++++++++++++++++++++++++ templates/buy.hamlet | 6 +- templates/buyCash.hamlet | 6 +- templates/cashCheck.hamlet | 7 ++- templates/default-layout-wrapper.hamlet | 16 +----- templates/default-layout.hamlet | 22 +++++++- templates/home.hamlet | 6 +- templates/journal.hamlet | 21 +++---- templates/modify.hamlet | 2 +- templates/modifyUser.hamlet | 4 +- templates/newArticle.hamlet | 4 +- templates/newUser.hamlet | 4 +- templates/payout.hamlet | 6 +- templates/reactivate.hamlet | 2 +- templates/recharge.hamlet | 6 +- templates/restock.hamlet | 4 +- templates/select.hamlet | 8 +-- templates/selectCash.hamlet | 2 +- templates/summary.hamlet | 12 ++-- templates/upstock.hamlet | 6 +- 30 files changed, 248 insertions(+), 161 deletions(-) create mode 100644 messages/de.msg diff --git a/Foundation.hs b/Foundation.hs index 6443e2c..c751473 100644 --- a/Foundation.hs +++ b/Foundation.hs @@ -11,6 +11,32 @@ import Settings.StaticFiles --snip import qualified Data.Text as T import Network.Wai as Wai +import Data.List (tail) +import Data.List.Split +import Text.Printf + + +prependZero :: Text -> Text +prependZero t0 = if T.null t1 + then t1 + else if T.head t1 == '.' + then '0' `T.cons` t1 + else if "-." `T.isPrefixOf` t1 + then "-0." `T.append` (T.drop 2 t1) + else t1 + + where t1 = T.dropWhile ((==) ' ') t0 + +formatFloat :: Double -> Text +formatFloat d = T.pack (t ++ c) + where + t = reverse (intercalate "." $ chunksOf 3 $ reverse $ fst sp) + c = "," ++ tail (snd sp) + sp = (break (== '.') (printf "%.2f" d)) + -- T.pack . (splitEvery 3) . (printf "%,2f") + +formatIntCurrency :: Int -> Text +formatIntCurrency x = formatFloat $ ((fromIntegral x) / 100) -- | The foundation datatype for your application. This can be a good place to -- keep settings and values requiring initialization before your application @@ -27,6 +53,13 @@ data App = App instance HasHttpManager App where getHttpManager = appHttpManager +mkMessage "App" "messages" "de" + +renderMessage' e = do + m <- getYesod + l <- languages + return $ renderMessage m l e + -- This is where we define all of the routes in our application. For a full -- explanation of the syntax, please see: -- http://www.yesodweb.com/book/routing-and-handlers @@ -168,3 +201,4 @@ instance RenderMessage App FormMessage where -- https://github.com/yesodweb/yesod/wiki/Sending-email -- https://github.com/yesodweb/yesod/wiki/Serve-static-files-from-a-separate-domain -- https://github.com/yesodweb/yesod/wiki/i18n-messages-in-the-scaffolding + diff --git a/Handler/Buy.hs b/Handler/Buy.hs index 22b3bfe..fac9e45 100644 --- a/Handler/Buy.hs +++ b/Handler/Buy.hs @@ -16,7 +16,7 @@ getBuyR uId bId = do defaultLayout $ do $(widgetFile "buy") Nothing -> do - setMessage "Benutzer oder Artikel unbekannt" + setMessageI MsgUserOrArticleUnknown redirect $ HomeR postBuyR :: UserId -> BeverageId -> Handler Html @@ -38,19 +38,19 @@ postBuyR uId bId = do liftIO $ notifyUser user bev price master case sw of False -> do - setMessage "Viel Vergnügen" + setMessageI MsgPurchaseSuccess redirect $ HomeR True -> do - setMessage "Achtung: Guthaben im negativen Bereich" + setMessageI MsgPurchaseDebtful redirect $ HomeR True -> do - setMessage "So viele Artikel sind nicht vorhanden" + setMessageI MsgNotEnoughItems redirect $ BuyR uId bId _ -> do - setMessage "Etwas ist schief gelaufen" + setMessageI MsgErrorOccured redirect $ HomeR Nothing -> do - setMessage "Benutzer oder Artikel unbekannt" + setMessageI MsgUserUnknown redirect $ HomeR notifyUser :: User -> Beverage -> Int -> App -> IO () @@ -84,7 +84,7 @@ getBuyCashR bId = do defaultLayout $ do $(widgetFile "buyCash") Nothing -> do - setMessage "Getrank unbekannt" + setMessageI MsgItemUnknown redirect $ HomeR postBuyCashR :: BeverageId -> Handler Html @@ -102,20 +102,17 @@ postBuyCashR bId = do runDB $ update bId [BeverageAmount -=. quant] updateCashier price "Barzahlung" checkAlert bId - setMessage $ Content $ Text $ "Viel Vergnügen. Bitte Zahle " - `T.append` (formatIntCurrency price) - `T.append` " " - `T.append` (appCurrency $ appSettings master) - `T.append` " in die Kasse ein" - redirect $ HomeR + let currency = appCurrency $ appSettings master + setMessageI $ MsgPurchaseSuccessCash price currency + redirect HomeR True -> do - setMessage "So viele Artikel sind nicht vorhanden" + setMessageI MsgNotEnoughItems redirect $ BuyCashR bId _ -> do - setMessage "Etwas ist schief gelaufen" + setMessageI MsgItemDisappeared redirect $ HomeR Nothing -> do - setMessage "Artikel unbekannt" + setMessageI MsgItemUnknown redirect $ HomeR checkData :: UserId -> BeverageId -> Handler (Maybe (User, Beverage)) @@ -131,4 +128,4 @@ checkData uId bId = do buyForm :: Form Int buyForm = renderDivs - $ areq amountField "Anzahl" (Just 1) + $ areq amountField (fieldSettingsLabel MsgAmount) (Just 1) diff --git a/Handler/CashCheck.hs b/Handler/CashCheck.hs index f495de5..b1be930 100644 --- a/Handler/CashCheck.hs +++ b/Handler/CashCheck.hs @@ -15,13 +15,13 @@ postCashCheckR = do case res of FormSuccess c -> do runDB $ insert_ c - setMessage "Kassensturz durchgeführt. Kasse aktualisiert" + setMessageI MsgCashChecked redirect $ HomeR _ -> do - setMessage "Fehler im Kassensturz" + setMessageI MsgCashCheckError redirect $ CashCheckR createCashierForm :: Form Cashier createCashierForm = renderDivs $ Cashier - <$> areq currencyField "Gezählter Betrag" Nothing + <$> areq currencyField (fieldSettingsLabel MsgCountedValue) Nothing <*> lift (liftIO getCurrentTime) diff --git a/Handler/Common.hs b/Handler/Common.hs index eee3dd8..8749c2b 100644 --- a/Handler/Common.hs +++ b/Handler/Common.hs @@ -5,12 +5,9 @@ import Data.FileEmbed (embedFile) import qualified Data.Text as T import qualified Data.Text.Lazy.Encoding as E import qualified Data.Text.Read as R -import Data.List (tail) -import Data.List.Split import Yesod.Form.Functions import Text.Shakespeare.Text import Network.Mail.Mime -import Text.Printf import Import -- These handlers embed files in the executable at compile time to avoid a @@ -113,25 +110,3 @@ sendMail to subject body = , partContent = E.encodeUtf8 body }]] } - -prependZero :: Text -> Text -prependZero t0 = if T.null t1 - then t1 - else if T.head t1 == '.' - then '0' `T.cons` t1 - else if "-." `T.isPrefixOf` t1 - then "-0." `T.append` (T.drop 2 t1) - else t1 - - where t1 = T.dropWhile ((==) ' ') t0 - -formatFloat :: Double -> Text -formatFloat d = T.pack (t ++ c) - where - t = reverse (intercalate "." $ chunksOf 3 $ reverse $ fst sp) - c = "," ++ tail (snd sp) - sp = (break (== '.') (printf "%.2f" d)) - -- T.pack . (splitEvery 3) . (printf "%,2f") - -formatIntCurrency :: Int -> Text -formatIntCurrency x = formatFloat $ ((fromIntegral x) / 100) diff --git a/Handler/Home.hs b/Handler/Home.hs index ce3d2eb..70f68a7 100644 --- a/Handler/Home.hs +++ b/Handler/Home.hs @@ -39,8 +39,8 @@ getUserReactivateR uId = do time <- liftIO getCurrentTime secs <- return $ R.read $ formatTime defaultTimeLocale "%s" time runDB $ update uId [UserTimestamp =. secs] - setMessage "Nutzer reaktiviert" + setMessageI MsgUserReactivated redirect $ HomeR Nothing -> do - setMessage "Nutzer unbekannt" + setMessageI MsgUserUnknown redirect $ HomeR diff --git a/Handler/Modify.hs b/Handler/Modify.hs index 52398ef..4cc4cac 100644 --- a/Handler/Modify.hs +++ b/Handler/Modify.hs @@ -12,7 +12,7 @@ getModifyR bId = do defaultLayout $ do $(widgetFile "modify") Nothing -> do - setMessage "Artikel unbekannt" + setMessageI MsgItemUnknown redirect $ SummaryR postModifyR :: BeverageId -> Handler Html @@ -29,21 +29,21 @@ postModifyR bId = do , BeverageAmount =. beverageAmount nBev , BeverageAlertAmount =. beverageAlertAmount nBev ] - setMessage "Bearbeitung erfolgreich" + setMessageI MsgEditSuccess redirect $ SummaryR _ -> do - setMessage "Bearbeitung nicht möglich" + setMessageI MsgEditFail redirect $ SummaryR Nothing -> do - setMessage "Artikel unbekannt" + setMessageI MsgItemUnknown redirect $ SummaryR modifyForm :: Beverage -> Form Beverage modifyForm bev = renderDivs $ Beverage - <$> areq textField "Name" (Just $ beverageIdent bev) - <*> areq currencyField "Preis" (Just $ beveragePrice bev) - <*> areq amountField "aktueller Bestand" (Just $ beverageAmount bev) - <*> areq amountField "Meldebestand" (Just $ beverageAlertAmount bev) + <$> areq textField (fieldSettingsLabel MsgName) (Just $ beverageIdent bev) + <*> areq currencyField (fieldSettingsLabel MsgPrice) (Just $ beveragePrice bev) + <*> areq amountField (fieldSettingsLabel MsgCurrentStock) (Just $ beverageAmount bev) + <*> areq amountField (fieldSettingsLabel MsgAnnouncedStock) (Just $ beverageAlertAmount bev) getDeleteBeverageR :: BeverageId -> Handler Html getDeleteBeverageR bId = do @@ -51,8 +51,8 @@ getDeleteBeverageR bId = do case mBev of Just bev -> do runDB $ delete bId - setMessage "Artikel gelöscht" + setMessageI MsgItemDeleted redirect $ HomeR Nothing -> do - setMessage "Artikel unbekannt" + setMessageI MsgItemUnknown redirect $ HomeR diff --git a/Handler/NewUser.hs b/Handler/NewUser.hs index f4a2f84..83f834b 100644 --- a/Handler/NewUser.hs +++ b/Handler/NewUser.hs @@ -21,19 +21,19 @@ postNewUserR = do case res of FormSuccess user -> do _ <- runDB $ insert user - setMessage "Benutzer angelegt" + setMessageI MsgUserCreated redirect $ HomeR _ -> do - setMessage "Benutzer konnte nicht angelegt werden" + setMessageI MsgUserNotCreated redirect $ NewUserR newUserForm :: Int -> Form User newUserForm secs = renderDivs $ User - <$> areq textField "Nickname" Nothing + <$> areq textField (fieldSettingsLabel MsgName) Nothing <*> pure 0 <*> pure secs - <*> aopt emailField "E-mail" Nothing - <*> areq boolField "Benachrichtigung bei Kauf" (Just False) + <*> aopt emailField (fieldSettingsLabel MsgEmail) Nothing + <*> areq boolField (fieldSettingsLabel MsgBuyNotification) (Just False) data UserConf = UserConf { userConfEmail :: Maybe Text @@ -49,7 +49,7 @@ getModifyUserR uId = do defaultLayout $ do $(widgetFile "modifyUser") Nothing -> do - setMessage "Benutzer unbekannt" + setMessageI MsgUserUnknown redirect $ HomeR postModifyUserR :: UserId -> Handler Html @@ -65,19 +65,19 @@ postModifyUserR uId = do , UserNotify =. userConfNotify conf ] liftIO $ notify user conf - setMessage "Nutzerdaten aktualisiert" + setMessageI MsgUserEdited redirect $ SelectR uId _ -> do - setMessage "Nutzerdatenaktualisierung nicht erfolgreich" + setMessageI MsgUserNotEdited redirect $ SelectR uId Nothing -> do - setMessage "Nutzer unbekannt" + setMessageI MsgUserUnknown redirect $ HomeR modifyUserForm :: User -> Form UserConf modifyUserForm user = renderDivs $ UserConf - <$> aopt emailField "E-Mail" (Just $ userEmail user) - <*> areq boolField "Benachrichtigung bei Kauf" (Just $ userNotify user) + <$> aopt emailField (fieldSettingsLabel MsgEmail) (Just $ userEmail user) + <*> areq boolField (fieldSettingsLabel MsgBuyNotification) (Just $ userNotify user) notify :: User -> UserConf -> IO () notify user conf diff --git a/Handler/Payout.hs b/Handler/Payout.hs index e474ff5..fdf262f 100644 --- a/Handler/Payout.hs +++ b/Handler/Payout.hs @@ -20,14 +20,15 @@ postPayoutR = do ((res, _), _) <- runFormPost payoutForm case res of FormSuccess payment -> do - updateCashier (- (paymentAmount payment)) ("Auszahlung: " `T.append` paymentDesc payment) - setMessage "Betrag ausgezahlt" + msg <- renderMessage' $ MsgPayout $ paymentDesc payment + updateCashier (- (paymentAmount payment)) msg + setMessageI MsgPaidOut redirect $ HomeR _ -> do - setMessage "Auszahlung nicht möglich" + setMessageI MsgNotPaidOut redirect $ JournalR payoutForm :: Form Payment payoutForm = renderDivs $ Payment - <$> areq currencyField "Betrag" Nothing - <*> areq textField "Beschreibung" Nothing + <$> areq currencyField (fieldSettingsLabel MsgValue) Nothing + <*> areq textField (fieldSettingsLabel MsgDescription) Nothing diff --git a/Handler/Restock.hs b/Handler/Restock.hs index dc51628..df1cb7a 100644 --- a/Handler/Restock.hs +++ b/Handler/Restock.hs @@ -18,7 +18,7 @@ getUpstockR bId = do defaultLayout $ do $(widgetFile "upstock") Nothing -> do - setMessage "Artikel unbekannt" + setMessageI MsgItemUnknown redirect $ HomeR postUpstockR :: BeverageId -> Handler Html @@ -32,21 +32,21 @@ postUpstockR bId = do case c > 0 of True -> do runDB $ update bId [BeverageAmount +=. c] - setMessage "Bestand aufgefüllt" + setMessageI MsgStockedUp redirect $ HomeR False -> do - setMessage "Bestand kann nicht negativ aufgefüllt werden" + setMessageI MsgNotStockedUp redirect $ UpstockR bId _ -> do - setMessage "Fehler beim Auffüllen" + setMessageI MsgStockupError redirect $ UpstockR bId Nothing -> do - setMessage "Artikel unbekannt" + setMessageI MsgItemUnknown redirect $ HomeR upstockForm :: Form Int upstockForm = renderDivs - $ areq amountField "Anzahl hinzugefügt" (Just 0) + $ areq amountField (fieldSettingsLabel MsgAmountAdded) (Just 0) getNewArticleR :: Handler Html getNewArticleR = do @@ -60,15 +60,15 @@ postNewArticleR = do case result of FormSuccess bev -> do runDB $ insert_ bev - setMessage "Neuer Artikel hinzugefügt" + setMessageI MsgItemAdded redirect $ HomeR _ -> do - setMessage "Fehler beim Hinzufügen" + setMessageI MsgItemNotAdded redirect $ HomeR newArticleForm :: Form Beverage newArticleForm = renderDivs $ Beverage - <$> areq textField "Name" Nothing - <*> areq currencyField "Preis" (Just 100) - <*> areq amountField "Anzahl Elemente" (Just 0) - <*> areq amountField "Warnung bei Anzahl" (Just 0) + <$> areq textField (fieldSettingsLabel MsgName) Nothing + <*> areq currencyField (fieldSettingsLabel MsgPrice) (Just 100) + <*> areq amountField (fieldSettingsLabel MsgAmount) (Just 0) + <*> areq amountField (fieldSettingsLabel MsgAmountWarning) (Just 0) diff --git a/Handler/Select.hs b/Handler/Select.hs index bcb18d3..d6328fa 100644 --- a/Handler/Select.hs +++ b/Handler/Select.hs @@ -15,7 +15,7 @@ getSelectR uId = do defaultLayout $ do $(widgetFile "select") Nothing -> do - setMessage "Benutzer unbekannt" + setMessageI MsgUserUnknown redirect $ HomeR getSelectCashR :: Handler Html @@ -30,10 +30,11 @@ getRechargeR uId = do case mUser of Just user -> do (rechargeWidget, enctype) <- generateFormPost rechargeForm + currency <- appCurrency <$> appSettings <$> getYesod defaultLayout $ do $(widgetFile "recharge") Nothing -> do - setMessage "Benutzer unbekannt" + setMessageI MsgUserUnknown redirect $ HomeR postRechargeR :: UserId -> Handler Html @@ -48,15 +49,15 @@ postRechargeR uId = do time <- liftIO getCurrentTime secs <- return $ R.read $ formatTime defaultTimeLocale "%s" time runDB $ update uId [UserBalance +=. amount, UserTimestamp =. secs] - setMessage "Guthaben erfolgreich aufgeladen" + setMessageI MsgRecharged redirect $ HomeR _ -> do - setMessage "Fehler beim Aufladen" + setMessageI MsgRechargeError redirect $ HomeR Nothing -> do - setMessage "Benutzer unbekannt" + setMessageI MsgUserUnknown redirect $ HomeR rechargeForm :: Form Int rechargeForm = renderDivs - $ areq currencyField "Betrag" (Just 0) + $ areq currencyField (fieldSettingsLabel MsgValue) (Just 0) diff --git a/messages/de.msg b/messages/de.msg new file mode 100644 index 0000000..16d813e --- /dev/null +++ b/messages/de.msg @@ -0,0 +1,75 @@ +UserReactivated: Nutzer reaktiviert +UserUnknown: Nutzer unbekannt +UserOrArticleUnknown: Benutzer oder Artikel unbekannt +PurchaseSuccess: Viel Vergnügen +PurchaseDebtful: Achtung: Guthaben im negativen Bereich +NotEnoughItems: So viele Artikel sind nicht vorhanden +ErrorOccured: Etwas ist schief gelaufen +ItemUnknown: Artikel unbekannt +PurchaseSuccessCash price@Int currency@Text: Viel Vergnügen. Bitte Zahle #{formatIntCurrency price} #{currency} in die Kasse ein +ItemDisappeared: Artikel ist verschwunden o_0 +Amount: Anzahl +EditSuccess: Bearbeitung erfolgreich +EditFail: Bearbeitung nicht möglich +Name: Name +Price: Preis +CurrentStock: Aktueller Bestand +AnnouncedStock: Meldebestand +DeleteItem: Artikel löschen +ItemDeleted: Artikel gelöscht +UserCreated: Benutzer angelegt +UserNotCreated: Benutzer konnte nicht angelegt werden +Email: E-Mail +BuyNotification: Benachrichtigung bei Kauf +UserEdited: Nutzerdaten aktualisiert +UserNotEdited: Nutzerdatenaktualisierung nicht erfolgreich +Payout desc@Text: Auszahlung: #{desc} +PaidOut: Betrag ausgezahlt +NotPaidOut: Auszahlung nicht möglich +Value: Betrag +Description: Beschreibung +StockedUp: Bestand aufgefüllt +NotStockedUp: Bestand kann nicht negativ aufgefüllt werden +StockupError: Fehler beim Auffüllen +AmountAdded: Anzahl hinzugefügt +ItemAdded: Neuer Artikel hinzugefügt +ItemNotAdded: Fehler beim Hinzufügen +AmountWarning: Warnung bei Anzahl +Recharged: Guthaben erfolgreich aufgeladen +RechargeError: Fehler beim Aufladen +CashCheck: Kassensturz +CashChecked: Kassensturz durchgeführt. Kasse aktualisiert +CashCheckError: Fehler im Kassensturz +CountedValue: Gezählter Betrag +PurchaseOf name@Text: Kauf von #{name} +PricePerUnit price@Int currency@Text: Preis pro Einheit: #{formatIntCurrency price} #{currency} +Purchase: Kaufen +PleaseCountAndCheck: Bitte Kasse zählen und gezählten Betrag in unten stehendes Feld eintragen. +Submit: Absenden +Home: Nachhause +Restock: Lager befüllen +Journal: Journal +Summary: Inventar +PayCash: Bar bezahlen +CreateUser: Neuen Nutzer anlegen +ReactivateOldUser: Alten Nutzer reaktivieren +Time: Zeit +ValueIn currency@Text: Betrag in #{currency} +TotalValue: Gesamtbetrag +CashStock: Kassenbestand +PayoutFromCash: Aus der Kasse auszahlen +NothingToShow: Noch keine Bewegungen zu verzeichnen +NewItem: Neuer Artikel +NewUser: Neuer Benutzer +DoPayout: Auszahlen +ReactivateUser: Nutzer reaktivieren +Recharge: Guthaben aufladen +CurrentCharge charge@Int currency@Text: aktuelles Guthaben: #{formatIntCurrency charge} #{currency} +AddItem: neuen Artikel hinzufügen +EditUser: Nutzerdaten akutalisieren +ChoosePrompt text@Text: Wähle deinen Artikel, #{text} +SelectItem: Wähle deinen Artikel +CurrentAmount: Aktuelle Anzahl +NoItems: keine Getränke vorhanden +StockUp name@Text: Bestand von #{name} auffüllen +Fillup: Auffüllen \ No newline at end of file diff --git a/templates/buy.hamlet b/templates/buy.hamlet index 0f3e570..33a4a1d 100644 --- a/templates/buy.hamlet +++ b/templates/buy.hamlet @@ -1,11 +1,11 @@ $doctype 5 -

Kauf von #{beverageIdent bev} +

_{MsgPurchaseOf $ beverageIdent bev}

- Preis pro Einheit: #{formatIntCurrency (beveragePrice bev)} #{appCurrency $ appSettings master} + _{MsgPricePerUnit (beveragePrice bev) (appCurrency $ appSettings master)}

^{buyWidget}
- + diff --git a/templates/buyCash.hamlet b/templates/buyCash.hamlet index dff8077..2bbd360 100644 --- a/templates/buyCash.hamlet +++ b/templates/buyCash.hamlet @@ -1,11 +1,11 @@ $doctype 5 -

Kauf von #{beverageIdent bev} +

_{MsgPurchaseOf $ beverageIdent bev}

- Preis pro Einheit: #{formatIntCurrency (beveragePrice bev + 50)} #{appCurrency $ appSettings master} + _{MsgPricePerUnit (beveragePrice bev + 50) (appCurrency $ appSettings master)} ^{buyCashWidget}

- + diff --git a/templates/cashCheck.hamlet b/templates/cashCheck.hamlet index 088e09b..3f4bd48 100644 --- a/templates/cashCheck.hamlet +++ b/templates/cashCheck.hamlet @@ -1,11 +1,12 @@ $doctype 5 -

Kassensturz +

_{MsgCashCheck}

- Bitte Kasse zählen und gezählten Betrag in unten stehendes Feld eintragen. + _{MsgPleaseCountAndCheck} + ^{cashCheckWidget}

- + diff --git a/templates/default-layout-wrapper.hamlet b/templates/default-layout-wrapper.hamlet index cac91e3..a89dd1f 100644 --- a/templates/default-layout-wrapper.hamlet +++ b/templates/default-layout-wrapper.hamlet @@ -23,21 +23,7 @@ $newline never