From 656128a86a9920f84cba8e2aa8644ff7ea2e87fe Mon Sep 17 00:00:00 2001 From: styiannis <1515939+styiannis@users.noreply.github.com> Date: Sat, 17 Jul 2021 20:46:03 +0300 Subject: [PATCH] added languages menu options --- .../page-layout/PageHeader/HeaderRight.jsx | 77 +++++++++++++++---- .../PageHeader/LanguageOptions.scss | 39 ++++++++++ .../PageHeader/LanguageOptions.tsx | 65 ++++++++++++++++ .../page-layout/PageHeader/PageHeader.scss | 1 - .../static/js/utils/contexts/HeaderContext.js | 34 +++++--- 5 files changed, 189 insertions(+), 27 deletions(-) create mode 100644 frontend/src/static/js/components/page-layout/PageHeader/LanguageOptions.scss create mode 100644 frontend/src/static/js/components/page-layout/PageHeader/LanguageOptions.tsx diff --git a/frontend/src/static/js/components/page-layout/PageHeader/HeaderRight.jsx b/frontend/src/static/js/components/page-layout/PageHeader/HeaderRight.jsx index 8fe9fb6..ad1b6e7 100644 --- a/frontend/src/static/js/components/page-layout/PageHeader/HeaderRight.jsx +++ b/frontend/src/static/js/components/page-layout/PageHeader/HeaderRight.jsx @@ -13,8 +13,37 @@ import { UserThumbnail, } from '../../_shared'; import { HeaderThemeSwitcher } from './HeaderThemeSwitcher'; +import { LanguageOptions } from './LanguageOptions'; -function headerPopupPages(user, popupNavItems, hasHeaderThemeSwitcher) { +const OpenThemeSwitcher = () => { + const { t } = useTranslation(); + return ( +
+ + + arrow_back + + + {t('Switch theme')} +
+ ); +}; + +const OpenLanguageOptions = () => { + const { t } = useTranslation(); + return ( +
+ + + arrow_back + + + {t('Language')} +
+ ); +}; + +function headerPopupPages(user, popupNavItems, hasHeaderThemeSwitcher, hasTranslations) { const pages = { main: null, }; @@ -65,14 +94,7 @@ function headerPopupPages(user, popupNavItems, hasHeaderThemeSwitcher) { pages['switch-theme'] = (
-
- - - arrow_back - - - Switch theme -
+
@@ -81,15 +103,29 @@ function headerPopupPages(user, popupNavItems, hasHeaderThemeSwitcher) { ); } + if (hasTranslations) { + pages['language'] = ( +
+ + + + + + +
+ ); + } + return pages; } function UploadMediaButton({ user, links }) { + const { t } = useTranslation(); return !user.is.anonymous && user.can.addMedia ? (
- + - Upload media + {t('Upload media')}
) : null; @@ -106,9 +142,9 @@ function LoginButton({ user, link, hasHeaderThemeSwitcher }) { className={ 'button-link sign-in' + (hasHeaderThemeSwitcher ? ' hidden-only-in-small' : ' hidden-only-in-extra-small') } - title="{t('Sign in')}" + title="{t('SIGN IN')}" > - {t('Sign in')} + {t('SIGN IN')}
) : null; @@ -125,9 +161,9 @@ function RegisterButton({ user, link, hasHeaderThemeSwitcher }) { 'button-link register-link' + (hasHeaderThemeSwitcher ? ' hidden-only-in-small' : ' hidden-only-in-extra-small') } - title="{t('Register')}" + title="{t('REGISTER')}" > - {t('Register')} + {t('REGISTER')} ) : null; @@ -157,7 +193,9 @@ export function HeaderRight(props) {
@@ -173,7 +211,12 @@ export function HeaderRight(props) { diff --git a/frontend/src/static/js/components/page-layout/PageHeader/LanguageOptions.scss b/frontend/src/static/js/components/page-layout/PageHeader/LanguageOptions.scss new file mode 100644 index 0000000..07e87b3 --- /dev/null +++ b/frontend/src/static/js/components/page-layout/PageHeader/LanguageOptions.scss @@ -0,0 +1,39 @@ +@import '../../../../css/includes/_variables.scss'; +@import '../../../../css/includes/_variables_dimensions.scss'; + +.language-options { + position: relative; + width: 100%; + padding: 12px 0; +} + +.language-option { + display: block; + + button { + display: block; + width: 100%; + padding: 0 24px 0 64px; + line-height: 40px; + text-align: inherit; + color: inherit; + border: 0; + background: 0; + + .material-icons { + margin-right: 16px; + color: var(--header-popup-menu-icon-color); + } + + &:focus, + &:hover { + background-color: var(--in-popup-nav-menu-item-hover-bg-color); + } + } + + &.selected-language { + button { + padding-left: 24px; + } + } +} diff --git a/frontend/src/static/js/components/page-layout/PageHeader/LanguageOptions.tsx b/frontend/src/static/js/components/page-layout/PageHeader/LanguageOptions.tsx new file mode 100644 index 0000000..82b8f4e --- /dev/null +++ b/frontend/src/static/js/components/page-layout/PageHeader/LanguageOptions.tsx @@ -0,0 +1,65 @@ +import React, { useContext, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { BrowserCache } from '../../../utils/classes'; +import { SiteContext } from '../../../utils/contexts'; +import { enabled as langEnabled, labels as langLabels } from '../../../utils/languages'; +import { MaterialIcon } from '../../_shared'; + +import './LanguageOptions.scss'; + +interface LanguageOptionProps { + code: string; + label: string; + active: boolean; +} + +export const LanguageOption: React.FC = ({ code, label, active }) => { + const { i18n } = useTranslation(); + const onClick = () => i18n.changeLanguage(code); + return ( + + + + ); +}; + +export const LanguageOptions: React.FC = () => { + const site = useContext(SiteContext); + const [browserCache, setBrowserCache] = useState(null); + + const { i18n } = useTranslation(); + const [languages, setLanguages] = useState([]); + const [current, setCurrent] = useState(i18n.language); + + useEffect(() => { + // @ts-ignore + setBrowserCache(new BrowserCache('MediaCMS[' + site.id + '][language]', 86400)); + }, [site.id]); + + useEffect(() => { + setCurrent(i18n.language); + if (browserCache) { + // @ts-ignore + browserCache.set('code', i18n.language); + } + }, [i18n.language]); + + useEffect(() => { + const lang: string[] = []; + for (let k in langEnabled) { + lang.push(langEnabled[k]); + } + setLanguages(lang); + }, []); + + return ( +
+ {languages.map((code) => ( + + ))} +
+ ); +}; diff --git a/frontend/src/static/js/components/page-layout/PageHeader/PageHeader.scss b/frontend/src/static/js/components/page-layout/PageHeader/PageHeader.scss index 7d00ee1..21dc53a 100755 --- a/frontend/src/static/js/components/page-layout/PageHeader/PageHeader.scss +++ b/frontend/src/static/js/components/page-layout/PageHeader/PageHeader.scss @@ -196,7 +196,6 @@ $__button-link-horizontal-padding: 16; font-weight: 500; line-height: 1; display: block; - text-transform: uppercase; } .signin-icon-link { diff --git a/frontend/src/static/js/utils/contexts/HeaderContext.js b/frontend/src/static/js/utils/contexts/HeaderContext.js index 376609d..4f9c0a4 100644 --- a/frontend/src/static/js/utils/contexts/HeaderContext.js +++ b/frontend/src/static/js/utils/contexts/HeaderContext.js @@ -1,4 +1,5 @@ import React, { createContext } from 'react'; +import i18next from 'i18next'; import { config as mediacmsConfig } from '../settings/config.js'; const config = mediacmsConfig(window.MediaCMS); @@ -8,6 +9,7 @@ const theme = config.theme; const user = config.member; const hasThemeSwitcher = theme.switch.enabled && 'header' === theme.switch.position; +const hasTranslations = true; function popupTopNavItems() { const items = []; @@ -17,7 +19,7 @@ function popupTopNavItems() { items.push({ link: links.user.addMedia, icon: 'video_call', - text: 'Upload media', + text: i18next.t('Upload media'), itemAttr: { className: 'visible-only-in-small', }, @@ -27,7 +29,7 @@ function popupTopNavItems() { items.push({ link: user.pages.media, icon: 'video_library', - text: 'My media', + text: i18next.t('My media'), }); } } @@ -35,7 +37,7 @@ function popupTopNavItems() { items.push({ link: links.signout, icon: 'exit_to_app', - text: 'Sign out', + text: i18next.t('Sign out'), }); } @@ -50,7 +52,7 @@ function popupMiddleNavItems() { itemType: 'open-subpage', icon: 'brightness_4', iconPos: 'left', - text: 'Switch theme', + text: i18next.t('Switch theme'), buttonAttr: { className: 'change-page', 'data-page-id': 'switch-theme', @@ -58,6 +60,19 @@ function popupMiddleNavItems() { }); } + if (hasTranslations) { + items.push({ + itemType: 'open-subpage', + icon: 'language', + iconPos: 'left', + text: i18next.t('Language'), + buttonAttr: { + className: 'change-page', + 'data-page-id': 'language', + }, + }); + } + if (user.is.anonymous) { if (user.can.login) { items.push({ @@ -77,7 +92,7 @@ function popupMiddleNavItems() { itemType: 'link', icon: 'person_add', iconPos: 'left', - text: 'Register', + text: i18next.t('Register'), link: links.register, linkAttr: { className: hasThemeSwitcher ? 'visible-only-in-small' : 'visible-only-in-extra-small', @@ -88,14 +103,14 @@ function popupMiddleNavItems() { items.push({ link: links.user.editProfile, icon: 'brush', - text: 'Edit profile', + text: i18next.t('Edit profile'), }); if (user.can.changePassword) { items.push({ link: links.changePassword, icon: 'lock', - text: 'Change password', + text: i18next.t('Change password'), }); } } @@ -110,7 +125,7 @@ function popupBottomNavItems() { items.push({ link: links.admin, icon: 'admin_panel_settings', - text: 'MediaCMS administration', + text: `MediaCMS ${i18next.t('administration')}`, }); } @@ -119,6 +134,7 @@ function popupBottomNavItems() { export const HeaderContext = createContext({ hasThemeSwitcher, + hasTranslations, popupNavItems: { top: popupTopNavItems(), middle: popupMiddleNavItems(), @@ -126,4 +142,4 @@ export const HeaderContext = createContext({ }, }); -export const HeaderConsumer = HeaderContext.Consumer; \ No newline at end of file +export const HeaderConsumer = HeaderContext.Consumer;