Skip to content

Commit 677d5d1

Browse files
author
Ivan Bochkarev
committed
feat: добавление локализации и новых скриптов для проекта
- Переведены сообщения об ошибках и текстовые метки на русский язык в компонентах, включая страницы и сообщения об ошибках. - Добавлен новый скрипт `audit:docs` в `package.json` для аудита переведённых файлов документации. - Обновлены инструкции по деплою на Vercel в README, включая переменные окружения и команды сборки. - Обновлён план перевода на русский язык с завершением нескольких фаз.
1 parent 1adc3a6 commit 677d5d1

File tree

22 files changed

+362
-75
lines changed

22 files changed

+362
-75
lines changed

.cursor/plans/nuxt_russian_translation.plan.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ todos:
1616
status: completed
1717
- id: phase1-vercel-env
1818
content: "Фаза 1.5: Обновление Vercel env-переменных, проверка деплоя"
19-
status: pending
19+
status: completed
2020
- id: phase1-nuxthub
2121
content: "Фаза 1.6: Обновление NuxtHub (0.9.0 -> 0.10.6+), миграции Drizzle"
22-
status: pending
22+
status: completed
2323
- id: phase2-glossary
2424
content: "Фаза 2.1: Создание/обновление глоссария терминов GLOSSARY.md"
2525
status: completed
@@ -31,13 +31,13 @@ todos:
3131
status: completed
3232
- id: phase2-pages
3333
content: "Фаза 2.4: Перевод страниц (index, blog, deploy, modules, enterprise, team и др.)"
34-
status: pending
34+
status: completed
3535
- id: phase2-meta
3636
content: "Фаза 2.5: Перевод мета-данных (llms, OG, title templates)"
37-
status: pending
37+
status: completed
3838
- id: phase3-audit
3939
content: "Фаза 3.0: Аудит уже переведённых файлов документации, список оставшихся"
40-
status: pending
40+
status: completed
4141
- id: phase3-getting-started
4242
content: "Фаза 3.1: Перевод/обновление docs/1.getting-started/ (18 файлов)"
4343
status: pending
@@ -70,18 +70,18 @@ todos:
7070
status: pending
7171
- id: phase5-ci
7272
content: "Фаза 5: GitHub Action для регулярной синхронизации с upstream"
73-
status: pending
73+
status: completed
7474
isProject: true
7575
---
7676

7777
# План реанимации [nuxt-ru.vercel.app](http://nuxt-ru.vercel.app)
7878

7979
План перенесён в репозиторий. Выполнять по фазам.
8080

81-
## Фаза 1: Деплой (1.1–1.4 выполнены)
81+
## Фаза 1: Деплой (выполнена)
8282

83-
- **1.5** В Vercel: задать `NUXT_SESSION_PASSWORD`, `NUXT_GITHUB_TOKEN` (опц.), проверить Build/Install команды.
84-
- **1.6** NuxtHub: при необходимости `nuxthub link`, `pnpm db:generate` / `pnpm db:migrate`.
83+
- **1.5** Инструкция по env и сборке добавлена в README (раздел «Деплой на Vercel»). Вручную в Vercel задать `NUXT_SESSION_PASSWORD`, `NUXT_PUBLIC_SITE_URL`, при необходимости `NUXT_GITHUB_TOKEN`.
84+
- **1.6** NuxtHub ^0.10.6 в проекте, скрипты `db:generate` / `db:migrate` есть. Инструкция в README; при необходимости — `nuxthub link`.
8585

8686
## Фаза 2: Перевод сайта
8787

@@ -93,6 +93,7 @@ isProject: true
9393

9494
## Фаза 3: Документация (translation-gang/nuxt, docs/)
9595

96+
- **3.0** Выполнено: скрипт `scripts/audit-docs-translation.mjs` и шаблон отчёта `docs/TRANSLATION_AUDIT.md`. Запуск: `NUXT_V4_PATH=/path/to/nuxt pnpm run audit:docs` — перезапишет отчёт списками переведённых/не переведённых по разделам.
9697
- **3.0** Аудит переведённого.
9798
- **3.1** getting-started (18) → **3.8** bridge + migration (21).
9899

@@ -101,9 +102,9 @@ isProject: true
101102
- **4.1** content/blog/ (~42).
102103
- **4.2** content/deploy/ (~22).
103104

104-
## Фаза 5: CI
105+
## Фаза 5: CI (выполнена)
105106

106-
- **5** Workflow уже есть: `.github/workflows/sync-upstream.yml`. При необходимости расширить (создание issue при изменениях в upstream).
107+
- **5** Workflow `.github/workflows/sync-upstream.yml`: еженедельно (пн 9:00) и по кнопке проверяет upstream nuxt/nuxt.com; при наличии изменений создаёт issue с метками `translation`, `sync` и списком изменённых файлов.
107108

108109
---
109110

.github/workflows/sync-upstream.yml

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Check upstream changes
1+
name: Sync upstream (nuxt.com)
22

