Adds a Russian version (data/resume.ru.json, default language) with an RU/EN switch stored under the key shared with the front page and the portfolio. The top bar becomes the site-wide one (brand, Resume, Portfolio, Gitea, Contact, language, theme) with a second row of anchors for this page's sections, and the fonts move to Unbounded and Onest so the three pages share one type system. Portfolio links now point at /portfolio/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XtcZtnG4GQA1d6mW5PNrS9
33 lines
1.2 KiB
TypeScript
33 lines
1.2 KiB
TypeScript
import type { ReactNode } from 'react'
|
|
|
|
export type Lang = 'ru' | 'en'
|
|
|
|
/** Both languages side by side; html[data-lang] decides which one is shown, so there is no flash and no state. */
|
|
export function Bi({ ru, en }: Readonly<{ ru: ReactNode; en: ReactNode }>) {
|
|
return (
|
|
<>
|
|
<span data-ru>{ru}</span>
|
|
<span data-en>{en}</span>
|
|
</>
|
|
)
|
|
}
|
|
|
|
const pluralRu = new Intl.PluralRules('ru')
|
|
const pluralEn = new Intl.PluralRules('en')
|
|
|
|
/** "21 проект" / "21 project": Russian has three forms (1 / 2-4 / 5+), English two. */
|
|
export function count(n: number, ru: [string, string, string], en: [string, string]) {
|
|
const r = pluralRu.select(n)
|
|
return {
|
|
ru: `${n} ${r === 'one' ? ru[0] : r === 'few' ? ru[1] : ru[2]}`,
|
|
en: `${n} ${pluralEn.select(n) === 'one' ? en[0] : en[1]}`,
|
|
}
|
|
}
|
|
|
|
export const monthYear = (iso: string | undefined, lang: Lang) =>
|
|
iso ? new Date(iso).toLocaleDateString(lang, { month: 'short', year: 'numeric' }) : ''
|
|
|
|
// Where the other pages of shanaty.ru live. Empty in the production build (root-relative links); the default is
|
|
// for builds that run elsewhere (dev, GitHub Pages), where relative links would point at the wrong site.
|
|
export const SITE = process.env.NEXT_PUBLIC_SITE_ORIGIN ?? 'https://shanaty.ru'
|