- Страницы обоих брендов из блоков Payload (D-029): главная, цены, локации, поддержка, 4 юридические, 404 и 500. Коллекции pages (черновики и версии) и faq с местами показа, 12 типов блоков; поля sites — почта и Telegram поддержки, часы работы, SEO по умолчанию. - Карта и глобус рисуются на сервере (d3-geo), контуры во внешнем SVG через <use>; выбор локации синхронизирован между картой и сеткой. - Тексты сайта и юридические черновики на 5 языках: de, fr, es — перевод с глоссарием; seed создаёт страницы и FAQ, только если их нет, SEED_CONTENT=reset пересоздаёт. - SEO: title и описания, canonical, hreflang с x-default, sitemap.xml и robots.txt на каждый домен, картинки для соцсетей. - Статическая сборка и пересборка через revalidatePath из хуков Payload (D-030); /svc/internal/revalidate для проверки. - 404 — статичная страница со статусом 404 через proxy; на сайте только опубликованные страницы. - Производительность: Client Hints темы Payload только в админке, предзагрузка 2 файлов шрифтов вместо 6; Lighthouse mobile 97–99. - Контраст --ink-3 по WCAG AA, радиокнопки вместо div role=button. - Документация: итоги 1b, глоссарий de/fr/es, трактовки юридических черновиков подтверждены, переносимые вопросы — в этапах 3e–3h. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
93 lines
12 KiB
Markdown
93 lines
12 KiB
Markdown
# 06. Языки и валюты на сайте
|
||
|
||
## 1. Языки
|
||
|
||
1. Сейчас: `en` (по умолчанию), `ru`, `de`, `fr`, `es`.
|
||
2. Позже: `pt-br` (бразильский португальский) и `ja`. Для японского понадобится запасной шрифт: Commissioner и Unbounded не содержат японских знаков.
|
||
3. Список языков задаётся в конфиге Payload и next-intl (код). У каждого домена в базе — включённые языки и язык по умолчанию.
|
||
4. Интерфейс админки — `ru` и `en`.
|
||
|
||
## 2. Два слоя переводов
|
||
|
||
| Что | Где | Кто правит |
|
||
|---|---|---|
|
||
| Интерфейс: кнопки, подписи, ошибки, сообщения форм | `src/i18n/messages/{en,ru,de,fr,es}.json`, next-intl | разработка, через git |
|
||
| Контент: тарифы, локации, FAQ, страницы, шаблоны писем, тексты бота | локализованные поля Payload | админка, без деплоя |
|
||
|
||
1. В коде компонентов нет строк на конкретном языке, только ключи переводов.
|
||
2. Нет перевода на языке — показывается английский. Отдельная проверка выводит список непереведённых ключей.
|
||
3. Множественные числа — ICU в next-intl: «12 серверов», «3 сервера», «1 сервер».
|
||
|
||
## 3. URL
|
||
|
||
1. Английский без префикса, остальные — с префиксом: `veilix.app/pricing`, `veilix.app/ru/pricing`, `veilix.app/de/pricing`. Точнее, без префикса открывается язык домена по умолчанию (`domains.defaultLocale`, сейчас везде en), а адрес с его префиксом (`/en/pricing`) перенаправляется на адрес без префикса.
|
||
2. Так же в кабинете: `my.veilix.app/keys`, `my.veilix.app/ru/keys`.
|
||
3. MiniApp: адрес в BotFather один, поэтому язык берётся из профиля пользователя или из Telegram; префикс в URL необязателен.
|
||
4. Пути одинаковые для всех языков (английские): `/pricing`, `/locations`, `/support`, `/legal/terms`, `/keys`, `/billing`, `/referral`, `/order`, `/login`.
|
||
5. Язык, не включённый на домене, — 404.
|
||
|
||
## 4. Определение языка
|
||
|
||
1. Порядок: язык из URL → выбранный ранее (cookie `NEXT_LOCALE`, у вошедшего — язык профиля) → язык браузера (`Accept-Language`) среди включённых → страна из заголовка nginx `X-Geo-Country` (MaxMind) → `en`.
|
||
2. Перенаправление на версию с префиксом — с адреса без префикса и только если выбран не язык домена по умолчанию ([D-024](decisions/D-024-locale-redirect.md)). Есть cookie `NEXT_LOCALE` — ведём на язык из cookie; cookie нет — определяем по языку браузера и стране. Перенаправляются только GET и HEAD. Поисковых ботов не перенаправляем никогда: так рекомендует Google.
|
||
3. Переключатель языка ставит cookie `NEXT_LOCALE`. У вошедшего пользователя язык сохраняется ещё и в профиле: на нём уходят письма и сообщения бота.
|
||
4. Соответствие стран языкам по умолчанию: RU, BY, KZ, KG → ru; DE, AT → de; FR → fr; ES и испаноязычные страны Латинской Америки → es (Бразилия — en, пока нет pt-br); остальные → en. Таблица — `src/core/routing/locale.ts`.
|
||
|
||
## 5. SEO
|
||
|
||
1. `hreflang` на все включённые языки и `x-default` на английскую версию.
|
||
2. `canonical` на основной домен, в том числе с зеркал.
|
||
3. `sitemap.xml` для каждого маркетингового домена с вариантами всех языков. `robots.txt` — на каждый домен: индексация разрешена только маркетинговым доменам с флагом `indexable`, остальным закрыто всё. Оба файла proxy переписывает на `/svc/seo/{домен}/…`.
|
||
4. Кабинет и MiniApp не индексируются (`noindex`).
|
||
5. Атрибут `lang` у `<html>` соответствует языку страницы.
|
||
6. `<title>`: у главной — свой заголовок целиком, у остальных страниц — по шаблону сайта `sites.seo.titleTemplate` («%s · Вейликс»). Описание — из `pages.seo`, иначе описание сайта. Плейсхолдеры цен и числа стран в них заполняются.
|
||
7. Картинка для соцсетей: своя у страницы (`pages.seo.image`) или сайта (`sites.seo.ogImage`), иначе создаётся `/svc/og/{сайт}/{язык}/{страница}` — 1200×630, заголовок страницы в цветах бренда.
|
||
8. 404 отдаётся со статусом 404 и `noindex`.
|
||
|
||
## 6. Валюта
|
||
|
||
1. Переключатель валюты отдельный от языка, стоит рядом с переключателем языка в шапке и подвале. В макете его нет — добавляется в стиле переключателя языка.
|
||
2. Валюта не определяется по стране: из России часто заходят через VPN.
|
||
3. По умолчанию — валюта домена для языка (`domains.localeCurrency`: ru → RUB), иначе `domains.defaultCurrency` (USD).
|
||
4. Выбор хранится в cookie `vx_currency`. Валюта не входит в URL: маркетинговые страницы заранее собраны во всех валютах, proxy выбирает вариант по cookie. Поисковые боты видят валюту по умолчанию.
|
||
5. Ссылка «Купить» передаёт валюту в оформление заказа (`?currency=`). У вошедшего пользователя в кабинете всегда валюта аккаунта ([04-billing.md](04-billing.md), раздел 2).
|
||
6. Форматирование — `Intl.NumberFormat` с узким символом валюты: «4 900 ₽» в русском, «₽4,900» в английском, «$49». Неразрывные пробелы ставит Intl. Даты — `Intl.DateTimeFormat`: «14 октября 2026».
|
||
|
||
## 7. Как переводим
|
||
|
||
1. Источник: русские тексты макетов и английские из словаря макета `design/handoff/project/i18n.js` (около 515 строк). Интерфейс ложится в `messages/*.json`, тексты страниц и остальной контент — в Payload ([D-029](decisions/D-029-pages-blocks.md)).
|
||
2. Немецкий, французский, испанский переводит Claude с глоссарием в каждом этапе, вместе с RU и EN ([D-033](decisions/D-033-translations.md)). Вычитки носителями нет, поэтому глоссарий и контекст обязательны. Финальная проверка — на публичном запуске (этап 3h).
|
||
3. В юридических текстах пункт: «При расхождениях между версиями действует английская».
|
||
4. Новая строка интерфейса или контента сразу появляется на 5 языках.
|
||
|
||
## 8. Глоссарий
|
||
|
||
| RU | EN | DE | FR | ES | Примечание |
|
||
|---|---|---|---|---|---|
|
||
| Вейликс / ВейликсВПН | Veilix / VeilixVPN | Veilix / VeilixVPN | Veilix / VeilixVPN | Veilix / VeilixVPN | не переводится |
|
||
| ключ | key | Schlüssel | clé | clave | купленная единица доступа |
|
||
| локация | location | Standort | emplacement | ubicación | |
|
||
| тариф | plan | Tarif | forfait | plan | |
|
||
| подписка | subscription | Abonnement | abonnement | suscripción | у mass на сайте |
|
||
| подключение | connection | Verbindung | connexion | conexión | |
|
||
| устройство | device | Gerät | appareil | dispositivo | |
|
||
| индивидуальный IP | dedicated IP | dedizierte IP-Adresse | IP dédiée | IP dedicada | |
|
||
| RU-адрес, российский адрес | RU address, Russian address | RU-Adresse, russische Adresse | adresse RU, adresse russe | dirección RU, dirección rusa | |
|
||
| кабинет | account | Kundenkonto | espace client | área de cliente | |
|
||
| баланс, счёт | balance | Guthaben | solde | saldo | |
|
||
| пополнить | top up | aufladen | recharger | recargar | |
|
||
| продление, автопродление | renewal, auto-renewal | Verlängerung, automatische Verlängerung | renouvellement, renouvellement automatique | renovación, renovación automática | |
|
||
| льготный период | grace period | Kulanzfrist | délai de grâce | período de gracia | |
|
||
| реферальная программа | referral program | Empfehlungsprogramm | programme de parrainage | programa de referidos | |
|
||
| серверы в наличии | servers available | Server verfügbar | serveurs disponibles | servidores disponibles | статус локации dedicated |
|
||
| установим за 24 часа | ready within 24 hours | in 24 Stunden bereit | prêt sous 24 heures | listo en 24 horas | статус локации dedicated |
|
||
| включено | included | inklusive | inclus | incluido | статус локации mass |
|
||
| скоро | coming soon | in Kürze | bientôt | próximamente | статус локации mass |
|
||
| цены | pricing | Preise | Tarifs | Precios | пункт меню и страница; тариф как продукт — по строке «тариф» |
|
||
| поддержка | support | Support | Assistance | Soporte | |
|
||
| войти | log in | Anmelden | Se connecter | Entrar | кнопка в шапке шириной 78 px |
|
||
| счёт и платежи | billing | Guthaben & Zahlungen | Facturation | Saldo y pagos | раздел кабинета |
|
||
| документы | legal | Rechtliches | Informations légales | Legal | раздел подвала; во Франции «Mentions légales» — отдельная обязательная страница |
|
||
|
||
Обращение к пользователю: de — «Sie», fr — «vous», es — «tú» (как принято у потребительских сервисов в Испании и Латинской Америке). Типографика: de — кавычки „…“ и короткое тире « – »; fr — « … » и неразрывный пробел перед `: ; ? !`; es — «…», ¿…? и ¡…!. Длинные немецкие слова в узких местах — с мягким переносом (U+00AD). Названия протоколов и приложений (WireGuard, AmneziaWG, Xray, VLESS, Hysteria2, XHTTP, Happ) не переводятся.
|