From c50beaf39632622f93f4c394b46a0167a7859f23 Mon Sep 17 00:00:00 2001 From: Adrian Cochrane Date: Wed, 10 Jan 2024 15:52:07 +1300 Subject: [PATCH] Start integrating internationalization infrastructure! --- src/Text/HTML/Form.hs | 7 +++-- src/Text/HTML/Form/Colours.hs | 52 ++++++++++++++++++----------------- src/Text/HTML/Form/I18n.hs | 6 ++-- src/Text/HTML/Form/WebApp.hs | 7 +++-- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/Text/HTML/Form.hs b/src/Text/HTML/Form.hs index c147b69..f957148 100644 --- a/src/Text/HTML/Form.hs +++ b/src/Text/HTML/Form.hs @@ -39,7 +39,9 @@ data Form = Form { -- | The purpose of this form, typically using an external vocabulary. rel :: Text, -- | What data should be sent to the endpoint. - inputs :: [Input] + inputs :: [Input], + -- | Which human language the form is written? To which additional messages should be localized? + lang :: String } -- | Individual piece of data to send to a webservice. @@ -199,7 +201,8 @@ parseElement el | _:_ <- laxElement "form" el = Just Form { autocomplete = hasAttr "autocomplete" el, formName = attr "name" el "", rel = attr "rel" el "", - inputs = mapMaybe parseInput $ queryInputs el + inputs = mapMaybe parseInput $ queryInputs el, + lang = Txt.unpack $ attr "lang" el "en" } | otherwise = Nothing diff --git a/src/Text/HTML/Form/Colours.hs b/src/Text/HTML/Form/Colours.hs index cd53282..0f1f23c 100644 --- a/src/Text/HTML/Form/Colours.hs +++ b/src/Text/HTML/Form/Colours.hs @@ -2,6 +2,8 @@ -- for where we can't provide free-form colour selection. module Text.HTML.Form.Colours(tailwindColours, Colour) where +import Text.HTML.Form.I18n (i18n) + -- Finally a good use for Tailwind! -- Otherwise it strikes me as little more than an illegible alternative to -- the `style` attribute! @@ -9,75 +11,75 @@ module Text.HTML.Form.Colours(tailwindColours, Colour) where -- | Stores a CSS hexcode, with preceding "#" type Colour = String -- | The Tailwind colour pallet: https://v1.tailwindcss.com/docs/customizing-colors#default-color-palette -tailwindColours :: [(String, [(Int, Colour)])] -tailwindColours = [ - "Slate"~>[50~>"#f8fafc", 100~>"#f1f5f9", 200~>"#e2e8f0", 300~>"#cbd5e1", +tailwindColours :: String -> [(String, [(Int, Colour)])] +tailwindColours lang = [ + i "Slate"~>[50~>"#f8fafc", 100~>"#f1f5f9", 200~>"#e2e8f0", 300~>"#cbd5e1", 400~>"#94a3b8", 500~>"#64748b", 600~>"#475569", 700~>"#334155", 800~>"#1e293b", 900~>"#0f172a", 950~>"#020617"], - "Gray"~>[50~>"#f9fafb", 100~>"#f3f4f6", 200~>"#e5e7eb", 300~>"#d1d5db", + i "Gray"~>[50~>"#f9fafb", 100~>"#f3f4f6", 200~>"#e5e7eb", 300~>"#d1d5db", 400~>"#9ca3af", 500~>"#6b7280", 600~>"#4b5563", 700~>"#374151", 800~>"#1f2937", 900~>"#111827", 950~>"#030712"], - "Zinc"~>[50~>"#fafafa", 100~>"#f4f4f5", 200~>"#e4e4e7", 300~>"#d4d4d8", + i "Zinc"~>[50~>"#fafafa", 100~>"#f4f4f5", 200~>"#e4e4e7", 300~>"#d4d4d8", 400~>"#a1a1aa", 500~>"#71717a", 600~>"#52525b", 700~>"#3f3f46", 800~>"#27272a", 900~>"#18181b", 950~>"#09090b"], - "Neutral"~>[50~>"#fafafa", 100~>"#f5f5f5", 200~>"#e5e5e5", 300~>"#d4d4d4", + i "Neutral"~>[50~>"#fafafa", 100~>"#f5f5f5", 200~>"#e5e5e5", 300~>"#d4d4d4", 400~>"#a3a3a3", 500~>"#737373", 600~>"#404040", 700~>"#404040", 800~>"#262626", 900~>"#171717", 950~>"#0a0a0a"], - "Stone"~>[50~>"#fafaf9", 100~>"#f5f5f4", 200~>"#e7e5e4", 300~>"#d6d3d1", + i "Stone"~>[50~>"#fafaf9", 100~>"#f5f5f4", 200~>"#e7e5e4", 300~>"#d6d3d1", 400~>"#a8a29e", 500~>"#78716c", 600~>"#57534e", 700~>"#44403c", 800~>"#292524", 900~>"#1c1917", 950~>"#0c0a09"], - "Red"~>[50~>"#fef2f2", 100~>"#fee2e2", 200~>"#fecaca", 300~>"#fca5a5", + i "Red"~>[50~>"#fef2f2", 100~>"#fee2e2", 200~>"#fecaca", 300~>"#fca5a5", 400~>"#f87171", 500~>"#ef4444", 600~>"#dc2626", 700~>"#b91c1c", 800~>"#991b1b", 900~>"#7f1d1d", 950~>"#450a0a"], - "Orange"~>[50~>"#fff7ed", 100~>"#ffedd5", 200~>"#fed7aa", 300~>"#fdba74", + i "Orange"~>[50~>"#fff7ed", 100~>"#ffedd5", 200~>"#fed7aa", 300~>"#fdba74", 400~>"#fb923c", 500~>"#f97316", 600~>"#ea580c", 700~>"#c2410c", 800~>"#9a3412", 900~>"#7c2d12", 950~>"#431407"], - "Amber"~>[50~>"#fffbeb", 100~>"#fef3c7", 200~>"#fde68a", 300~>"#fcd34d", + i "Amber"~>[50~>"#fffbeb", 100~>"#fef3c7", 200~>"#fde68a", 300~>"#fcd34d", 400~>"#fbbf24", 500~>"#f59e0b", 600~>"#d97706", 700~>"#b45309", 800~>"#92400e", 900~>"#78350f", 950~>"#451a03"], - "Yellow"~>[50~>"#fefce8", 100~>"#fef9c3", 200~>"#fef08a", 300~>"#fde047", + i "Yellow"~>[50~>"#fefce8", 100~>"#fef9c3", 200~>"#fef08a", 300~>"#fde047", 400~>"#facc15", 500~>"#eab308", 600~>"#ca8a04", 700~>"#a16207", 800~>"#854d0e", 900~>"#713f12", 950~>"#422006"], - "Lime"~>[50~>"#f7fee7", 100~>"#ecfccb", 200~>"#d9f99d", 300~>"#bef264", + i "Lime"~>[50~>"#f7fee7", 100~>"#ecfccb", 200~>"#d9f99d", 300~>"#bef264", 400~>"#a3e635", 500~>"#84cc16", 600~>"#65a30d", 700~>"#4d7c0f", 800~>"#3f6212", 900~>"#365314", 950~>"#1a2e05"], - "Green"~>[50~>"#f0fdf4", 100~>"#dcfce7", 200~>"#bbf7d0", 300~>"#86efac", + i "Green"~>[50~>"#f0fdf4", 100~>"#dcfce7", 200~>"#bbf7d0", 300~>"#86efac", 400~>"#4ade80", 500~>"#22c55e", 600~>"#16a34a", 700~>"#15803d", 800~>"#166534", 900~>"#14532d", 950~>"#052e16"], - "Emerald"~>[50~>"#ecfdf5", 100~>"#d1fae5", 200~>"#a7f3d0", 300~>"#6ee7b7", + i "Emerald"~>[50~>"#ecfdf5", 100~>"#d1fae5", 200~>"#a7f3d0", 300~>"#6ee7b7", 400~>"#34d399", 500~>"#10b981", 600~>"#059669", 700~>"#047857", 800~>"#065f46", 900~>"#064e3b", 950~>"#022c22"], - "Teal"~>[50~>"#f0fdfa", 100~>"#ccfbf1", 200~>"#99f6e4", 300~>"#5eead4", + i "Teal"~>[50~>"#f0fdfa", 100~>"#ccfbf1", 200~>"#99f6e4", 300~>"#5eead4", 400~>"#2dd4bf", 500~>"#14b8a6", 600~>"#0f766e", 700~>"#0f766e", 800~>"#115e59", 900~>"#134e4a", 950~>"#042f2e"], - "Cyan"~>[50~>"#ecfeff", 100~>"#cffafe", 200~>"#a5f3fc", 300~>"#67e8f9", + i "Cyan"~>[50~>"#ecfeff", 100~>"#cffafe", 200~>"#a5f3fc", 300~>"#67e8f9", 400~>"#22d3ee", 500~>"#06b6d4", 600~>"#0891b2", 700~>"#0e7490", 800~>"#155e75", 900~>"#164e63", 950~>"#083344"], - "Sky"~>[50~>"#f0f9ff", 100~>"#e0f2fe", 200~>"#bae6fd", 300~>"#7dd3fc", + i "Sky"~>[50~>"#f0f9ff", 100~>"#e0f2fe", 200~>"#bae6fd", 300~>"#7dd3fc", 400~>"#38bdf8", 500~>"#0ea5e9", 600~>"#0284c7", 700~>"#0369a1", 800~>"#075985", 900~>"#0c4a6e", 950~>"#082f49"], - "Blue"~>[50~>"#eff6ff", 100~>"#dbeafe", 200~>"#bfdbfe", 300~>"#93c5fd", + i "Blue"~>[50~>"#eff6ff", 100~>"#dbeafe", 200~>"#bfdbfe", 300~>"#93c5fd", 400~>"#60a5fa", 500~>"#3b82f6", 600~>"#2563eb", 700~>"#1d4ed8", 800~>"#1e40af", 900~>"#1e3a8a", 950~>"#172554"], - "Indigo"~>[50~>"#eef2ff", 100~>"#e0e7ff", 200~>"#c7d2fe", 300~>"#a5b4fc", + i "Indigo"~>[50~>"#eef2ff", 100~>"#e0e7ff", 200~>"#c7d2fe", 300~>"#a5b4fc", 400~>"#818cf8", 500~>"#6366f1", 600~>"#4f46e5", 700~>"#4338ca", 800~>"#3730a3", 900~>"#312e81", 950~>"#1e1b4b"], - "Violet"~>[50~>"#f5f3ff", 100~>"#ede9fe", 200~>"#ddd6fe", 300~>"#c4b5fd", + i "Violet"~>[50~>"#f5f3ff", 100~>"#ede9fe", 200~>"#ddd6fe", 300~>"#c4b5fd", 400~>"#a78bfa", 500~>"#8b5cf6", 600~>"#7c3aed", 700~>"#6d28d9", 800~>"#5b21b6", 900~>"#4c1d95", 950~>"#2e1065"], - "Purple"~>[50~>"#faf5ff", 100~>"#f3e8ff", 200~>"#e9d5ff", 300~>"#d8b4fe", + i "Purple"~>[50~>"#faf5ff", 100~>"#f3e8ff", 200~>"#e9d5ff", 300~>"#d8b4fe", 400~>"#c084fc", 500~>"#a855f7", 600~>"#9333ea", 700~>"#7e22ce", 800~>"#6b21a8", 900~>"#581c87", 950~>"#3b0764"], - "Fuchsia"~>[50~>"#fdf4ff", 100~>"#fae8ff", 200~>"#f5d0fe", 300~>"#f0abfc", + i "Fuchsia"~>[50~>"#fdf4ff", 100~>"#fae8ff", 200~>"#f5d0fe", 300~>"#f0abfc", 400~>"#e879f9", 500~>"#d946ef", 600~>"#c026d3", 700~>"#a21caf", 800~>"#86198f", 900~>"#701a75", 950~>"#4a044e"], - "Pink"~>[50~>"#fdf2f8", 100~>"#fce7f3", 200~>"#fbcfe8", 300~>"#f9a8d4", + i "Pink"~>[50~>"#fdf2f8", 100~>"#fce7f3", 200~>"#fbcfe8", 300~>"#f9a8d4", 400~>"#f472b6", 500~>"#ec4899", 600~>"#db2777", 700~>"#be185d", 800~>"#9d174d", 900~>"#831843", 950~>"#500724"], - "Rose"~>[50~>"#fff1f2", 100~>"#ffe4e6", 200~>"#fecdd3", 300~>"#fda4af", + i "Rose"~>[50~>"#fff1f2", 100~>"#ffe4e6", 200~>"#fecdd3", 300~>"#fda4af", 400~>"#fb7185", 500~>"#f43f5e", 600~>"#e11d48", 700~>"#be123c", 800~>"#9f1239", 900~>"#881337", 950~>"#4c0519"] - ] + ] where i = i18n lang (~>) :: a -> b -> (a, b) a ~> b = (a, b) diff --git a/src/Text/HTML/Form/I18n.hs b/src/Text/HTML/Form/I18n.hs index 387b0b8..8106c5b 100644 --- a/src/Text/HTML/Form/I18n.hs +++ b/src/Text/HTML/Form/I18n.hs @@ -1,5 +1,5 @@ {-# LANGUAGE TemplateHaskell #-} -module Text.HTML.Form.I18n(strings, i18n, i18n', i18n2, stringsJSON) where +module Text.HTML.Form.I18n(strings, langs, i18n, i18n', i18n2, stringsJSON) where import Data.FileEmbed (embedDir, makeRelativeToProject) import Data.Text.Encoding (decodeUtf8Lenient) @@ -21,7 +21,9 @@ bs2str = unpack . decodeUtf8Lenient strings :: String -> [(String, String)] strings = fromMaybe [] . - lookup [(dropExtension k, parseKVs $ bs2str v) | (k, v) <- files] + flip lookup [(dropExtension k, parseKVs $ bs2str v) | (k, v) <- files] +langs :: [String] +langs = map dropExtension $ map fst files i18n :: String -> String -> String i18n lang key = fromMaybe key $ lookup key $ strings lang diff --git a/src/Text/HTML/Form/WebApp.hs b/src/Text/HTML/Form/WebApp.hs index 9a0fe05..1e61b65 100644 --- a/src/Text/HTML/Form/WebApp.hs +++ b/src/Text/HTML/Form/WebApp.hs @@ -182,18 +182,19 @@ renderInput f ix input@Input { inputType = ty, inputName = n } [] qs | isCalType _ -> toGVal () renderInput form ix input@Input { inputType = "color" } [] qs = template' "color.html" form ix input qs $ \x -> case x of - "colours" -> V.list $ L.map colourGVal tailwindColours + "colours" -> V.list $ L.map colourGVal $ tailwindColours $ lang form "shades" -> toGVal False "subfolder" -> toGVal False _ -> toGVal () renderInput form ix input@Input { inputType = "color" } [c, ""] qs = template' "color.html" form ix input qs $ \x -> case x of - "colours" -> V.list $ L.map colourGVal tailwindColours - "shades" -> case Txt.unpack c `lookup` tailwindColours of + "colours" -> V.list $ L.map colourGVal $ tailwindColours l + "shades" -> case Txt.unpack c `lookup` tailwindColours l of Just shades -> V.list $ L.map shadeGVal shades Nothing -> toGVal False "subfolder" -> toGVal True _ -> toGVal () + where l = lang form renderInput form ix input [keyboard] qs = renderInput form ix input [keyboard, ""] qs renderInput form ix input [keyboard, ""] qs | Just (Just _) <- resolveSource path = -- 2.30.2