Prepare for selecting languages

UI language is stored in user settings for authenticated users;
otherwise is only stored in the current model (not persisted).
This commit is contained in:
Eike Kettner 2021-03-27 22:00:50 +01:00
parent 9fcab84267
commit 322a3e837c
10 changed files with 335 additions and 1 deletions

View File

@ -2,6 +2,7 @@ module App.Data exposing
( Model
, Msg(..)
, defaultPage
, getUiLanguage
, init
)
@ -24,6 +25,7 @@ import Page.Queue.Data
import Page.Register.Data
import Page.Upload.Data
import Page.UserSettings.Data
import UiLanguage exposing (UiLanguage)
import Url exposing (Url)
@ -48,6 +50,8 @@ type alias Model =
, uiSettings : UiSettings
, sidebarVisible : Bool
, anonymousTheme : UiTheme
, anonymousUiLang : UiLanguage
, langMenuOpen : Bool
}
@ -97,6 +101,8 @@ init key url flags_ settings =
, uiSettings = settings
, sidebarVisible = settings.sideMenuVisible
, anonymousTheme = Data.UiTheme.Light
, anonymousUiLang = UiLanguage.English
, langMenuOpen = False
}
, Cmd.batch
[ Cmd.map UserSettingsMsg uc
@ -152,8 +158,20 @@ type Msg
| GetUiSettings UiSettings
| ToggleSidebar
| ToggleDarkMode
| ToggleLangMenu
| SetLanguage UiLanguage
defaultPage : Flags -> Page
defaultPage flags =
HomePage
getUiLanguage : Model -> UiLanguage
getUiLanguage model =
case model.flags.account of
Just _ ->
model.uiSettings.uiLang
Nothing ->
model.anonymousUiLang

View File

@ -84,6 +84,15 @@ updateWithSub msg model =
, Sub.none
)
ToggleLangMenu ->
( { model | langMenuOpen = not model.langMenuOpen }
, Cmd.none
, Sub.none
)
SetLanguage lang ->
( { model | anonymousUiLang = lang, langMenuOpen = False }, Cmd.none, Sub.none )
HomeMsg lm ->
updateHome lm model

View File

