From 65e42e7d44f143fe88cc0438ad57bd0048e789b7 Mon Sep 17 00:00:00 2001 From: emil Date: Sat, 9 May 2026 16:49:57 +0300 Subject: [PATCH] Add Russian language version of the site - New i18n system: src/i18n/translations.ts with en/ru translation objects - LanguageSwitcher component (fixed top-right EN/RU toggle) - BaseLayout updated with lang prop, hreflang links, auto-redirect for Russian browsers - All 10 generator components updated to use T.* translations - GeneratorCard updated to show ruTitle/ruDescription and link to /ru/ routes - SeoBlock updated with translated section headers - New /ru/ home page and /ru/generators/[slug] dynamic route (all 10 generators) - Russian SEO content (howTo/whenTo) for all generator pages - English pages explicitly pass lang="en" Co-Authored-By: Claude Sonnet 4.6 --- src/components/GeneratorCard.astro | 19 +- src/components/LanguageSwitcher.astro | 41 ++++ src/components/SeoBlock.astro | 11 +- src/components/generators/CardGenerator.astro | 79 +++--- src/components/generators/CoinGenerator.astro | 70 +++--- .../generators/ColorGenerator.astro | 5 +- src/components/generators/DiceGenerator.astro | 45 ++-- src/components/generators/ListGenerator.astro | 91 +++---- .../generators/LotteryGenerator.astro | 159 ++++-------- .../generators/NumberGenerator.astro | 127 +++------- .../generators/PasswordGenerator.astro | 170 ++++--------- src/components/generators/UuidGenerator.astro | 30 ++- src/components/generators/WheelSpinner.astro | 44 ++-- src/data/generators.ts | 44 ++++ src/i18n/translations.ts | 138 +++++++++++ src/layouts/BaseLayout.astro | 32 ++- src/pages/generators/cards.astro | 2 +- src/pages/generators/coin.astro | 2 +- src/pages/generators/colors.astro | 2 +- src/pages/generators/dice.astro | 2 +- src/pages/generators/list.astro | 2 +- src/pages/generators/lottery.astro | 2 +- src/pages/generators/numbers.astro | 2 +- src/pages/generators/password.astro | 2 +- src/pages/generators/uuid.astro | 2 +- src/pages/generators/wheel.astro | 2 +- src/pages/index.astro | 9 +- src/pages/ru/generators/[slug].astro | 227 ++++++++++++++++++ src/pages/ru/index.astro | 50 ++++ 29 files changed, 893 insertions(+), 518 deletions(-) create mode 100644 src/components/LanguageSwitcher.astro create mode 100644 src/i18n/translations.ts create mode 100644 src/pages/ru/generators/[slug].astro create mode 100644 src/pages/ru/index.astro diff --git a/src/components/GeneratorCard.astro b/src/components/GeneratorCard.astro index 9f54261..c43ae90 100644 --- a/src/components/GeneratorCard.astro +++ b/src/components/GeneratorCard.astro @@ -1,14 +1,21 @@ --- import type { Generator } from '../data/generators'; +import { useT } from '../i18n/translations'; +import type { Lang } from '../i18n/translations'; interface Props { generator: Generator; + lang?: Lang; } -const { generator } = Astro.props; -const { slug, title, description, icon, status } = generator; +const { generator, lang = 'en' } = Astro.props; +const T = useT(lang); +const { slug, icon, status } = generator; const isLive = status === 'live'; -const href = `/generators/${slug}/`; +const isRu = lang === 'ru'; +const title = isRu ? generator.ruTitle : generator.title; +const description = isRu ? generator.ruDescription : generator.description; +const href = isRu ? `/ru/generators/${slug}/` : `/generators/${slug}/`; const icons: Record = { hash: ``, @@ -32,7 +39,7 @@ const icons: Record = {

@@ -43,12 +50,12 @@ const icons: Record = { ) : (

{title}

diff --git a/src/components/LanguageSwitcher.astro b/src/components/LanguageSwitcher.astro new file mode 100644 index 0000000..a352d9b --- /dev/null +++ b/src/components/LanguageSwitcher.astro @@ -0,0 +1,41 @@ +--- +interface Props { + lang: 'en' | 'ru'; + alternatePath: string; +} + +const { lang, alternatePath } = Astro.props; +const targetLang = lang === 'en' ? 'ru' : 'en'; +--- + +
+ EN + RU +
+ + diff --git a/src/components/SeoBlock.astro b/src/components/SeoBlock.astro index 7cb73cb..270640d 100644 --- a/src/components/SeoBlock.astro +++ b/src/components/SeoBlock.astro @@ -1,21 +1,26 @@ --- +import { useT } from '../i18n/translations'; +import type { Lang } from '../i18n/translations'; + interface Props { howTo: string[]; whenTo: string[]; + lang?: Lang; } -const { howTo, whenTo } = Astro.props; +const { howTo, whenTo, lang = 'en' } = Astro.props; +const T = useT(lang); ---
-

How to use

+

{T.howToUse}

    {howTo.map((step) =>
  1. {step}
  2. )}
-

When to use

+

{T.whenToUse}

    {whenTo.map((item) =>
  • {item}
  • )}
diff --git a/src/components/generators/CardGenerator.astro b/src/components/generators/CardGenerator.astro index 3217ba8..42c340e 100644 --- a/src/components/generators/CardGenerator.astro +++ b/src/components/generators/CardGenerator.astro @@ -1,33 +1,35 @@ --- -// Interactive card generator — runs on the client via inline script +import { useT } from '../../i18n/translations'; +const isRu = Astro.url.pathname.startsWith('/ru'); +const T = useT(isRu ? 'ru' : 'en'); ---
- +
diff --git a/src/components/generators/PasswordGenerator.astro b/src/components/generators/PasswordGenerator.astro index 92afef6..129acfd 100644 --- a/src/components/generators/PasswordGenerator.astro +++ b/src/components/generators/PasswordGenerator.astro @@ -1,193 +1,115 @@ --- -// Interactive password generator — runs on the client via inline script +import { useT } from '../../i18n/translations'; +const isRu = Astro.url.pathname.startsWith('/ru'); +const T = useT(isRu ? 'ru' : 'en'); ---
-
- + 16
- -
- 464 -
+ +
464
-
{[ - { id: 'pg-upper', label: 'Uppercase (A–Z)' }, - { id: 'pg-lower', label: 'Lowercase (a–z)' }, - { id: 'pg-digits', label: 'Digits (0–9)' }, - { id: 'pg-symbols', label: 'Symbols (!@#…)' }, + { id: 'pg-upper', label: T.uppercase }, + { id: 'pg-lower', label: T.lowercase }, + { id: 'pg-digits', label: T.digits }, + { id: 'pg-symbols', label: T.symbols }, ].map(({ id, label }) => ( ))}
- +
- - - Copied + {T.copied}
-
+