langswitch-fix

This commit is contained in:
Untone 2024-06-26 01:52:46 +03:00
parent 4c7839aaff
commit a5eaeab5cd
7 changed files with 94 additions and 149 deletions

View File

@ -5,10 +5,12 @@ import sassDts from 'vite-plugin-sass-dts'
const isVercel = Boolean(process?.env.VERCEL) const isVercel = Boolean(process?.env.VERCEL)
const isBun = Boolean(process.env.BUN) const isBun = Boolean(process.env.BUN)
export default defineConfig({ export default defineConfig({
ssr: true,
server: { server: {
preset: isVercel ? 'vercel_edge' : isBun ? 'bun' : 'node', preset: isVercel ? 'vercel_edge' : isBun ? 'bun' : 'node',
port: 3000, port: 3000,
}, },
devOverlay: true,
build: { build: {
chunkSizeWarningLimit: 1024, chunkSizeWarningLimit: 1024,
target: 'esnext', target: 'esnext',
@ -33,7 +35,7 @@ export default defineConfig({
preprocessorOptions: { preprocessorOptions: {
scss: { scss: {
additionalData: '@import "src/styles/imports";\n', additionalData: '@import "src/styles/imports";\n',
includePaths: ['public', 'src/styles'] includePaths: ['./public', './src/styles'],
}, },
}, },
}, },

View File

@ -1,127 +1,76 @@
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { For, createMemo } from 'solid-js' import { For, createSignal, onMount } from 'solid-js'
import { useLocalize } from '../../context/localize' import { useLocalize } from '../../context/localize'
import { Icon } from '../_shared/Icon' import { Icon } from '../_shared/Icon'
import { Newsletter } from '../_shared/Newsletter' import { Newsletter } from '../_shared/Newsletter'
import styles from './Footer.module.scss' import styles from './Footer.module.scss'
export const Footer = () => {
const { t, lang } = useLocalize()
const changeLangTitle = createMemo(() => (lang() === 'ru' ? 'English' : 'Русский')) const social = [
const changeLangLink = createMemo(() => `?lng=${lang() === 'ru' ? 'en' : 'ru'}`) { name: 'facebook', href: 'https://facebook.com/discoursio' },
const links = createMemo(() => [ { name: 'vk', href: 'https://vk.com/discoursio' },
{ name: 'twitter', href: 'https://twitter.com/discours_io' },
{ name: 'telegram', href: 'https://t.me/discoursio' },
]
type FooterItem = {
title: string
slug: string
rel?: string
}
export const FooterView = () => {
const { t, lang } = useLocalize()
const [footerLinks, setFooterLinks] = createSignal<Array<{ header: string, items: FooterItem[]}>>([])
onMount(() => {
setFooterLinks([
{ {
header: t('About the project'), header: t('About the project'),
items: [ items: [
{ { title: t('Discours Manifest'), slug: '/about/manifest' },
title: t('Discours Manifest'), { title: t('How it works'), slug: '/about/guide' },
slug: '/about/manifest', { title: t('Dogma'), slug: '/about/dogma' },
}, { title: t('Principles'), slug: '/about/principles' },
{ { title: t('How to write an article'), slug: '/how-to-write-a-good-article' },
title: t('How it works'),
slug: '/about/guide',
},
{
title: t('Dogma'),
slug: '/about/dogma',
},
{
title: t('Principles'),
slug: '/about/principles',
},
{
title: t('How to write an article'),
slug: '/how-to-write-a-good-article',
},
], ],
}, },
{ {
header: t('Participating'), header: t('Participating'),
items: [ items: [
{ { title: t('Suggest an idea'), slug: '/connect' },
title: t('Suggest an idea'), { title: t('Become an author'), slug: '/create' },
slug: '/connect', { title: t('Support Discours'), slug: '/about/help' },
}, { title: t('Work with us'), slug: 'https://docs.google.com/forms/d/e/1FAIpQLSeNNvIzKlXElJtkPkYiXl-jQjlvsL9u4-kpnoRjz1O8Wo40xQ/viewform' },
{
title: t('Become an author'),
slug: '/create',
},
{
title: t('Support Discours'),
slug: '/about/help',
},
{
title: t('Work with us'),
slug: 'https://docs.google.com/forms/d/e/1FAIpQLSeNNvIzKlXElJtkPkYiXl-jQjlvsL9u4-kpnoRjz1O8Wo40xQ/viewform',
},
], ],
}, },
{ {
header: t('Sections'), header: t('Sections'),
items: [ items: [
{ { title: t('Authors'), slug: '/authors' },
title: t('Authors'), { title: t('Communities'), slug: '/community' },
slug: '/authors', { title: t('Partners'), slug: '/about/partners' },
}, { title: t('Special projects'), slug: '/about/projects' },
{ { title: lang() === 'ru' ? 'English' : 'Русский', slug: `?lng=${lang() === 'ru' ? 'en' : 'ru'}`, rel: 'external' },
title: t('Communities'),
slug: '/community',
},
{
title: t('Partners'),
slug: '/about/partners',
},
{
title: t('Special projects'),
slug: '/about/projects',
},
{
title: changeLangTitle(),
slug: changeLangLink(),
rel: 'external',
},
], ],
}, },
]) ])
})
const social = [
{
name: 'facebook',
href: 'https://facebook.com/discoursio',
},
{
name: 'vk',
href: 'https://vk.com/discoursio',
},
{
name: 'twitter',
href: 'https://twitter.com/discours_io',
},
{
name: 'telegram',
href: 'https://t.me/discoursio',
},
]
return ( return (
<footer class={styles.discoursFooter}> <footer class={styles.discoursFooter}>
<div class="wide-container"> <div class="wide-container">
<div class="row"> <div class="row">
<For each={links()}> <For each={footerLinks()}>
{({ header, items }) => ( {({ header, items }) => (
<div class="col-sm-8 col-md-6"> <div class="col-sm-8 col-md-6">
<h5>{header}</h5> <h5>{t(header)}</h5>
<ul> <ul>
<For each={items}> <For each={items}>
{({ slug, title, ...rest }) => ( {({ slug, title, rel }: FooterItem) => (
<li> <li>
{' '} {' '}
<a href={slug} {...rest}> <a href={slug} rel={rel}>
{title} {rel ? title : t(title)}
</a>{' '} </a>{' '}
</li> </li>
)} )}
@ -147,16 +96,13 @@ export const Footer = () => {
</div> </div>
<div class={clsx(styles.footerCopyrightSocial, 'col-md-6 col-lg-4')}> <div class={clsx(styles.footerCopyrightSocial, 'col-md-6 col-lg-4')}>
<For each={social}> <For each={social}>
{(social) => { {(provider) => (
const styleKey = `socialItem${social.name}` as keyof typeof styles <div class={clsx(styles.socialItem, styles[`socialItem${provider.name}` as keyof typeof styles])}>
return ( <a href={provider.href}>
<div class={clsx(styles.socialItem, styles[styleKey])}> <Icon name={`${provider.name}-white`} class={styles.icon} />
<a href={social.href}>
<Icon name={`${social.name}-white`} class={styles.icon} />
</a> </a>
</div> </div>
) )}
}}
</For> </For>
</div> </div>
</div> </div>

View File

@ -4,7 +4,7 @@ import { Title } from '@solidjs/meta'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { Show, createEffect, createSignal } from 'solid-js' import { Show, createEffect, createSignal } from 'solid-js'
import { Footer } from '../Discours/Footer' import { FooterView } from '../Discours/Footer'
import { Header } from '../Nav/Header' import { Header } from '../Nav/Header'
import '../../styles/app.scss' import '../../styles/app.scss'
@ -26,7 +26,7 @@ type Props = {
} }
export const PageLayout = (props: Props) => { export const PageLayout = (props: Props) => {
const isHeaderFixed = props.isHeaderFixed === undefined ? true : props.isHeaderFixed const isHeaderFixed = (props.isHeaderFixed === undefined) ? true : props.isHeaderFixed
const [scrollToComments, setScrollToComments] = createSignal<boolean>(false) const [scrollToComments, setScrollToComments] = createSignal<boolean>(false)
createEffect(() => { createEffect(() => {
@ -56,7 +56,7 @@ export const PageLayout = (props: Props) => {
{props.children} {props.children}
</main> </main>
<Show when={props.hideFooter !== true}> <Show when={props.hideFooter !== true}>
<Footer /> <FooterView />
</Show> </Show>
</> </>
) )

View File

@ -1,7 +1,6 @@
import { useSearchParams } from '@solidjs/router' import { useSearchParams } from '@solidjs/router'
import type { Accessor, JSX } from 'solid-js' import type { Accessor, JSX } from 'solid-js'
import { Show, createContext, createEffect, createMemo, createSignal, useContext } from 'solid-js' import { Show, createContext, createEffect, createMemo, createSignal, on, onMount, useContext } from 'solid-js'
import { TimeAgo, type i18n, i18next, i18nextInit } from '~/lib/i18next' import { TimeAgo, type i18n, i18next, i18nextInit } from '~/lib/i18next'
i18nextInit() i18nextInit()
@ -24,27 +23,22 @@ const LocalizeContext = createContext<LocalizeContextType>({
export function useLocalize() { export function useLocalize() {
return useContext(LocalizeContext) return useContext(LocalizeContext)
} }
type LocalizeSearchParams = {
lng?: Language
}
export const LocalizeProvider = (props: { children: JSX.Element }) => { export const LocalizeProvider = (props: { children: JSX.Element }) => {
const [lang, setLang] = createSignal<Language>(i18next.language === 'en' ? 'en' : 'ru') const [lang, setLang] = createSignal<Language>(i18next.language === 'en' ? 'en' : 'ru')
const [searchParams, changeSearchParams] = useSearchParams<Record<string, string>>() const [searchParams, changeSearchParams] = useSearchParams<LocalizeSearchParams>()
createEffect(() => { // set lang effects
if (!(searchParams?.lng || localStorage.getItem('lng'))) { onMount(() => {
return const lng = searchParams?.lng || localStorage?.getItem('lng') || 'ru'
} setLang(lng as Language)
try { changeSearchParams({lng: undefined})
const lng: Language = searchParams?.lng === 'en' ? 'en' : 'ru'
i18next.changeLanguage(lng)
setLang(lng)
if (searchParams?.lng) {
changeSearchParams({ lng }, { replace: true })
}
localStorage?.setItem('lng', lng)
} catch (e) {
console.warn(e)
}
}) })
createEffect(on(lang, (lng: Language) => {
localStorage.setItem('lng', lng || 'ru')
i18next.changeLanguage(lng || 'ru')
}))
const formatTime = (date: Date, options: Intl.DateTimeFormatOptions = {}) => { const formatTime = (date: Date, options: Intl.DateTimeFormatOptions = {}) => {
const opts = Object.assign( const opts = Object.assign(

View File

@ -164,7 +164,7 @@ export const UIProvider = (props: { children: JSX.Element }) => {
} }
const showModal = (modalType: ModalType, modalSource?: AuthModalSource) => { const showModal = (modalType: ModalType, modalSource?: AuthModalSource) => {
console.log('[context.ui] showModal()', modalType) // console.log('[context.ui] showModal()', modalType)
if (modalSource) { if (modalSource) {
setSearchParams({ source: modalSource }) setSearchParams({ source: modalSource })
} }
@ -172,7 +172,7 @@ export const UIProvider = (props: { children: JSX.Element }) => {
} }
const hideModal = () => { const hideModal = () => {
console.log('[context.ui] hideModal()', modal()) // console.log('[context.ui] hideModal()', modal())
setTimeout(() => setModal(null), 1) // NOTE: modal rerender fix setTimeout(() => setModal(null), 1) // NOTE: modal rerender fix
setSearchParams({ source: undefined, m: undefined, mode: undefined }) setSearchParams({ source: undefined, m: undefined, mode: undefined })
} }
@ -184,7 +184,7 @@ export const UIProvider = (props: { children: JSX.Element }) => {
[modal, () => searchParams?.m || ''], [modal, () => searchParams?.m || ''],
([m1, m2]) => { ([m1, m2]) => {
const m = m1 || m2 || '' const m = m1 || m2 || ''
console.log('[context.ui] search params change', m) m1 && console.log('[context.ui] search params change', m1)
if (m) { if (m) {
showModal(m as ModalType) showModal(m as ModalType)
} else { } else {

View File

@ -2,11 +2,14 @@ import i18next, { type i18n } from 'i18next'
import HttpApi from 'i18next-http-backend' import HttpApi from 'i18next-http-backend'
import ICU from 'i18next-icu' import ICU from 'i18next-icu'
import TimeAgo from 'javascript-time-ago' import TimeAgo from 'javascript-time-ago'
import en from 'javascript-time-ago/locale/en' import enTime from 'javascript-time-ago/locale/en'
import ru from 'javascript-time-ago/locale/ru' import ruTime from 'javascript-time-ago/locale/ru'
import en from './locales/en/translation.json'
import ru from './locales/ru/translation.json'
TimeAgo.addLocale(en)
TimeAgo.addLocale(ru) TimeAgo.addLocale(enTime)
TimeAgo.addLocale(ruTime)
export const i18nextInit = async (lng = 'ru') => { export const i18nextInit = async (lng = 'ru') => {
if (!i18next.isInitialized) { if (!i18next.isInitialized) {
@ -23,8 +26,8 @@ export const i18nextInit = async (lng = 'ru') => {
load: 'languageOnly', load: 'languageOnly',
initImmediate: false, initImmediate: false,
resources: { resources: {
ru: { translation: await import('./locales/ru/translation.json') }, ru: { translation: ru },
en: { translation: await import('./locales/en/translation.json') }, en: { translation: en },
}, },
}) })
// console.debug(i18next) // console.debug(i18next)

View File

@ -853,7 +853,7 @@ figure {
position: relative; position: relative;
@include media-breakpoint-up(lg) { @include media-breakpoint-up(lg) {
padding-top: 130px; // padding-top: 130px;
} }
} }