@ -7,6 +7,7 @@ import Data.Flags
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
import Messages
import Page exposing (Page(..))
import Page.CollectiveSettings.View2 as CollectiveSettings
import Page.Home.Data
@ -20,6 +21,7 @@ import Page.Register.View2 as Register
import Page.Upload.View2 as Upload
import Page.UserSettings.View2 as UserSettings
import Styles as S
import UiLanguage
view : Model -> List (Html Msg)
@ -64,13 +66,18 @@ topNavUser auth model =
topNavAnon : Model -> Html Msg
topNavAnon model =
let
texts =
Messages.get <| App.Data.getUiLanguage model
in
nav
[ id "top-nav"
, class styleTopNav
]
[ headerNavItem model
, div [ class "flex flex-grow justify-end" ]
[ a
[ langMenu model
, a
[ href "#"
, onClick ToggleDarkMode
, class dropdownLink
@ -100,6 +107,10 @@ headerNavItem model =
mainContent : Model -> Html Msg
mainContent model =
let
texts =
Messages.get <| App.Data.getUiLanguage model
in
div
[ id "main"
, class styleMain
@ -151,6 +162,45 @@ styleMain =
"mt-12 flex md:flex-row flex-col w-full h-screen-12 overflow-y-hidden bg-white dark:bg-bluegray-800 text-gray-800 dark:text-bluegray-300 antialiased"
langMenu : Model -> Html Msg
langMenu model =
let
texts =
Messages.get <| App.Data.getUiLanguage model
langItem lang =
let
langMsg =
Messages.get lang
in
a
[ classList
[ ( dropdownItem, True )
, ( "bg-gray-200 dark:bg-bluegray-700", lang == texts.lang )
]
, onClick (SetLanguage lang)
, href "#"
]
[ i [ langMsg |> .flagIcon |> class ] []
, span [ class "ml-2" ] [ text langMsg.label ]
]
in
div [ class "relative" ]
[ a
[ class dropdownLink
, onClick ToggleLangMenu
, href "#"
]
[ i [ class texts.flagIcon ] []
]
, div
[ class dropdownMenu
, classList [ ( "hidden", not model.langMenuOpen ) ]
]
(List.map langItem UiLanguage.all)
]
dataMenu : AuthResult -> Model -> Html Msg
dataMenu _ model =
div [ class "relative" ]

View File

@ -11,11 +11,13 @@ import Api.Model.TagList exposing (TagList)
import Comp.BasicSizeField
import Comp.ColorTagger
import Comp.FieldListSelect
import Comp.FixedDropdown
import Comp.IntField
import Comp.MenuBar as MB
import Comp.Tabs
import Data.BasicSize exposing (BasicSize)
import Data.Color exposing (Color)
import Data.DropdownStyle as DS
import Data.Fields exposing (Field)
import Data.Flags exposing (Flags)
import Data.ItemTemplate as IT exposing (ItemTemplate)
@ -26,8 +28,10 @@ import Html.Attributes exposing (..)
import Html.Events exposing (onClick, onInput)
import Http
import Markdown
import Messages
import Set exposing (Set)
import Styles as S
import UiLanguage exposing (UiLanguage)
import Util.Maybe
import Util.Tag
@ -56,6 +60,8 @@ type alias Model =
, searchStatsVisible : Bool
, sideMenuVisible : Bool
, powerSearchEnabled : Bool
, uiLangModel : Comp.FixedDropdown.Model UiLanguage
, uiLang : UiLanguage
, openTabs : Set String
}
@ -148,6 +154,10 @@ init flags settings =
, searchStatsVisible = settings.searchStatsVisible
, sideMenuVisible = settings.sideMenuVisible
, powerSearchEnabled = settings.powerSearchEnabled
, uiLang = settings.uiLang
, uiLangModel =
List.map langItem UiLanguage.all
|> Comp.FixedDropdown.init
, openTabs = Set.empty
}
, Api.getTags flags "" GetTagsResp
@ -174,6 +184,15 @@ type Msg
| ToggleAkkordionTab String
| ToggleSideMenuVisible
| TogglePowerSearch
| UiLangMsg (Comp.FixedDropdown.Msg UiLanguage)
langItem : UiLanguage -> Comp.FixedDropdown.Item UiLanguage
langItem lang =
{ id = lang
, display = Messages.get lang |> .label
, icon = Just (Messages.get lang |> .flagIcon)
}
@ -445,6 +464,22 @@ update sett msg model =
, Just { sett | powerSearchEnabled = next }
)
UiLangMsg lm ->
let
( m, sel ) =
Comp.FixedDropdown.update lm model.uiLangModel
newLang =
Maybe.withDefault model.uiLang sel
in
( { model | uiLangModel = m, uiLang = newLang }
, if newLang == model.uiLang then
Nothing
else
Just { sett | uiLang = newLang }
)
--- View2
@ -494,6 +529,15 @@ settingFormTabs flags _ model =
, value = model.sideMenuVisible
}
]
, div [ class "mb-4" ]
[ label [ class S.inputLabel ] [ text "UI Language" ]
, Html.map UiLangMsg
(Comp.FixedDropdown.viewStyled2 DS.mainStyle
False
(Just <| langItem model.uiLang)
model.uiLangModel
)
]
]
}
, { title = "Item Search"

View File

@ -32,6 +32,8 @@ import Data.UiTheme exposing (UiTheme)
import Dict exposing (Dict)
import Html exposing (Attribute)
import Html.Attributes as HA
import Messages
import UiLanguage exposing (UiLanguage)
{-| Settings for the web ui. All fields should be optional, since it
@ -63,6 +65,7 @@ type alias StoredUiSettings =
, uiTheme : Maybe String
, sideMenuVisible : Bool
, powerSearchEnabled : Bool
, uiLang : Maybe String
}
@ -94,6 +97,7 @@ type alias UiSettings =
, uiTheme : UiTheme
, sideMenuVisible : Bool
, powerSearchEnabled : Bool
, uiLang : UiLanguage
}
@ -165,6 +169,7 @@ defaults =
, uiTheme = Data.UiTheme.Light
, sideMenuVisible = True
, powerSearchEnabled = False
, uiLang = UiLanguage.English
}
@ -217,6 +222,9 @@ merge given fallback =
|> Maybe.withDefault fallback.uiTheme
, sideMenuVisible = given.sideMenuVisible
, powerSearchEnabled = given.powerSearchEnabled
, uiLang =
Maybe.map Messages.fromIso2 given.uiLang
|> Maybe.withDefault UiLanguage.English
}
@ -254,6 +262,7 @@ toStoredUiSettings settings =
, uiTheme = Just (Data.UiTheme.toString settings.uiTheme)
, sideMenuVisible = settings.sideMenuVisible
, powerSearchEnabled = settings.powerSearchEnabled
, uiLang = Just <| Messages.toIso2 settings.uiLang
}

