lang-fix
This commit is contained in:
parent
22f45d8bd9
commit
bff5de0c8e
|
@ -1,4 +1,4 @@
|
||||||
import { useLocalize } from '../../../../context/localize'
|
import { useLocalize } from '~/context/localize'
|
||||||
import { Icon } from '../../../_shared/Icon'
|
import { Icon } from '../../../_shared/Icon'
|
||||||
import { Popover } from '../../../_shared/Popover'
|
import { Popover } from '../../../_shared/Popover'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useSearchParams } from '@solidjs/router'
|
import { useSearchParams } from '@solidjs/router'
|
||||||
import { Show } from 'solid-js'
|
import { Show } from 'solid-js'
|
||||||
import { useLocalize } from '../../../../context/localize'
|
import { useLocalize } from '~/context/localize'
|
||||||
import styles from './AuthModalHeader.module.scss'
|
import styles from './AuthModalHeader.module.scss'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { Show, createEffect, createSignal, on } from 'solid-js'
|
import { Show, createEffect, createSignal, on } from 'solid-js'
|
||||||
|
import { useLocalize } from '~/context/localize'
|
||||||
import { useLocalize } from '../../../../context/localize'
|
|
||||||
import { Icon } from '../../../_shared/Icon'
|
import { Icon } from '../../../_shared/Icon'
|
||||||
|
|
||||||
import styles from './PasswordField.module.scss'
|
import styles from './PasswordField.module.scss'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { For } from 'solid-js'
|
import { For } from 'solid-js'
|
||||||
|
import { useLocalize } from '~/context/localize'
|
||||||
import { useLocalize } from '../../../../context/localize'
|
import { useSession } from '~/context/session'
|
||||||
import { useSession } from '../../../../context/session'
|
|
||||||
import { Icon } from '../../../_shared/Icon'
|
import { Icon } from '../../../_shared/Icon'
|
||||||
|
|
||||||
import styles from './SocialProviders.module.scss'
|
import styles from './SocialProviders.module.scss'
|
||||||
|
|
||||||
export const PROVIDERS = ['facebook', 'google', 'github'] // 'vk' | 'telegram'
|
export const PROVIDERS = ['facebook', 'google', 'github'] // 'vk' | 'telegram'
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { A, useLocation, useNavigate, useSearchParams } from '@solidjs/router'
|
import { A, useLocation, useNavigate, useSearchParams } from '@solidjs/router'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { For, Show, createEffect, createMemo, createSignal, onCleanup, onMount } from 'solid-js'
|
import { For, Show, createEffect, createSignal, onCleanup, onMount } from 'solid-js'
|
||||||
import { Icon } from '~/components/_shared/Icon'
|
|
||||||
import { Newsletter } from '~/components/_shared/Newsletter'
|
|
||||||
import { useLocalize } from '~/context/localize'
|
import { useLocalize } from '~/context/localize'
|
||||||
import { useSession } from '~/context/session'
|
import { useSession } from '~/context/session'
|
||||||
import { useTopics } from '~/context/topics'
|
import { useTopics } from '~/context/topics'
|
||||||
import { useUI } from '~/context/ui'
|
import { useUI } from '~/context/ui'
|
||||||
import type { Topic } from '~/graphql/schema/core.gen'
|
import type { Topic } from '../../../graphql/schema/core.gen'
|
||||||
import { getRandomTopicsFromArray } from '~/utils/getRandomTopicsFromArray'
|
import { getRandomTopicsFromArray } from '../../../utils/getRandomTopicsFromArray'
|
||||||
import { getDescription } from '~/utils/meta'
|
import { getDescription } from '../../../utils/meta'
|
||||||
import { SharePopup, getShareUrl } from '../../Article/SharePopup'
|
import { SharePopup, getShareUrl } from '../../Article/SharePopup'
|
||||||
|
import { Icon } from '../../_shared/Icon'
|
||||||
|
import { Newsletter } from '../../_shared/Newsletter'
|
||||||
import { AuthModal } from '../AuthModal'
|
import { AuthModal } from '../AuthModal'
|
||||||
import { ConfirmModal } from '../ConfirmModal'
|
import { ConfirmModal } from '../ConfirmModal'
|
||||||
import { HeaderAuth } from '../HeaderAuth'
|
import { HeaderAuth } from '../HeaderAuth'
|
||||||
|
@ -18,6 +18,7 @@ import { Modal } from '../Modal'
|
||||||
import { SearchModal } from '../SearchModal/SearchModal'
|
import { SearchModal } from '../SearchModal/SearchModal'
|
||||||
import { Snackbar } from '../Snackbar'
|
import { Snackbar } from '../Snackbar'
|
||||||
import styles from './Header.module.scss'
|
import styles from './Header.module.scss'
|
||||||
|
import { Link } from './HeaderLink'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title?: string
|
title?: string
|
||||||
|
@ -32,27 +33,29 @@ type HeaderSearchParams = {
|
||||||
source?: string
|
source?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSwitchLanguage = (value: string) => {
|
const handleSwitchLanguage = (event: { target: { value: string } }) => {
|
||||||
location.href = `${location.href}${location.href.includes('?') ? '&' : '?'}lng=${value}`
|
location.href = `${location.href}${location.href.includes('?') ? '&' : '?'}lng=${event.target.value}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Header = (props: Props) => {
|
export const Header = (props: Props) => {
|
||||||
const { t, lang } = useLocalize()
|
const { t, lang } = useLocalize()
|
||||||
const { modal } = useUI()
|
const { modal } = useUI()
|
||||||
const navigate = useNavigate()
|
|
||||||
const [searchParams] = useSearchParams<HeaderSearchParams>()
|
|
||||||
const { requireAuthentication } = useSession()
|
const { requireAuthentication } = useSession()
|
||||||
const { sortedTopics } = useTopics()
|
const [searchParams, ] = useSearchParams<HeaderSearchParams>()
|
||||||
const topics = createMemo<Topic[]>(() => sortedTopics())
|
const { sortedTopics: topics } = useTopics()
|
||||||
const [randomTopics, setRandomTopics] = createSignal<Topic[]>([])
|
const [randomTopics, setRandomTopics] = createSignal<Topic[]>([])
|
||||||
const [getIsScrollingBottom, setIsScrollingBottom] = createSignal(false)
|
const [getIsScrollingBottom, setIsScrollingBottom] = createSignal(false)
|
||||||
const [getIsScrolled, setIsScrolled] = createSignal(false)
|
const [getIsScrolled, setIsScrolled] = createSignal(false)
|
||||||
const [fixed, setFixed] = createSignal(false)
|
const [fixed, setFixed] = createSignal(false)
|
||||||
const [isSharePopupVisible, setIsSharePopupVisible] = createSignal(false)
|
const [isSharePopupVisible, setIsSharePopupVisible] = createSignal(false)
|
||||||
const [isProfilePopupVisible, setIsProfilePopupVisible] = createSignal(false)
|
const [isProfilePopupVisible, setIsProfilePopupVisible] = createSignal(false)
|
||||||
const [isTopMenuVisible, setIsTopMenuVisible] = createSignal(false)
|
const [isKnowledgeBaseVisible, setIsKnowledgeBaseVisible] = createSignal(false)
|
||||||
|
const [isTopicsVisible, setIsTopicsVisible] = createSignal(false)
|
||||||
|
const [isZineVisible, setIsZineVisible] = createSignal(false)
|
||||||
|
const [isFeedVisible, setIsFeedVisible] = createSignal(false)
|
||||||
const { session } = useSession()
|
const { session } = useSession()
|
||||||
|
const loc = useLocation()
|
||||||
|
const navigate = useNavigate()
|
||||||
const toggleFixed = () => setFixed(!fixed())
|
const toggleFixed = () => setFixed(!fixed())
|
||||||
|
|
||||||
const tag = (topic: Topic) =>
|
const tag = (topic: Topic) =>
|
||||||
|
@ -62,29 +65,24 @@ export const Header = (props: Props) => {
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (topics()?.length) {
|
if (topics()?.length) {
|
||||||
const rt: Topic[] = getRandomTopicsFromArray(topics())
|
setRandomTopics(getRandomTopicsFromArray(topics()))
|
||||||
setRandomTopics(rt)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const mainContent = document.querySelector<HTMLDivElement>('.main-content')
|
const mainContent = document.querySelector<HTMLDivElement>('.main-content')
|
||||||
|
|
||||||
if ((window && fixed()) || modal() !== null) {
|
if (fixed() || modal() !== null) {
|
||||||
windowScrollTop = window.scrollY
|
windowScrollTop = window.scrollY
|
||||||
if (mainContent) {
|
if (mainContent) mainContent.style.marginTop = `-${windowScrollTop}px`
|
||||||
mainContent.style.marginTop = `-${windowScrollTop}px`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.classList.toggle('fixed', fixed() || modal() !== null)
|
document.body.classList.toggle('fixed', fixed() || modal() !== null)
|
||||||
document.body.classList.toggle(styles.fixed, fixed() && !modal())
|
document.body.classList.toggle(styles.fixed, fixed() && !modal())
|
||||||
|
|
||||||
if (!(fixed() || modal())) {
|
if (!(fixed() || modal())) {
|
||||||
if (mainContent) {
|
|
||||||
mainContent.style.marginTop = ''
|
|
||||||
}
|
|
||||||
window.scrollTo(0, windowScrollTop)
|
window.scrollTo(0, windowScrollTop)
|
||||||
|
if(mainContent) mainContent.style.marginTop = ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -103,19 +101,19 @@ export const Header = (props: Props) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const scrollToComments = (event: MouseEvent | undefined, value: boolean) => {
|
const scrollToComments = (event: MouseEvent & { currentTarget: HTMLDivElement; target: Element }, value: boolean) => {
|
||||||
event?.preventDefault()
|
event.preventDefault()
|
||||||
props.scrollToComments?.(value)
|
props.scrollToComments?.(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleBookmarkButtonClick = (ev: MouseEvent | undefined) => {
|
const handleBookmarkButtonClick = (ev: { preventDefault: () => void }) => {
|
||||||
requireAuthentication(() => {
|
requireAuthentication(() => {
|
||||||
// TODO: implement bookmark clicked
|
// TODO: implement bookmark clicked
|
||||||
ev?.preventDefault()
|
ev.preventDefault()
|
||||||
}, 'bookmark')
|
}, 'bookmark')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCreateButtonClick = (ev: MouseEvent | undefined) => {
|
const handleCreateButtonClick = (ev?: { preventDefault: () => void }) => {
|
||||||
requireAuthentication(() => {
|
requireAuthentication(() => {
|
||||||
ev?.preventDefault()
|
ev?.preventDefault()
|
||||||
|
|
||||||
|
@ -123,9 +121,12 @@ export const Header = (props: Props) => {
|
||||||
}, 'create')
|
}, 'create')
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleSubnavigation = (isShow: boolean, signal?: (v: boolean) => void) => {
|
const toggleSubnavigation = (isShow: boolean, signal?: (b: boolean) => void) => {
|
||||||
clearTimer()
|
clearTimer()
|
||||||
setIsTopMenuVisible(false)
|
setIsKnowledgeBaseVisible(false)
|
||||||
|
setIsTopicsVisible(false)
|
||||||
|
setIsZineVisible(false)
|
||||||
|
setIsFeedVisible(false)
|
||||||
|
|
||||||
if (signal) {
|
if (signal) {
|
||||||
signal(isShow)
|
signal(isShow)
|
||||||
|
@ -138,17 +139,21 @@ export const Header = (props: Props) => {
|
||||||
clearTimeout(timer)
|
clearTimeout(timer)
|
||||||
}
|
}
|
||||||
|
|
||||||
const hideSubnavigation = (time = 500) => {
|
const hideSubnavigation = (_ev?: MouseEvent, time = 500) => {
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
toggleSubnavigation(false)
|
toggleSubnavigation(false)
|
||||||
}, time)
|
}, time)
|
||||||
}
|
}
|
||||||
const loc = useLocation()
|
|
||||||
const handleToggleMenuByLink = (event: MouseEvent, route: string) => {
|
const handleToggleMenuByLink = (event: MouseEvent, route: string) => {
|
||||||
|
console.debug('toggling menu link', fixed(), route)
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
navigate(route)
|
if (loc.pathname === route) {
|
||||||
|
toggleFixed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
navigate(route)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
class={styles.mainHeader}
|
class={styles.mainHeader}
|
||||||
|
@ -163,7 +168,7 @@ export const Header = (props: Props) => {
|
||||||
<Modal
|
<Modal
|
||||||
variant={searchParams?.source ? 'narrow' : 'wide'}
|
variant={searchParams?.source ? 'narrow' : 'wide'}
|
||||||
name="auth"
|
name="auth"
|
||||||
hideClose={Boolean(searchParams?.source === 'authguard')}
|
hideClose={searchParams?.source === 'authguard'}
|
||||||
noPadding={true}
|
noPadding={true}
|
||||||
>
|
>
|
||||||
<AuthModal />
|
<AuthModal />
|
||||||
|
@ -185,7 +190,7 @@ export const Header = (props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class={clsx('col-md-5 col-xl-4 col-auto', styles.mainLogo)}>
|
<div class={clsx('col-md-5 col-xl-4 col-auto', styles.mainLogo)}>
|
||||||
<A href={'/'}>
|
<A href='/'>
|
||||||
<img src="/logo.svg" alt={t('Discours')} />
|
<img src="/logo.svg" alt={t('Discours')} />
|
||||||
</A>
|
</A>
|
||||||
</div>
|
</div>
|
||||||
|
@ -195,34 +200,58 @@ export const Header = (props: Props) => {
|
||||||
</Show>
|
</Show>
|
||||||
<div class={clsx(styles.mainNavigation, { [styles.fixed]: fixed() })}>
|
<div class={clsx(styles.mainNavigation, { [styles.fixed]: fixed() })}>
|
||||||
<ul class="view-switcher">
|
<ul class="view-switcher">
|
||||||
<For each={['', 'feed', 'topics', 'authors', 'guide']}>
|
<Link
|
||||||
{(route: string) => (
|
onMouseOver={() => toggleSubnavigation(true, setIsZineVisible)}
|
||||||
<li classList={{ 'view-switcher__item--selected': loc.pathname.includes(route) }}>
|
onMouseOut={hideSubnavigation}
|
||||||
<A
|
href="/"
|
||||||
class={clsx({ [styles.mainNavigationItemActive]: loc.pathname.includes(route) })}
|
active={isZineVisible()}
|
||||||
href={`/${route}`}
|
body={t('journal')}
|
||||||
onClick={(event) => handleToggleMenuByLink(event, `/${route}`)}
|
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, '')}
|
||||||
onMouseOver={() => toggleSubnavigation(true, setIsTopMenuVisible)}
|
/>
|
||||||
onMouseOut={() => hideSubnavigation()}
|
<Link
|
||||||
>
|
onMouseOver={() => toggleSubnavigation(true, setIsFeedVisible)}
|
||||||
{t(route || 'journal')}
|
onMouseOut={hideSubnavigation}
|
||||||
</A>
|
href="/feed"
|
||||||
</li>
|
active={isFeedVisible()}
|
||||||
)}
|
body={t('feed')}
|
||||||
</For>
|
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, 'feed')}
|
||||||
|
/>
|
||||||
|
<Link
|
||||||
|
onMouseOver={() => toggleSubnavigation(true, setIsTopicsVisible)}
|
||||||
|
onMouseOut={hideSubnavigation}
|
||||||
|
href="/topic"
|
||||||
|
active={isTopicsVisible()}
|
||||||
|
body={t('topics')}
|
||||||
|
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, 'topic')}
|
||||||
|
/>
|
||||||
|
<Link
|
||||||
|
onMouseOver={(event?: MouseEvent) => hideSubnavigation(event, 0)}
|
||||||
|
onMouseOut={(event?: MouseEvent) => hideSubnavigation(event, 0)}
|
||||||
|
href="/author"
|
||||||
|
body={t('authors')}
|
||||||
|
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, 'author')}
|
||||||
|
/>
|
||||||
|
<Link
|
||||||
|
onMouseOver={() => toggleSubnavigation(true, setIsKnowledgeBaseVisible)}
|
||||||
|
onMouseOut={() => hideSubnavigation}
|
||||||
|
href="/guide"
|
||||||
|
body={t('Knowledge base')}
|
||||||
|
active={isKnowledgeBaseVisible()}
|
||||||
|
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, 'guide')}
|
||||||
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class={styles.mainNavigationMobile}>
|
<div class={styles.mainNavigationMobile}>
|
||||||
<h4>{t('Participating')}</h4>
|
<h4>{t('Participating')}</h4>
|
||||||
<ul class="view-switcher">
|
<ul class="view-switcher">
|
||||||
<li>
|
<li>
|
||||||
<A href="/edit/new">{t('Create post')}</A>
|
<a href="/create">{t('Create post')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/connect">{t('Suggest an idea')}</A>
|
<a href="/connect">{t('Suggest an idea')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/support">{t('Support the project')}</A>
|
<a href="/about/help">{t('Support the project')}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -272,7 +301,7 @@ export const Header = (props: Props) => {
|
||||||
<h4>{t('Language')}</h4>
|
<h4>{t('Language')}</h4>
|
||||||
<select
|
<select
|
||||||
class={styles.languageSelectorMobile}
|
class={styles.languageSelectorMobile}
|
||||||
onChange={(ev) => handleSwitchLanguage(ev.target.value)}
|
onChange={handleSwitchLanguage}
|
||||||
value={lang()}
|
value={lang()}
|
||||||
>
|
>
|
||||||
<option value="ru">🇷🇺 Русский</option>
|
<option value="ru">🇷🇺 Русский</option>
|
||||||
|
@ -280,9 +309,9 @@ export const Header = (props: Props) => {
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<div class={styles.mainNavigationAdditionalLinks}>
|
<div class={styles.mainNavigationAdditionalLinks}>
|
||||||
<A href="/guide/dogma">{t('Dogma')}</A>
|
<a href="/about/dogma">{t('Dogma')}</a>
|
||||||
<A href="/guide/debate">{t('Discussion rules')}</A>
|
<a href="/about/discussion-rules" innerHTML={t('Discussion rules')} />
|
||||||
<A href="/guide/principles">{t('Our principles')}</A>
|
<a href="/about/principles">{t('Principles')}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
|
@ -337,73 +366,74 @@ export const Header = (props: Props) => {
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={clsx(styles.subnavigation, 'col')}
|
class={clsx(styles.subnavigation, 'col')}
|
||||||
|
classList={{ hidden: !isKnowledgeBaseVisible() }}
|
||||||
onMouseOver={clearTimer}
|
onMouseOver={clearTimer}
|
||||||
onMouseOut={() => hideSubnavigation()}
|
onMouseOut={hideSubnavigation}
|
||||||
>
|
>
|
||||||
<ul class="nodash">
|
<ul class="nodash">
|
||||||
<li>
|
<li>
|
||||||
<A href="/guide/manifest">{t('Manifesto')}</A>
|
<a href="/about/manifest">{t('Manifesto')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/guide/dogma">{t('Dogma')}</A>
|
<a href="/about/dogma">{t('Dogma')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/guide/principles">{t('Community Our principles')}</A>
|
<a href="/about/principles">{t('Community Principles')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/guide">{t('Platform Guide')}</A>
|
<a href="/about/guide">{t('Platform Guide')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/support">{t('Support us')}</A>
|
<a href="/about/manifest#participation">{t('Support us')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/manifest#participation">{t('How to help')}</A>
|
<a href="/about/help">{t('How to help')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class={styles.rightItem}>
|
<li class={styles.rightItem}>
|
||||||
<A href="/connect">
|
<a href="/connect">
|
||||||
{t('Suggest an idea')}
|
{t('Suggest an idea')}
|
||||||
<Icon name="arrow-right-black" class={clsx(styles.icon, styles.rightItemIcon)} />
|
<Icon name="arrow-right-black" class={clsx(styles.icon, styles.rightItemIcon)} />
|
||||||
</A>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={clsx(styles.subnavigation, 'col')}
|
class={clsx(styles.subnavigation, 'col')}
|
||||||
classList={{ hidden: !isTopMenuVisible() }}
|
classList={{ hidden: !isZineVisible() }}
|
||||||
onMouseOver={clearTimer}
|
onMouseOver={clearTimer}
|
||||||
onMouseOut={() => hideSubnavigation()}
|
onMouseOut={hideSubnavigation}
|
||||||
>
|
>
|
||||||
<ul class="nodash">
|
<ul class="nodash">
|
||||||
<li class="item">
|
<li class="item">
|
||||||
<A href="/expo">{t('Art')}</A>
|
<a href="/expo">{t('Art')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="item">
|
<li class="item">
|
||||||
<A href="/podcasts">{t('Podcasts')}</A>
|
<a href="/podcasts">{t('Podcasts')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="item">
|
<li class="item">
|
||||||
<A href="/guide/projects">{t('Special Projects')}</A>
|
<a href="/about/projects">{t('Special Projects')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/topic/interview">#{t('Interview')}</A>
|
<a href="/topic/interview">#{t('Interview')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/topic/reportage">#{t('Reports')}</A>
|
<a href="/topic/reportage">#{t('Reports')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/topic/empiric">#{t('Experience')}</A>
|
<a href="/topic/empiric">#{t('Experience')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/topic/society">#{t('Society')}</A>
|
<a href="/topic/society">#{t('Society')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/topic/culture">#{t('Culture')}</A>
|
<a href="/topic/culture">#{t('Culture')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/topic/theory">#{t('Theory')}</A>
|
<a href="/topic/theory">#{t('Theory')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<A href="/topic/poetry">#{t('Poetry')}</A>
|
<a href="/topic/poetry">#{t('Poetry')}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class={styles.rightItem}>
|
<li class={styles.rightItem}>
|
||||||
<A href="/topic">
|
<A href="/topic">
|
||||||
|
@ -416,8 +446,9 @@ export const Header = (props: Props) => {
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={clsx(styles.subnavigation, 'col')}
|
class={clsx(styles.subnavigation, 'col')}
|
||||||
|
classList={{ hidden: !isTopicsVisible() }}
|
||||||
onMouseOver={clearTimer}
|
onMouseOver={clearTimer}
|
||||||
onMouseOut={() => hideSubnavigation()}
|
onMouseOut={hideSubnavigation}
|
||||||
>
|
>
|
||||||
<ul class="nodash">
|
<ul class="nodash">
|
||||||
<Show when={randomTopics().length > 0}>
|
<Show when={randomTopics().length > 0}>
|
||||||
|
@ -442,8 +473,9 @@ export const Header = (props: Props) => {
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={clsx(styles.subnavigation, styles.subnavigationFeed, 'col')}
|
class={clsx(styles.subnavigation, styles.subnavigationFeed, 'col')}
|
||||||
|
classList={{ hidden: !isFeedVisible() }}
|
||||||
onMouseOver={clearTimer}
|
onMouseOver={clearTimer}
|
||||||
onMouseOut={() => hideSubnavigation()}
|
onMouseOut={hideSubnavigation}
|
||||||
>
|
>
|
||||||
<ul class="nodash">
|
<ul class="nodash">
|
||||||
<li>
|
<li>
|
||||||
|
|
36
src/components/Nav/Header/HeaderLink.tsx
Normal file
36
src/components/Nav/Header/HeaderLink.tsx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { A, useLocation } from '@solidjs/router'
|
||||||
|
import { clsx } from 'clsx'
|
||||||
|
import { ConditionalWrapper } from '../../_shared/ConditionalWrapper'
|
||||||
|
import styles from './Header.module.scss'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onMouseOver: (event?: MouseEvent, time?: number) => void
|
||||||
|
onMouseOut: (event?: MouseEvent, time?: number) => void
|
||||||
|
href?: string
|
||||||
|
body: string
|
||||||
|
active?: boolean
|
||||||
|
onClick?: (event: MouseEvent) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Link = (props: Props) => {
|
||||||
|
const loc = useLocation()
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
onClick={props.onClick}
|
||||||
|
classList={{ 'view-switcher__item--selected': props.href === `/${loc.pathname}` }}
|
||||||
|
>
|
||||||
|
<ConditionalWrapper
|
||||||
|
condition={props.href === `/${loc.pathname}`}
|
||||||
|
wrapper={(children) => <A href={props.href||'/'}>{children}</A>}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class={clsx('cursorPointer linkReplacement', { [styles.mainNavigationItemActive]: props.active })}
|
||||||
|
onMouseOver={props.onMouseOver}
|
||||||
|
onMouseOut={props.onMouseOut}
|
||||||
|
>
|
||||||
|
{props.body}
|
||||||
|
</span>
|
||||||
|
</ConditionalWrapper>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
|
@ -120,7 +120,7 @@ export const AllAuthors = (props: Props) => {
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-20 col-xl-18">
|
<div class="col-lg-20 col-xl-18">
|
||||||
<ul class={clsx('nodash', styles.alphabet)}>
|
<ul class={clsx('nodash', styles.alphabet)}>
|
||||||
<For each={[...alphabet()]}>
|
<For each={[...(alphabet()||[])]}>
|
||||||
{(letter, index) => (
|
{(letter, index) => (
|
||||||
<li>
|
<li>
|
||||||
<Show when={letter in byLetterFiltered()} fallback={letter}>
|
<Show when={letter in byLetterFiltered()} fallback={letter}>
|
||||||
|
@ -140,15 +140,15 @@ export const AllAuthors = (props: Props) => {
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<For each={sortedKeys()}>
|
<For each={sortedKeys() || []}>
|
||||||
{(letter) => (
|
{(letter) => (
|
||||||
<div class={clsx(styles.group, 'group')}>
|
<div class={clsx(styles.group, 'group')}>
|
||||||
<h2 id={`letter-${alphabet().indexOf(letter)}`}>{letter}</h2>
|
<h2 id={`letter-${alphabet()?.indexOf(letter)||''}`}>{letter}</h2>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-20">
|
<div class="col-lg-20">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<For each={byLetterFiltered()[letter]}>
|
<For each={byLetterFiltered()?.[letter] || []}>
|
||||||
{(author) => (
|
{(author) => (
|
||||||
<div class={clsx(styles.topic, 'topic col-sm-12 col-md-8')}>
|
<div class={clsx(styles.topic, 'topic col-sm-12 col-md-8')}>
|
||||||
<div class="topic-title">
|
<div class="topic-title">
|
||||||
|
|
|
@ -83,11 +83,11 @@ export const LocalizeProvider = (props: { children: JSX.Element }) => {
|
||||||
const formatTimeAgo = (date: Date) => timeAgo().format(date)
|
const formatTimeAgo = (date: Date) => timeAgo().format(date)
|
||||||
|
|
||||||
const value: LocalizeContextType = {
|
const value: LocalizeContextType = {
|
||||||
t: ((s: string) => {
|
t: ((...args) => {
|
||||||
try {
|
try {
|
||||||
return i18next.t(s)
|
return i18next.t(...args)
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return s
|
return args?.length > 0 ? args[0] as string : ''
|
||||||
}
|
}
|
||||||
}) as i18n['t'],
|
}) as i18n['t'],
|
||||||
lang,
|
lang,
|
||||||
|
|
|
@ -10,30 +10,40 @@ import ru from '~/config/locales/ru/translation.json'
|
||||||
TimeAgo.addLocale(enTime)
|
TimeAgo.addLocale(enTime)
|
||||||
TimeAgo.addLocale(ruTime)
|
TimeAgo.addLocale(ruTime)
|
||||||
|
|
||||||
|
class AutoKeyMap extends Map<string, string> {
|
||||||
|
get(key: string): string {
|
||||||
|
return super.get(key) ?? key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const i18nextInit = async (lng = 'ru') => {
|
export const i18nextInit = async (lng = 'ru') => {
|
||||||
if (!i18next.isInitialized) {
|
if (!i18next.isInitialized) {
|
||||||
console.debug('[i18next] initializing...')
|
console.debug('[i18next] initializing...')
|
||||||
// eslint-disable-next-line import/no-named-as-default-member
|
|
||||||
|
const enAutoKeyMap = new AutoKeyMap(Object.entries(en));
|
||||||
|
|
||||||
await i18next
|
await i18next
|
||||||
.use(HttpApi)
|
.use(HttpApi)
|
||||||
.use(ICU)
|
.use(ICU)
|
||||||
.init({
|
.init({
|
||||||
// debug: true,
|
// debug: true,
|
||||||
supportedLngs: ['ru', 'en'],
|
supportedLngs: ['ru', 'en'],
|
||||||
fallbackLng: lng,
|
fallbackLng: 'en',
|
||||||
lng,
|
lng,
|
||||||
load: 'languageOnly',
|
load: 'languageOnly',
|
||||||
initImmediate: false,
|
initImmediate: false,
|
||||||
resources: {
|
resources: {
|
||||||
ru: { translation: ru },
|
ru: { translation: ru },
|
||||||
en: { translation: en }
|
en: { translation: enAutoKeyMap }
|
||||||
}
|
},
|
||||||
|
interpolation: {
|
||||||
|
escapeValue: false
|
||||||
|
},
|
||||||
|
parseMissingKeyHandler: (key) => key
|
||||||
})
|
})
|
||||||
// console.debug(i18next)
|
|
||||||
} else if (i18next.language !== lng) {
|
} else if (i18next.language !== lng) {
|
||||||
await i18next.changeLanguage(lng)
|
await i18next.changeLanguage(lng)
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.debug(`[i18next] using <${lng}>...`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { TimeAgo, i18next, type i18n }
|
export { TimeAgo, i18next, type i18n }
|
||||||
|
|
Loading…
Reference in New Issue
Block a user