33
on:
44
schedule:
@@ -8,6 +8,9 @@ on:
88
jobs:
99
check-upstream:
1010
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
13+
issues: write
1114
steps:
1215
- uses: actions/checkout@v4
1316
with:
@@ -19,6 +22,36 @@ jobs:
1922
git fetch upstream main
2023
2124
- name: List changed files
25+
id: diff
2226
run: |
2327
echo "## Изменённые файлы в upstream" >> $GITHUB_STEP_SUMMARY
24-
git diff HEAD..upstream/main --stat >> $GITHUB_STEP_SUMMARY || echo "Нет изменений" >> $GITHUB_STEP_SUMMARY
28+
CHANGED=$(git diff HEAD..upstream/main --name-only)
29+
if [ -n "$CHANGED" ]; then
30+
echo "has_changes=true" >> $GITHUB_OUTPUT
31+
echo "$CHANGED" >> $GITHUB_STEP_SUMMARY
32+
{
33+
echo "## Изменения в upstream (nuxt/nuxt.com)"
34+
echo ""
35+
echo "Обнаружены отличия от ветки \`main\` upstream. Рекомендуется провести синхронизацию и при необходимости обновить переводы."
36+
echo ""
37+
echo "### Изменённые файлы"
38+
echo '```'
39+
echo "$CHANGED"
40+
echo '```'
41+
echo ""
42+
echo "---"
43+
echo "*Workflow: [Sync upstream](https://github.com/${{ github.repository }}/actions/workflows/sync-upstream.yml)*"
44+
} > upstream-changes.md
45+
else
46+
echo "has_changes=false" >> $GITHUB_OUTPUT
47+
echo "Нет изменений" >> $GITHUB_STEP_SUMMARY
48+
fi
49+
50+
- name: Create issue if upstream changed
51+
if: steps.diff.outputs.has_changes == 'true'
52+
uses: peter-evans/create-issue-from-file@v5
53+
with:
54+
title: "[sync] В upstream nuxt.com есть изменения"
55+
content-filepath: upstream-changes.md
56+
labels: translation,sync
57+
token: ${{ secrets.GITHUB_TOKEN }}

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,46 @@ pnpm dev:full
7070
pnpm build
7171
```
7272

73+
## Деплой на Vercel (фазы 1.5–1.6)
74+
75+
### Переменные окружения в Vercel
76+
77+
В настройках проекта Vercel → Settings → Environment Variables задайте:
78+
79+
**Обязательные для сборки и работы:**
80+
81+
| Переменная | Описание |
82+
|------------|----------|
83+
| `NUXT_SESSION_PASSWORD` | Пароль для шифрования сессий (nuxt-auth-utils). Сгенерировать: `openssl rand -base64 32` |
84+
| `NUXT_PUBLIC_SITE_URL` | URL сайта, например `https://nuxt-ru.vercel.app` |
85+
86+
**Рекомендуемые (иначе часть страниц/API будет падать при пререндере или в рантайме):**
87+
88+
| Переменная | Описание |
89+
|------------|----------|
90+
| `NUXT_GITHUB_TOKEN` | GitHub Personal Access Token с доступом к репозиторию (для модулей, team, stats) |
91+
92+
**Опционально:** см. `.env.example` (Turnstile, Resend, Open Collective, OAuth для админки отзывов и т.д.).
93+
94+
### Сборка в Vercel
95+
96+
Используются настройки из `vercel.json`:
97+
98+
- **Build Command:** `NODE_OPTIONS='--max-old-space-size=8192' pnpm run build`
99+
- **Install Command:** `corepack enable && corepack prepare pnpm@10.29.3 --activate && pnpm install`
100+
101+
При необходимости их можно переопределить в Vercel → Settings → General.
102+
103+
### NuxtHub (1.6)
104+
105+
- В проекте уже используется `@nuxthub/core` ^0.10.6, БД — sqlite (для продакшена на Vercel используется драйвер Vercel).
106+
- Если меняете схему БД в `server/db/schema.ts`, локально выполните:
107+
```bash
108+
pnpm db:generate
109+
pnpm db:migrate
110+
```
111+
- Привязка проекта к NuxtHub (если нужен дашборд/бэкап): `npx nuxthub@latest login` и `npx nuxthub@latest link`.
112+
73113
### Evals для MCP-сервера
74114

75115
Для запуска evals убедитесь, что dev-сервер запущен, создайте API-ключ на https://vercel.com/ai-gateway и добавьте `AI_GATEWAY_API_KEY` в `.env`. Затем: `pnpm eval` или `pnpm eval:ui`.

app/composables/useModules.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ export const useModules = () => {
7878
]
7979

8080
const orders: Filter[] = [
81-
{ key: 'desc', label: 'Desc', icon: 'i-lucide-arrow-down-wide-narrow' },
82-
{ key: 'asc', label: 'Asc', icon: 'i-lucide-arrow-up-wide-narrow' }
81+
{ key: 'desc', label: 'По убыванию', icon: 'i-lucide-arrow-down-wide-narrow' },
82+
{ key: 'asc', label: 'По возрастанию', icon: 'i-lucide-arrow-up-wide-narrow' }
8383
]
8484

