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 isBun = Boolean(process.env.BUN)
export default defineConfig({
ssr: true,
server: {
preset: isVercel ? 'vercel_edge' : isBun ? 'bun' : 'node',
port: 3000,
},
devOverlay: true,
build: {
chunkSizeWarningLimit: 1024,
target: 'esnext',
@ -33,7 +35,7 @@ export default defineConfig({
preprocessorOptions: {
scss: {
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 { For, createMemo } from 'solid-js'
import { For, createSignal, onMount } from 'solid-js'
import { useLocalize } from '../../context/localize'
import { Icon } from '../_shared/Icon'
import { Newsletter } from '../_shared/Newsletter'
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 [footerLinks, setFooterLinks] = createSignal<Array<{ header: string, items: FooterItem[]}>>([])
const changeLangTitle = createMemo(() => (lang() === 'ru' ? 'English' : 'Русский'))
const changeLangLink = createMemo(() => `?lng=${lang() === 'ru' ? 'en' : 'ru'}`)
const links = createMemo(() => [
{
header: t('About the project'),
items: [
{
title: t('Discours Manifest'),
slug: '/about/manifest',
},
{
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',
},
],
},
onMount(() => {
setFooterLinks([
{
header: t('About the project'),
items: [
{ title: t('Discours Manifest'), slug: '/about/manifest' },
{ 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'),
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: 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 (
<footer class={styles.discoursFooter}>
<div class="wide-container">
<div class="row">
<For each={links()}>
<For each={footerLinks()}>
{({ header, items }) => (
<div class="col-sm-8 col-md-6">
<h5>{header}</h5>
<h5>{t(header)}</h5>
<ul>
<For each={items}>
{({ slug, title, ...rest }) => (
{({ slug, title, rel }: FooterItem) => (
<li>
{' '}
<a href={slug} {...rest}>
{title}
<a href={slug} rel={rel}>
{rel ? title : t(title)}
</a>{' '}
</li>
)}
@ -147,16 +96,13 @@ export const Footer = () => {
</div>
<div class={clsx(styles.footerCopyrightSocial, 'col-md-6 col-lg-4')}>
<For each={social}>
{(social) => {
const styleKey = `socialItem${social.name}` as keyof typeof styles
return (
<div class={clsx(styles.socialItem, styles[styleKey])}>
<a href={social.href}>
<Icon name={`${social.name}-white`} class={styles.icon} />
</a>
</div>
)
}}
{(provider) => (
<div class={clsx(styles.socialItem, styles[`socialItem${provider.name}` as keyof typeof styles])}>
<a href={provider.href}>
<Icon name={`${provider.name}-white`} class={styles.icon} />
</a>
</div>
)}
</For>
</div>
</div>

View File

@ -4,7 +4,7 @@ import { Title } from '@solidjs/meta'
import { clsx } from 'clsx'
import { Show, createEffect, createSignal } from 'solid-js'
import { Footer } from '../Discours/Footer'
import { FooterView } from '../Discours/Footer'
import { Header } from '../Nav/Header'
import '../../styles/app.scss'
@ -26,7 +26,7 @@ type 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)
createEffect(() => {
@ -56,7 +56,7 @@ export const PageLayout = (props: Props) => {
{props.children}
</main>
<Show when={props.hideFooter !== true}>
<Footer />
<FooterView />
</Show>
</>
)

View File

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

View File

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

View File

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

View File

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