perf+security: fix build, secure downloads, dedupe translations, refactor i18n
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m49s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m49s
Frontend:
- Fix Framer Motion / motion-dom build error by pinning framer-motion to
11.18.2 (compatible with React 19 and Next.js 16).
- Add cross-env and build:local script to bypass standalone symlink errors
on Windows without Developer Mode.
- Allow NEXT_OUTPUT=default to disable standalone output for local builds.
- Refactor i18n: split 14,177-line src/lib/i18n.tsx into per-locale,
per-namespace JSON files under src/lib/i18n/messages/.
- Load English synchronously; other locales loaded on demand via dynamic
imports (reduces initial bundle, improves maintainability).
- Remove unused next-intl message files src/messages/en.json and fr.json.
Backend:
- Remove insecure legacy /api/v1/download/{filename} and /api/v1/cleanup/{filename}
endpoints. The job-based /api/v1/download/{job_id} already enforces ownership.
- Deduplicate texts in TranslationService.translate_batch before sending them
to the provider, reducing API calls for repeated strings.
- Pin httpx to <0.28 to fix TestClient incompatibility with starlette 0.35.1.
- Add pytest-cov and ruff dev dependencies/config.
DevOps:
- Remove hardcoded Grafana password from docker-compose.yml and
docker-compose.monitoring.yml; use GRAFANA_PASSWORD env var.
- Change default TRANSLATION_SERVICE from ollama to google in
docker-compose.yml (Ollama is an optional profile).
- Add GRAFANA_PASSWORD to .env.example.
- Add .coverage and frontend/pnpm-workspace.yaml to .gitignore.
Tests:
- Update API versioning tests for removed legacy endpoints.
- Add tests/test_translation_service.py for deduplication behavior.
Verified:
- pnpm run build:local passes.
- uv run pytest tests/test_providers/* tests/test_translation_service.py
tests/test_story_3_5_api_versioning.py tests/test_download_endpoint.py
tests/test_translators/test_excel_translator.py: provider/translator tests
pass; one pre-existing French error-message test still fails (message is
returned in English, unrelated to this change).
This commit is contained in:
151
frontend/src/lib/i18n/messages/ru/pricing.json
Normal file
151
frontend/src/lib/i18n/messages/ru/pricing.json
Normal file
@@ -0,0 +1,151 @@
|
||||
{
|
||||
"pricing.nav.back": "Назад",
|
||||
"pricing.nav.home": "Главная",
|
||||
"pricing.nav.mySubscription": "Моя подписка",
|
||||
"pricing.header.badge": "ИИ-модели обновлены — март 2026",
|
||||
"pricing.header.title": "Тариф для любых задач",
|
||||
"pricing.header.subtitle": "Переводите документы Word, Excel и PowerPoint с сохранением исходного форматирования. Без API-ключей.",
|
||||
"pricing.billing.monthly": "Ежемесячно",
|
||||
"pricing.billing.yearly": "Ежегодно",
|
||||
"pricing.plans.free.name": "Бесплатный",
|
||||
"pricing.plans.starter.name": "Starter",
|
||||
"pricing.plans.pro.name": "Pro",
|
||||
"pricing.plans.business.name": "Business",
|
||||
"pricing.plans.enterprise.name": "Enterprise",
|
||||
"pricing.plans.free.description": "Отлично для знакомства с приложением",
|
||||
"pricing.plans.starter.description": "Для частных лиц и небольших проектов",
|
||||
"pricing.plans.pro.description": "Для профессионалов и растущих команд",
|
||||
"pricing.plans.business.description": "Для команд и организаций",
|
||||
"pricing.plans.enterprise.description": "Индивидуальные решения для крупных организаций",
|
||||
"pricing.plans.pro.highlight": "Самый популярный",
|
||||
"pricing.plans.pro.badge": "ПОПУЛЯРНЫЙ",
|
||||
"pricing.plans.enterprise.badge": "ПО ЗАПРОСУ",
|
||||
"pricing.plans.free.feat1": "5 документов / месяц",
|
||||
"pricing.plans.free.feat2": "До 15 страниц на документ",
|
||||
"pricing.plans.free.feat3": "Google Переводчик включён",
|
||||
"pricing.plans.free.feat4": "Все языки (130+)",
|
||||
"pricing.plans.free.feat5": "Поддержка сообщества",
|
||||
"pricing.plans.starter.feat1": "50 документов / месяц",
|
||||
"pricing.plans.starter.feat2": "До 50 страниц на документ",
|
||||
"pricing.plans.starter.feat3": "Google Переводчик + DeepL",
|
||||
"pricing.plans.starter.feat4": "Файлы до 10 МБ",
|
||||
"pricing.plans.starter.feat5": "Поддержка по эл. почте",
|
||||
"pricing.plans.starter.feat6": "История за 30 дней",
|
||||
"pricing.plans.pro.feat1": "200 документов / месяц",
|
||||
"pricing.plans.pro.feat2": "До 200 страниц на документ",
|
||||
"pricing.plans.pro.feat3": "Базовый ИИ-перевод",
|
||||
"pricing.plans.pro.feat4": "Google Переводчик + DeepL",
|
||||
"pricing.plans.pro.feat5": "Файлы до 25 МБ",
|
||||
"pricing.plans.pro.feat6": "Пользовательские глоссарии",
|
||||
"pricing.plans.pro.feat7": "Приоритетная поддержка",
|
||||
"pricing.plans.pro.feat8": "История за 90 дней",
|
||||
"pricing.plans.business.feat1": "1 000 документов / месяц",
|
||||
"pricing.plans.business.feat2": "До 500 страниц на документ",
|
||||
"pricing.plans.business.feat3": "Базовый + Премиум ИИ (Claude Haiku)",
|
||||
"pricing.plans.business.feat4": "Все провайдеры перевода",
|
||||
"pricing.plans.business.feat5": "Файлы до 50 МБ",
|
||||
"pricing.plans.business.feat6": "Доступ к API (10 000 вызовов/мес.)",
|
||||
"pricing.plans.business.feat7": "Вебхуки уведомлений",
|
||||
"pricing.plans.business.feat8": "Выделенная поддержка",
|
||||
"pricing.plans.business.feat9": "История за 1 год",
|
||||
"pricing.plans.business.feat10": "Расширенная аналитика",
|
||||
"pricing.plans.enterprise.feat1": "Безлимитные документы",
|
||||
"pricing.plans.enterprise.feat2": "Все ИИ-модели (GPT-5, Claude Opus 4.6…)",
|
||||
"pricing.plans.enterprise.feat3": "Локальное развёртывание или выделенное облако",
|
||||
"pricing.plans.enterprise.feat4": "SLA 99,9 % гарантировано",
|
||||
"pricing.plans.enterprise.feat5": "Выделенная поддержка 24/7",
|
||||
"pricing.plans.enterprise.feat6": "White-label",
|
||||
"pricing.plans.enterprise.feat7": "Безлимитные команды",
|
||||
"pricing.plans.enterprise.feat8": "Индивидуальные интеграции",
|
||||
"pricing.card.onRequest": "По запросу",
|
||||
"pricing.card.free": "Бесплатно",
|
||||
"pricing.card.perMonth": "/мес.",
|
||||
"pricing.card.billedYearly": "К оплате {price} € / год",
|
||||
"pricing.card.documents": "Документы",
|
||||
"pricing.card.pagesMax": "Макс. страниц",
|
||||
"pricing.card.aiTranslation": "ИИ-перевод",
|
||||
"pricing.card.unlimited": "Безлимит",
|
||||
"pricing.card.perMonthStat": "/ месяц",
|
||||
"pricing.card.perDoc": "стр. / док.",
|
||||
"pricing.card.aiEssential": "Базовый",
|
||||
"pricing.card.aiEssentialPremium": "Базовый + Премиум",
|
||||
"pricing.card.aiCustom": "Индивидуальный",
|
||||
"pricing.card.myPlan": "Мой тариф",
|
||||
"pricing.card.managePlan": "Управлять тарифом",
|
||||
"pricing.card.startFree": "Начать бесплатно",
|
||||
"pricing.card.contactUs": "Связаться с нами",
|
||||
"pricing.card.choosePlan": "Выбрать этот тариф",
|
||||
"pricing.card.processing": "Обработка…",
|
||||
"pricing.comparison.title": "Подробное сравнение",
|
||||
"pricing.comparison.subtitle": "Всё, что входит в каждый тариф",
|
||||
"pricing.comparison.feature": "Функция",
|
||||
"pricing.comparison.docsPerMonth": "Документы / месяц",
|
||||
"pricing.comparison.pagesMaxPerDoc": "Макс. страниц / документ",
|
||||
"pricing.comparison.maxFileSize": "Макс. размер файла",
|
||||
"pricing.comparison.googleTranslation": "Google Переводчик",
|
||||
"pricing.comparison.deepl": "DeepL",
|
||||
"pricing.comparison.aiEssential": "Базовый ИИ-перевод",
|
||||
"pricing.comparison.aiPremium": "Премиум ИИ-перевод",
|
||||
"pricing.comparison.apiAccess": "Доступ к API",
|
||||
"pricing.comparison.priorityProcessing": "Приоритетная обработка",
|
||||
"pricing.comparison.support": "Поддержка",
|
||||
"pricing.comparison.support.community": "Сообщество",
|
||||
"pricing.comparison.support.email": "Эл. почта",
|
||||
"pricing.comparison.support.priority": "Приоритетная",
|
||||
"pricing.comparison.support.dedicated": "Выделенная",
|
||||
"pricing.comparison.mb": "МБ",
|
||||
"pricing.credits.title": "Дополнительные кредиты",
|
||||
"pricing.credits.subtitle": "Нужно больше? Купите кредиты поштучно, без подписки.",
|
||||
"pricing.credits.perPage": "1 кредит = 1 переведённая страница.",
|
||||
"pricing.credits.bestValue": "Лучшая ценность",
|
||||
"pricing.credits.unit": "кредитов",
|
||||
"pricing.credits.centsPerCredit": "коп. / кредит",
|
||||
"pricing.credits.buy": "Купить",
|
||||
"pricing.trust.encryption.title": "Сквозное шифрование",
|
||||
"pricing.trust.encryption.sub": "TLS 1.3 + AES-256 при хранении",
|
||||
"pricing.trust.languages.title": "130+ языков",
|
||||
"pricing.trust.languages.sub": "Включая арабский, персидский, иврит (RTL)",
|
||||
"pricing.trust.parallel.title": "Параллельная обработка",
|
||||
"pricing.trust.parallel.sub": "Сверхбыстрая многопоточная ИИ",
|
||||
"pricing.trust.availability.title": "Доступно 24/7",
|
||||
"pricing.trust.availability.sub": "99,9 % гарантированный аптайм",
|
||||
"pricing.aiModels.title": "Наши ИИ-модели — март 2026",
|
||||
"pricing.aiModels.essential.title": "Базовый ИИ-перевод",
|
||||
"pricing.aiModels.essential.plan": "Тариф Pro",
|
||||
"pricing.aiModels.essential.descPrefix": "На базе",
|
||||
"pricing.aiModels.essential.descSuffix": "— самой экономичной ИИ-модели 2026 года. Качество на уровне frontier-моделей при стоимости в десятки раз ниже.",
|
||||
"pricing.aiModels.essential.modelName": "наша базовая ИИ-модель",
|
||||
"pricing.aiModels.essential.context": "163K токенов контекста",
|
||||
"pricing.aiModels.essential.value": "Отличное соотношение цены и качества",
|
||||
"pricing.aiModels.premium.title": "Премиум ИИ-перевод",
|
||||
"pricing.aiModels.premium.plan": "Тариф Business",
|
||||
"pricing.aiModels.premium.descPrefix": "На базе",
|
||||
"pricing.aiModels.premium.descSuffix": "от Anthropic — высокая точность на юридических, медицинских и сложных технических документах.",
|
||||
"pricing.aiModels.premium.context": "200K токенов контекста",
|
||||
"pricing.aiModels.premium.precision": "Наивысшая точность",
|
||||
"pricing.faq.title": "Часто задаваемые вопросы",
|
||||
"pricing.faq.q1": "Могу ли я сменить тариф в любое время?",
|
||||
"pricing.faq.a1": "Да. Повышение тарифа применяется сразу с пересчётом. Понижение вступает в силу в конце текущего периода.",
|
||||
"pricing.faq.q2": "Что такое «Базовый ИИ-перевод»?",
|
||||
"pricing.faq.a2": "Это наш ИИ-движок. Он понимает контекст ваших документов, сохраняет вёрстку и обрабатывает технические термины намного лучше классического перевода.",
|
||||
"pricing.faq.q3": "В чём разница между базовым и премиум ИИ-переводом?",
|
||||
"pricing.faq.a3": "Базовый ИИ использует оптимизированную модель (отличное соотношение цены и качества). Премиум ИИ использует Claude 3.5 Haiku от Anthropic, более точный на юридических, медицинских и сложных технических документах.",
|
||||
"pricing.faq.q4": "Сохраняются ли мои документы после перевода?",
|
||||
"pricing.faq.a4": "Переведённые файлы доступны в зависимости от тарифа (30 дней Starter, 90 дней Pro, 1 год Business). Они зашифрованы при хранении и передаче.",
|
||||
"pricing.faq.q5": "Что произойдёт при превышении месячной квоты?",
|
||||
"pricing.faq.a5": "Вы можете докупить кредиты поштучно или повысить тариф. Уведомление приходит при достижении 80 % использования.",
|
||||
"pricing.faq.q6": "Есть ли бесплатный пробный период для платных тарифов?",
|
||||
"pricing.faq.a6": "Бесплатный тариф постоянный и не требует банковской карты. Для тарифов Pro и Business свяжитесь с нами для получения 14-дневного пробного доступа.",
|
||||
"pricing.faq.q7": "Какие форматы файлов поддерживаются?",
|
||||
"pricing.faq.a7": "Word (.docx), Excel (.xlsx/.xls), PowerPoint (.pptx), а скоро и PDF. Все тарифы поддерживают одинаковые форматы.",
|
||||
"pricing.cta.title": "Готовы начать?",
|
||||
"pricing.cta.subtitle": "Начните бесплатно, без банковской карты. Повысьте тариф, когда понадобится.",
|
||||
"pricing.cta.createAccount": "Создать бесплатный аккаунт",
|
||||
"pricing.cta.login": "Войти",
|
||||
"pricing.toast.demo": "Деморежим — Stripe ещё не настроен. В рабочей среде вы были бы перенаправлены на страницу оплаты для активации тарифа {planId}.",
|
||||
"pricing.toast.networkError": "Сетевая ошибка. Пожалуйста, попробуйте снова.",
|
||||
"pricing.toast.paymentError": "Ошибка при создании платежа.",
|
||||
"pricing.dashboard": "Панель",
|
||||
"pricing.okSymbol": "✓",
|
||||
"pricing.errSymbol": "✕"
|
||||
}
|
||||
Reference in New Issue
Block a user