feat(i18n): populate frontend datetime locale from backend settings
This commit is contained in:
parent
83a458ddf5
commit
498d6168a0
@ -1,3 +1,5 @@
|
|||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* I18n
|
* I18n
|
||||||
*
|
*
|
||||||
@ -13,10 +15,15 @@
|
|||||||
|
|
||||||
export class I18n {
|
export class I18n {
|
||||||
|
|
||||||
translations = {};
|
_translations = {};
|
||||||
|
_datetimeLocale = undefined;
|
||||||
|
|
||||||
add(id, translation) {
|
add(id, translation) {
|
||||||
this.translations[id] = translation;
|
if (!this._translations[id]) {
|
||||||
|
this._translations[id] = translation;
|
||||||
|
} else {
|
||||||
|
throw new Error('I18N Error: Attempting to set translation multiple times for »' + id + '«!');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addMany(manyTranslations) {
|
addMany(manyTranslations) {
|
||||||
@ -24,9 +31,27 @@ export class I18n {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(id) {
|
get(id) {
|
||||||
if (!this.translations[id]) {
|
if (!this._translations[id]) {
|
||||||
throw new Error('I18N Error: Translation missing for »' + id + '«!');
|
throw new Error('I18N Error: Translation missing for »' + id + '«!');
|
||||||
}
|
}
|
||||||
return this.translations[id];
|
return this._translations[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setDatetimeLocale(locale) {
|
||||||
|
if (!this._datetimeLocale) {
|
||||||
|
moment.locale(locale);
|
||||||
|
this._datetimeLocale = locale;
|
||||||
|
} else {
|
||||||
|
throw new Error('I18N Error: Attempting to set datetime locale multiple times!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDatetimeLocale() {
|
||||||
|
if (!this._datetimeLocale) {
|
||||||
|
throw new Error('I18N Error: Attempting to access datetime locale when it has not been set!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._datetimeLocale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,9 +48,6 @@ const DATEPICKER_CONFIG = {
|
|||||||
timeMinutes: 0,
|
timeMinutes: 0,
|
||||||
timeSeconds: 0,
|
timeSeconds: 0,
|
||||||
|
|
||||||
// german settings
|
|
||||||
// TODO: hardcoded, get from current language / settings
|
|
||||||
locale: 'de',
|
|
||||||
weekStart: 1,
|
weekStart: 1,
|
||||||
dateFormat: FORM_DATE_FORMAT_DATE_DT,
|
dateFormat: FORM_DATE_FORMAT_DATE_DT,
|
||||||
timeFormat: FORM_DATE_FORMAT_TIME_DT,
|
timeFormat: FORM_DATE_FORMAT_TIME_DT,
|
||||||
@ -86,6 +83,7 @@ export class Datepicker {
|
|||||||
datepickerInstance;
|
datepickerInstance;
|
||||||
_element;
|
_element;
|
||||||
elementType;
|
elementType;
|
||||||
|
_locale;
|
||||||
|
|
||||||
constructor(element) {
|
constructor(element) {
|
||||||
if (!element) {
|
if (!element) {
|
||||||
@ -96,6 +94,8 @@ export class Datepicker {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._locale = window.App.i18n.getDatetimeLocale();
|
||||||
|
|
||||||
// initialize datepickerCollections singleton if not already done
|
// initialize datepickerCollections singleton if not already done
|
||||||
if (!Datepicker.datepickerCollections) {
|
if (!Datepicker.datepickerCollections) {
|
||||||
Datepicker.datepickerCollections = new Map();
|
Datepicker.datepickerCollections = new Map();
|
||||||
@ -134,7 +134,7 @@ export class Datepicker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initialize tail.datetime (datepicker) instance and let it do weird stuff with the element value
|
// initialize tail.datetime (datepicker) instance and let it do weird stuff with the element value
|
||||||
this.datepickerInstance = datetime(this._element, { ...datepickerGlobalConfig, ...datepickerConfig });
|
this.datepickerInstance = datetime(this._element, { ...datepickerGlobalConfig, ...datepickerConfig, locale: this._locale });
|
||||||
|
|
||||||
// reset date to something sane
|
// reset date to something sane
|
||||||
if (parsedMomentDate)
|
if (parsedMomentDate)
|
||||||
|
|||||||
@ -1930,6 +1930,7 @@ siteLayout' headingOverride widget = do
|
|||||||
let
|
let
|
||||||
-- See Utils.Frontend.I18n and files in messages/frontend for message definitions
|
-- See Utils.Frontend.I18n and files in messages/frontend for message definitions
|
||||||
frontendI18n = toJSON (mr :: FrontendMessage -> Text)
|
frontendI18n = toJSON (mr :: FrontendMessage -> Text)
|
||||||
|
frontendDatetimeLocale <- toJSON <$> selectLanguage frontendDatetimeLocales
|
||||||
|
|
||||||
pc <- widgetToPageContent $ do
|
pc <- widgetToPageContent $ do
|
||||||
-- fonts
|
-- fonts
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
module Utils.Frontend.I18n
|
module Utils.Frontend.I18n
|
||||||
( FrontendMessage(..)
|
( FrontendMessage(..)
|
||||||
|
, frontendDatetimeLocales
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import ClassyPrelude
|
import ClassyPrelude
|
||||||
@ -14,6 +15,9 @@ import Data.Aeson.Types (toJSONKeyText)
|
|||||||
import Data.Aeson.TH
|
import Data.Aeson.TH
|
||||||
import qualified Data.Char as Char
|
import qualified Data.Char as Char
|
||||||
|
|
||||||
|
import Data.List.NonEmpty (NonEmpty(..))
|
||||||
|
import Text.Shakespeare.I18N (Lang)
|
||||||
|
|
||||||
|
|
||||||
-- | I18n-Messages used in JavaScript-Frontend
|
-- | I18n-Messages used in JavaScript-Frontend
|
||||||
--
|
--
|
||||||
@ -39,3 +43,7 @@ instance ToJSONKey FrontendMessage where
|
|||||||
toJSONKey = toJSONKeyText toPathPiece
|
toJSONKey = toJSONKeyText toPathPiece
|
||||||
instance FromJSONKey FrontendMessage where
|
instance FromJSONKey FrontendMessage where
|
||||||
fromJSONKey = FromJSONKeyTextParser $ parseJSON . String
|
fromJSONKey = FromJSONKeyTextParser $ parseJSON . String
|
||||||
|
|
||||||
|
|
||||||
|
frontendDatetimeLocales :: NonEmpty Lang
|
||||||
|
frontendDatetimeLocales = "de" :| ["en"]
|
||||||
|
|||||||
@ -11,8 +11,6 @@ import qualified Data.List as List
|
|||||||
|
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|
||||||
import Control.Lens (none)
|
|
||||||
|
|
||||||
import Yesod.Core.Types (HandlerData(handlerRequest), YesodRequest(reqLangs))
|
import Yesod.Core.Types (HandlerData(handlerRequest), YesodRequest(reqLangs))
|
||||||
import qualified Network.Wai.Parse as NWP
|
import qualified Network.Wai.Parse as NWP
|
||||||
|
|
||||||
@ -41,7 +39,7 @@ selectLanguages avL (l:ls)
|
|||||||
, l'' <- matchesFor l'
|
, l'' <- matchesFor l'
|
||||||
, langMatches lParts' l''
|
, langMatches lParts' l''
|
||||||
]
|
]
|
||||||
= let now = nonEmpty . filter (\l' -> none (((==) `on` CI.mk) l') ls) $ sortOn (Down . length) found
|
= let now = nonEmpty $ sortOn (Down . length) found
|
||||||
others = selectLanguages avL ls
|
others = selectLanguages avL ls
|
||||||
in maybe id (\now' others' -> NonEmpty.fromList $ toList now' ++ filter (`notElem` toList now') (toList others')) now others
|
in maybe id (\now' others' -> NonEmpty.fromList $ toList now' ++ filter (`notElem` toList now') (toList others')) now others
|
||||||
| otherwise = selectLanguages avL ls
|
| otherwise = selectLanguages avL ls
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
if (window.App) {
|
if (window.App) {
|
||||||
window.App.i18n.addMany(#{frontendI18n});
|
window.App.i18n.addMany(#{frontendI18n});
|
||||||
// window.App.i18n.setLang(lang); TODO: set language string for datepicker config
|
window.App.i18n.setDatetimeLocale(#{frontendDatetimeLocale});
|
||||||
} else {
|
} else {
|
||||||
throw new Error('I18n JavaScript service is missing!');
|
throw new Error('I18n JavaScript service is missing!');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user