8585
const categories = computed<Filter[]>(() => {

app/error.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import type { NuxtError } from '#app'
33
44
useSeoMeta({
5-
title: 'Page not found',
6-
description: 'We are sorry but this page could not be found.'
5+
title: 'Страница не найдена',
6+
description: 'К сожалению, эта страница не найдена.'
77
})
88
99
defineProps<{ error: NuxtError }>()

app/pages/blog/[slug].vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ const links = [
134134
</ULink>
135135
<div class="flex justify-end items-center gap-1.5">
136136
<UButton icon="i-lucide-link" variant="ghost" color="neutral" @click="copyLink">
137-
<span class="sr-only">Copy URL</span>
137+
<span class="sr-only">Копировать URL</span>
138138
Скопировать URL
139139
</UButton>
140140
<UButton
@@ -156,7 +156,7 @@ const links = [
156156
</UPageBody>
157157

158158
<template #right>
159-
<UContentToc v-if="article.body && article.body.toc" :links="article.body.toc.links" title="Table of Contents" highlight>
159+
<UContentToc v-if="article.body && article.body.toc" :links="article.body.toc.links" title="Содержание" highlight>
160160
<template #bottom>
161161
<div class="hidden lg:block space-y-6">
162162
<UPageLinks title="Ссылки" :links="links" />

app/pages/blog/index.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
const { data: page } = await useAsyncData('blog-landing', () => queryCollection('landing').path('/blog').first())
33
if (!page.value) {
4-
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
4+
throw createError({ statusCode: 404, statusMessage: 'Страница не найдена', fatal: true })
55
}
66
definePageMeta({
77
heroBackground: 'opacity-70 -z-10'
@@ -26,7 +26,7 @@ useSeoMeta({
2626
ogTitle: page.value.title
2727
})
2828
defineOgImageComponent('Docs', {
29-
headline: 'Blog',
29+
headline: 'Блог',
3030
title: page.value.title,
3131
description: page.value.description
3232
})
@@ -77,7 +77,7 @@ await fetchList()
7777
height: (index === 0 ? 378 : 246),
7878
alt: `${article.title} image`
7979
}"
80-
:date="formatDateByLocale('en', article.date)"
80+
:date="formatDateByLocale('ru', article.date)"
8181
:authors="article.authors.map(author => ({ ...author, avatar: { ...author.avatar, alt: `${author.name} avatar` } }))"
8282
:badge="{ label: article.category, color: 'primary', variant: 'subtle' }"
8383
:variant="index === 0 ? 'outline' : 'subtle'"

app/pages/deploy/index.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const { fetchList, providers } = useHostingProviders()
77
88
const { data: page } = await useAsyncData('deploy-landing', () => queryCollection('landing').path('/deploy').first())
99
if (!page.value) {
10-
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
10+
throw createError({ statusCode: 404, statusMessage: 'Страница не найдена', fatal: true })
1111
}
1212
1313
const title = page.value.title
@@ -22,7 +22,7 @@ useSeoMeta({
2222
})
2323
2424
defineOgImageComponent('Docs', {
25-
title: 'Deploy Nuxt',
25+
title: 'Развёртывание Nuxt',
2626
description
2727
})
2828
@@ -41,7 +41,7 @@ await fetchList()
4141
:items="providers.map(provider => ({
4242
label: provider.title,
4343
to: provider.path,
44-
badge: provider.sponsor ? 'Sponsor' : undefined
44+
badge: provider.sponsor ? 'Спонсор' : undefined
4545
})).sort((a, b) => a.label.localeCompare(b.label))"
4646
/>
4747
</UPageAside>
@@ -69,7 +69,7 @@ await fetchList()
6969
class="shine absolute top-4 right-4 sm:top-6 sm:right-6"
7070
variant="subtle"
7171
color="important"
72-
label="Sponsor"
72+
label="Спонсор"
7373
/>
7474
<template #title>
7575
{{ deployment.title }}

app/pages/design-kit.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ definePageMeta({
55
66
const { data: page } = await useAsyncData('design-kit', () => queryCollection('designKit').first())
77
if (!page.value) {
8-
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
8+
throw createError({ statusCode: 404, statusMessage: 'Страница не найдена', fatal: true })
99
}
1010
1111
const title = page.value.title

app/pages/enterprise/agencies/[slug].vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ const route = useRoute()
99
1010
const { data: agency } = await useAsyncData(kebabCase(route.path), () => queryCollection('agencies').path(route.path).first())
1111
if (!agency.value) {
12-
throw createError({ statusCode: 404, statusMessage: 'Agency not found', fatal: true })
12+
throw createError({ statusCode: 404, statusMessage: 'Агентство не найдено', fatal: true })
1313
}
1414
1515
const links = computed(() => agency.value
1616
? [{
17-
label: `Visit ${agency.value.title}`,
17+
label: `Перейти на сайт ${agency.value.title}`,
1818
color: 'neutral' as const,
1919
size: 'md' as const,
2020
variant: 'solid' as const,

0 commit comments

Comments
 (0)