langswitch-fix
This commit is contained in:
parent
4c7839aaff
commit
a5eaeab5cd
|
@ -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'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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 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' },
|
||||||
|
]
|
||||||
|
type FooterItem = {
|
||||||
|
title: string
|
||||||
|
slug: string
|
||||||
|
rel?: string
|
||||||
|
}
|
||||||
|
export const FooterView = () => {
|
||||||
const { t, lang } = useLocalize()
|
const { t, lang } = useLocalize()
|
||||||
|
const [footerLinks, setFooterLinks] = createSignal<Array<{ header: string, items: FooterItem[]}>>([])
|
||||||
|
|
||||||
const changeLangTitle = createMemo(() => (lang() === 'ru' ? 'English' : 'Русский'))
|
onMount(() => {
|
||||||
const changeLangLink = createMemo(() => `?lng=${lang() === 'ru' ? 'en' : 'ru'}`)
|
setFooterLinks([
|
||||||
const links = createMemo(() => [
|
{
|
||||||
{
|
header: t('About the project'),
|
||||||
header: t('About the project'),
|
items: [
|
||||||
items: [
|
{ title: t('Discours Manifest'), slug: '/about/manifest' },
|
||||||
{
|
{ title: t('How it works'), slug: '/about/guide' },
|
||||||
title: t('Discours Manifest'),
|
{ title: t('Dogma'), slug: '/about/dogma' },
|
||||||
slug: '/about/manifest',
|
{ 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',
|
{
|
||||||
},
|
header: t('Participating'),
|
||||||
{
|
items: [
|
||||||
title: t('Dogma'),
|
{ title: t('Suggest an idea'), slug: '/connect' },
|
||||||
slug: '/about/dogma',
|
{ 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' },
|
||||||
title: t('Principles'),
|
],
|
||||||
slug: '/about/principles',
|
},
|
||||||
},
|
{
|
||||||
{
|
header: t('Sections'),
|
||||||
title: t('How to write an article'),
|
items: [
|
||||||
slug: '/how-to-write-a-good-article',
|
{ title: t('Authors'), slug: '/authors' },
|
||||||
},
|
{ title: t('Communities'), slug: '/community' },
|
||||||
],
|
{ 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' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
{
|
|
||||||
header: t('Participating'),
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
title: t('Suggest an idea'),
|
|
||||||
slug: '/connect',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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'),
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
title: t('Authors'),
|
|
||||||
slug: '/authors',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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}>
|
</a>
|
||||||
<Icon name={`${social.name}-white`} class={styles.icon} />
|
</div>
|
||||||
</a>
|
)}
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user