View File

@ -0,0 +1,87 @@
module Messages exposing
( Messages
, fromIso2
, get
, toIso2
)
import Messages.App
import Messages.LoginPage
import UiLanguage exposing (UiLanguage(..))
{-| The messages record contains all strings used in the application.
-}
type alias Messages =
{ lang : UiLanguage
, iso2 : String
, label : String
, flagIcon : String
, app : Messages.App.Texts
, login : Messages.LoginPage.Texts
}
get : UiLanguage -> Messages
get lang =
case lang of
English ->
gb
German ->
de
{-| Get a ISO-3166-1 code of the given lanugage.
-}
toIso2 : UiLanguage -> String
toIso2 lang =
get lang |> .iso2
{-| Return the UiLanguage from given iso2 code. If the iso2 code is not
known, return Nothing.
-}
readIso2 : String -> Maybe UiLanguage
readIso2 iso =
let
isIso lang =
iso == toIso2 lang
in
List.filter isIso UiLanguage.all
|> List.head
{-| return the language from the given iso2 code. if the iso2 code is
not known, return English as a default.
-}
fromIso2 : String -> UiLanguage
fromIso2 iso =
readIso2 iso
|> Maybe.withDefault English
--- Messages Definitions
gb : Messages
gb =
{ lang = English
, iso2 = "gb"
, label = "English"
, flagIcon = "flag-icon flag-icon-gb"
, app = Messages.App.gb
, login = Messages.LoginPage.gb
}
de : Messages
de =
{ lang = German
, iso2 = "de"
, label = "Deutsch"
, flagIcon = "flag-icon flag-icon-de"
, app = Messages.App.de
, login = Messages.LoginPage.de
}

View File

@ -0,0 +1,22 @@
module Messages.App exposing
( Texts
, de
, gb
)
type alias Texts =
{ login : String
}
gb : Texts
gb =
{ login = "Login"
}
de : Texts
de =
{ login = "Anmelden"
}

View File

@ -0,0 +1,22 @@
module Messages.FixedDropdown exposing
( Texts
, de
, gb
)
type alias Texts =
{ select : String
}
gb : Texts
gb =
{ select = "Select"
}
de : Texts
de =
{ select = "Auswahl"
}

View File

@ -0,0 +1,57 @@
module Messages.LoginPage exposing
( Texts
, de
, fr
, gb
)
type alias Texts =
{ username : String
, password : String
, loginPlaceholder : String
, passwordPlaceholder : String
, loginButton : String
, loginSuccessful : String
, noAccount : String
, signupLink : String
}
gb : Texts
gb =
{ username = "Username"
, password = "Password"
, loginPlaceholder = "Login"
, passwordPlaceholder = "Password"
, loginButton = "Login"
, loginSuccessful = "Login successful"
, noAccount = "No account?"
, signupLink = "Sign up!"
}
de : Texts
de =
{ username = "Benutzer"
, password = "Passwort"
, loginPlaceholder = "Benutzer"
, passwordPlaceholder = "Passwort"
, loginButton = "Anmelden"
, loginSuccessful = "Anmeldung erfolgreich"
, noAccount = "Kein Konto?"
, signupLink = "Hier registrieren!"
}
fr : Texts
fr =
{ username = "Identifiant"
, password = "Mot de passe"
, loginPlaceholder = "Utilisateur"
, passwordPlaceholder = "Mot de passe"
, loginButton = "Connexion"
, loginSuccessful = "Identification réussie"
, noAccount = "Pas de compte ?"
, signupLink = "S'inscrire"
}

View File

@ -0,0 +1,16 @@
module UiLanguage exposing
( UiLanguage(..)
, all
)
type UiLanguage
= English
| German
all : List UiLanguage
all =
[ English
, German
]