2026-02-26 23:09:20 +04:00
import { Translations } from './translations' ;
export const ru : Translations = {
header : {
home : 'Главная' ,
search : 'Поиск' ,
about : 'О нас' ,
contacts : 'Контакты' ,
searchPlaceholder : 'Искать...' ,
catalog : 'Каталог' ,
2026-07-09 01:13:54 +04:00
wishlist : 'Избранное' ,
compare : 'Сравнение' ,
2026-07-09 02:29:12 +04:00
openMenu : 'Открыть меню' ,
closeMenu : 'Закрыть меню' ,
2026-02-26 23:09:20 +04:00
} ,
footer : {
description : 'Современный маркетплейс для комфортных покупок' ,
company : 'Компания' ,
aboutUs : 'О нас' ,
contacts : 'Контакты' ,
requisites : 'Реквизиты' ,
support : 'Поддержка' ,
faq : 'FAQ' ,
delivery : 'Доставка' ,
guarantee : 'Гарантия' ,
legal : 'Правовая информация' ,
offer : 'Оферта' ,
privacy : 'Конфиденциальность' ,
returns : 'Возврат' ,
info : 'Информация' ,
aboutCompany : 'О компании' ,
documents : 'Документы' ,
paymentRules : 'Правила оплаты' ,
returnPolicy : 'Политика возврата' ,
publicOffer : 'Публичная оферта' ,
help : 'Помощь' ,
payment : 'Оплата' ,
allRightsReserved : 'В с е права защищены.' ,
} ,
home : {
welcomeTo : 'Добро пожаловать в {{brand}}' ,
subtitle : 'Найдите всё, что нужно, в одном месте' ,
startSearch : 'Начать поиск' ,
loading : 'Загружаем категории...' ,
errorTitle : 'Что-то пошло не так' ,
retry : 'Попробовать снова' ,
categoriesTitle : 'Категории товаров' ,
categoriesSubtitle : 'Выберите интересующую категорию' ,
categoriesEmpty : 'Категории скоро появятся' ,
categoriesEmptyDesc : 'Мы работаем над наполнением каталога' ,
dexarHeroTitle : 'Здесь ты найдёшь всё' ,
dexarHeroSubtitle : 'Тысячи товаров в одном месте' ,
dexarHeroTagline : 'просто и удобно' ,
goToCatalog : 'Перейти в каталог' ,
findProduct : 'Найти товар' ,
loadingDexar : 'Загрузка категорий...' ,
catalogTitle : 'Каталог товаров' ,
emptyCategoriesDexar : 'Категории пока отсутствуют' ,
categoriesSoonDexar : 'Скоро здесь появятся категории товаров' ,
itemsCount : '{{count}} товаров' ,
} ,
cart : {
title : 'Корзина' ,
clear : 'Очистить' ,
empty : 'Корзина пуста' ,
emptyDesc : 'Добавьте товары, чтобы начать покупки' ,
goShopping : 'Перейти к покупкам' ,
total : 'Итого' ,
items : 'Товары' ,
deliveryLabel : 'Доставка' ,
2026-06-21 23:13:01 +04:00
deliveryMethod : 'Способ доставки' ,
selectDelivery : 'Выберите способ доставки' ,
deliveryPlace : 'Место' ,
deliveryTime : 'Срок доставки' ,
digitalDelivery : 'Цифровая доставка' ,
deliveryRequired : 'Выберите доставку для всех товаров с доставкой перед оформлением заказа.' ,
2026-02-26 23:09:20 +04:00
toPay : 'К оплате' ,
agreeWith : 'Я согласен с ' ,
publicOffer : 'публичной офертой' ,
returnPolicy : 'политикой возврата' ,
guaranteeTerms : 'условиями гарантии' ,
privacyPolicy : 'политикой конфиденциальности' ,
and : 'и' ,
checkout : 'Оформить заказ' ,
2026-06-29 00:06:18 +04:00
payViaQr : 'Оплатить через QR' ,
payViaCard : 'Оплатить картой' ,
2026-02-26 23:09:20 +04:00
close : 'Закрыть' ,
creatingPayment : 'Создание платежа...' ,
waitFewSeconds : 'Подождите несколько секунд' ,
scanQr : 'Сканируйте QR-код для оплаты' ,
amountToPay : 'Сумма к оплате:' ,
waitingPayment : 'Ожидание оплаты...' ,
copied : '✓ Скопировано' ,
copyLink : 'Скопировать ссылку' ,
openNewTab : 'Открыть в новой вкладке' ,
paymentSuccess : 'Поздравляем! Оплата прошла успешно!' ,
paymentSuccessDesc : 'Введите ваши контактные данные, и мы отправим вам покупку в течение нескольких минут' ,
sending : 'Отправка...' ,
send : 'Отправить' ,
2026-06-02 00:57:36 +04:00
paymentError : 'Н е удалось создать платеж' ,
paymentErrorDesc : 'Сейчас не получилось подготовить QR-код для оплаты. Попробуйте еще раз через минуту.' ,
retryPayment : 'Попробовать снова' ,
2026-02-26 23:09:20 +04:00
paymentTimeout : 'Время ожидания истекло' ,
paymentTimeoutDesc : 'Мы не получили подтверждение оплаты в течение 3 минут.' ,
autoClose : 'Окно закроется автоматически...' ,
confirmClear : 'Вы уверены, что хотите очистить корзину?' ,
2026-07-09 02:29:12 +04:00
removeItem : 'Удалить товар' ,
paymentQrAlt : 'QR-код для оплаты' ,
2026-02-26 23:09:20 +04:00
acceptTerms : 'Пожалуйста, примите условия оферты, политику возврата и возврата для подтверждения оформления заказа.' ,
copyError : 'Ошибка копирования:' ,
emailSuccess : 'Email успешно отправлен! Проверьте свою почту.' ,
emailError : 'Произошла ошибка при отправке email. Пожалуйста, попробуйте снова.' ,
phoneRequired : 'Номер телефона обязателен' ,
phoneMoreDigits : 'Введите ещё {{count}} цифр' ,
phoneTooMany : 'Слишком много цифр' ,
emailRequired : 'Email обязателен' ,
emailTooShort : 'Email слишком короткий (минимум 5 символов)' ,
emailTooLong : 'Email слишком длинный (максимум 100 символов)' ,
emailNeedsAt : 'Email должен содержать @' ,
emailNeedsDomain : 'Email должен содержать домен (.com, .ru и т.д.)' ,
emailInvalid : 'Некорректный формат email' ,
2026-03-24 00:09:11 +04:00
loginRequired : 'Войдите для оформления' ,
loginRequiredDesc : 'Для оформления заказа войдите через Telegram' ,
loginWithTelegram : 'Войти через Telegram' ,
orScanQr : 'Или отсканируйте QR-код' ,
2026-02-26 23:09:20 +04:00
} ,
search : {
title : 'Поиск товаров' ,
placeholder : 'Введите название товара...' ,
2026-07-10 13:25:31 +04:00
searchBarAria : 'Поисковая строка' ,
2026-02-26 23:09:20 +04:00
resultsCount : 'Найдено товаров:' ,
searching : 'Поиск...' ,
retry : 'Попробовать снова' ,
noResults : 'Ничего не найдено' ,
noResultsFor : 'По запросу "{{query}}" товары не найдены' ,
noResultsHint : 'Попробуйте изменить запрос или используйте другие ключевые слова' ,
2026-07-10 13:25:31 +04:00
emptyResultsAria : 'Пустые результаты поиска' ,
popularCategories : 'Популярные категории' ,
recommendedProducts : 'Рекомендуемые товары' ,
aiSuggestionHint : 'AI-подсказка (в будущем)' ,
suggestionType : {
product : 'Товар' ,
category : 'Категория' ,
brand : 'Бренд' ,
collection : 'Подборка' ,
seller : 'Продавец' ,
'static-page' : 'Страница' ,
ai : 'AI' ,
} ,
2026-02-26 23:09:20 +04:00
addToCart : 'В корзину' ,
loadingMore : 'Загрузка...' ,
allLoaded : 'В с е результаты загружены' ,
emptyState : 'Введите запрос для поиска товаров' ,
2026-07-05 01:10:56 +04:00
minLength : 'Введите минимум {{count}} символа для поиска' ,
2026-02-26 23:09:20 +04:00
of : 'из' ,
} ,
category : {
retry : 'Попробовать снова' ,
addToCart : 'В корзину' ,
loadingMore : 'Загрузка...' ,
allLoaded : 'В с е товары загружены' ,
emptyTitle : 'Упс! Здесь пока пусто' ,
emptyDesc : 'В этой категории ещё нет товаров, но скоро они появятся' ,
goHome : 'Н а главную' ,
loading : 'Загрузка товаров...' ,
} ,
2026-07-05 01:36:21 +04:00
catalog : {
title : 'Каталог' ,
breadcrumb : 'Навигация по каталогу' ,
allCategories : 'В с е категории' ,
products : 'Товары' ,
loading : 'Загрузка каталога...' ,
loadingProducts : 'Загрузка товаров...' ,
errorTitle : 'Каталог недоступен' ,
error : 'Н е удалось загрузить каталог. Попробуйте позже.' ,
retry : 'Попробовать снова' ,
categoryHint : 'Выберите категорию, чтобы продолжить' ,
productHint : 'Товары в выбранной категории' ,
emptyTitle : 'Здесь пока пусто' ,
emptyCategories : 'В этом разделе пока нет дочерних категорий.' ,
emptyProducts : 'В этой категории пока нет товаров.' ,
addToCart : 'В корзину' ,
categoriesCount : '{{count}} категорий' ,
productsCount : '{{count}} товаров' ,
2026-07-09 01:40:22 +04:00
entriesCount : '{{count}} позиций' ,
categoryBannerPlaceholder : 'Баннер категории подготовлен для медиа и описания из backend.' ,
navigationPlaceholder : 'Макет навигации подготовлен для конфигурации из backend/bootstrap.' ,
removeSavedSearch : 'Удалить сохраненный поиск' ,
resetFilters : 'Сбросить' ,
filtersTitle : 'Фильтры' ,
2026-07-09 02:57:48 +04:00
from : 'От' ,
to : 'До' ,
2026-07-09 01:40:22 +04:00
minValue : 'От {{value}}' ,
maxValue : 'До {{value}}' ,
enabled : 'Включено' ,
searchPlaceholder : 'Поиск товаров, брендов и категорий' ,
searchSubmit : 'Найти' ,
2026-07-09 02:29:12 +04:00
clearSearch : 'Очистить' ,
2026-07-09 01:40:22 +04:00
suggestionsTitle : 'Подсказки' ,
2026-07-09 02:29:12 +04:00
popularSearchesTitle : 'Популярные запросы' ,
2026-07-09 01:40:22 +04:00
recentSearchesTitle : 'Недавние запросы' ,
searchHistoryTitle : 'История поиска' ,
clearHistory : 'Очистить' ,
searchNoResultsHint : 'Ничего не найдено. Попробуйте более общий запрос.' ,
2026-07-09 02:29:12 +04:00
searchProductsFound : 'Найдено товаров: {{total}}' ,
searchResultsSummary : '{{total}} результатов по запросу "{{query}}"' ,
2026-07-10 15:55:38 +04:00
loadMore : 'Показать еще' ,
2026-07-09 01:40:22 +04:00
sortBy : 'Сортировать по' ,
2026-07-09 01:46:32 +04:00
sortRelevance : 'Рекомендуемые' ,
2026-07-09 01:40:22 +04:00
sortLatest : 'Новизне' ,
sortPriceAsc : 'Цене: по возрастанию' ,
sortPriceDesc : 'Цене: по убыванию' ,
sortRating : 'Рейтингу' ,
sortPopular : 'Популярности' ,
sortDiscount : 'Скидке' ,
layoutGrid : 'Сетка' ,
layoutLargeGrid : 'Крупная сетка' ,
layoutCompactGrid : 'Компактная сетка' ,
2026-07-10 15:55:38 +04:00
layoutGrid2 : '2 колонки' ,
layoutGrid3 : '3 колонки' ,
layoutGrid4 : '4 колонки' ,
layoutCompact : 'Компактно' ,
2026-07-09 01:40:22 +04:00
layoutList : 'Список' ,
noResults : 'Нет результатов' ,
itemsCount : '{{count}} товаров' ,
emptyResultsTitle : 'Результаты не найдены' ,
emptyResultsDescription : 'Попробуйте изменить фильтры, сортировку или поисковый запрос.' ,
previousPage : 'Назад' ,
nextPage : 'Вперед' ,
pageOf : 'Страница {{page}} / {{total}}' ,
2026-07-09 01:46:32 +04:00
emptyCategoryTitle : 'В этой категории пока нет товаров' ,
emptyCategoryMessage : 'Попробуйте перейти в родительские категории или вернуться в общий каталог.' ,
2026-07-10 15:55:38 +04:00
goToParentCategory : 'Перейти в родительскую категорию' ,
2026-07-09 01:46:32 +04:00
browseCategories : 'Смотреть категории' ,
2026-07-10 15:55:38 +04:00
offlineTitle : 'Нет подключения' ,
offlineMessage : 'Подключитесь к сети, чтобы продолжить просмотр каталога.' ,
2026-07-09 01:46:32 +04:00
noFilterMatchTitle : 'Нет товаров, соответствующих выбранным фильтрам.' ,
noFilterMatchMessage : 'Попробуйте расширить диапазон цены, атрибуты или бренды.' ,
clearFilters : 'Очистить фильтры' ,
openFilters : 'Открыть фильтры' ,
applyFilters : 'Применить' ,
close : 'Закрыть' ,
filtersDrawerAria : 'Панель фильтров' ,
sortSheetAria : 'Параметры сортировки' ,
mobileToolbarAria : 'Мобильная панель каталога' ,
gridCycle : 'Сетка' ,
filtersPanelAria : 'Фильтры каталога' ,
2026-07-09 01:40:22 +04:00
filterPrice : 'Цена' ,
filterAvailability : 'Наличие' ,
filterInStock : 'В наличии' ,
filterLowStock : 'Мало в наличии' ,
filterOutOfStock : 'Нет в наличии' ,
filterRating : 'Рейтинг' ,
filterStars : '{{count}} звезд' ,
filterBrand : 'Бренд' ,
filterCategory : 'Категория' ,
filterCategoryValue : 'Категория {{value}}' ,
filterSubcategory : 'Подкатегория' ,
filterDiscount : 'Скидка' ,
filterNew : 'Новинки' ,
filterColor : 'Цвет' ,
filterSize : 'Размер' ,
filterAttributes : 'Атрибуты' ,
} ,
productDetails : {
loading : 'Загрузка товара...' ,
errorTitle : 'Товар недоступен' ,
retry : 'Попробовать снова' ,
missingTitle : 'Товар не найден' ,
missingDescription : 'Этот товар не существует или больше недоступен.' ,
backToCatalog : 'Вернуться в каталог' ,
tabsAria : 'Вкладки товара' ,
mediaAria : 'Медиа товара' ,
ratingStarsAria : 'Рейтинг в звездах' ,
selectRatingAria : 'Выберите оценку' ,
reviewsEmpty : 'Пока нет отзывов.' ,
questionsEmpty : 'Пока нет вопросов.' ,
askQuestion : 'Задать вопрос' ,
hideQuestionForm : 'Скрыть форму вопроса' ,
questionFormTitle : 'Задать вопрос' ,
questionFormPlaceholder : 'Спросите о размере, доставке, совместимости или использовании' ,
questionFormAnonymous : 'Задать анонимно' ,
submitQuestion : 'Отправить вопрос' ,
reviewFormTitle : 'Оставить отзыв' ,
reviewRatingLabel : 'Оценка' ,
reviewTitleLabel : 'Заголовок' ,
reviewTitlePlaceholder : 'Короткий заголовок' ,
reviewTextLabel : 'Отзыв' ,
reviewTextPlaceholder : 'Опишите ваш опыт использования' ,
reviewAnonymous : 'Отправить анонимно' ,
reviewUploadPlaceholder : 'Загрузка фото запланирована в следующем спринте.' ,
2026-07-10 13:10:35 +04:00
reviewRatingRequired : 'Выберите оценку.' ,
reviewTextRequired : 'Добавьте текст отзыва.' ,
reviewSuccess : 'Отзыв успешно отправлен.' ,
2026-07-09 01:40:22 +04:00
submitReview : 'Отправить отзыв' ,
submitting : 'Отправка...' ,
2026-07-10 13:10:35 +04:00
loadMore : 'Показать еще' ,
showingOf : 'Показано {{shown}} из {{total}}' ,
questionsSubmissionFuture : 'Отправку вопросов можно включить позже без изменения компонента.' ,
specificationsGeneral : 'Общие' ,
actionsAria : 'Действия с товаром' ,
buyNow : 'Купить сейчас' ,
wishlist : 'В избранное' ,
compare : 'Сравнить' ,
share : 'Поделиться' ,
notifyMe : 'Сообщить о наличии' ,
zoom : 'Увеличить' ,
fullscreen : 'Полный экран' ,
pdfDocument : 'PDF документ товара' ,
manualDocument : 'Инструкция товара' ,
warrantyDocument : 'Гарантийный документ' ,
openDocument : 'Открыть документ' ,
2026-07-09 01:40:22 +04:00
specificationsEmpty : 'Характеристики пока не указаны.' ,
warrantyTitle : 'Гарантия и возврат' ,
warrantyItem1 : 'Условия гарантии определяются продавцом и местным законодательством.' ,
warrantyItem2 : 'Возможность возврата зависит от состояния и категории товара.' ,
warrantyItem3 : 'Подробная инструкция по возврату доступна после покупки.' ,
verifiedPurchase : 'Подтвержденная покупка' ,
officialSeller : 'Официальный продавец' ,
acceptedAnswer : 'Принятый ответ' ,
like : 'Нравится' ,
dislike : 'Н е нравится' ,
reviewsCountLabel : '{{count}} отзывов' ,
previous : 'Назад' ,
next : 'Вперед' ,
pageOf : 'Страница {{page}} / {{total}}' ,
2026-07-05 01:36:21 +04:00
} ,
2026-02-26 23:09:20 +04:00
subcategories : {
loading : 'Загрузка подкатегорий...' ,
retry : 'Попробовать снова' ,
emptyTitle : 'Упс! Подкатегорий пока нет' ,
emptyDesc : 'В этом разделе ещё нет подкатегорий, но скоро они появятся' ,
goHome : 'Н а главную' ,
2026-03-24 00:09:11 +04:00
itemsInCategory : 'Товары в этой категории' ,
2026-07-05 01:09:55 +04:00
childrenCount : '{{count}} категорий' ,
productsCount : '{{count}} товаров' ,
includesProducts : 'Есть товары' ,
2026-02-26 23:09:20 +04:00
} ,
itemDetail : {
loading : 'Загрузка...' ,
loadingDexar : 'Загрузка товара...' ,
back : 'Вернуться' ,
backHome : 'Вернуться на главную' ,
noImage : 'Нет изображения' ,
stock : 'Наличие:' ,
inStock : 'В наличии' ,
lowStock : 'Осталось немного' ,
lastItems : 'Последние штуки' ,
mediumStock : 'Заканчивается' ,
addToCart : 'Добавить в корзину' ,
description : 'Описание' ,
2026-02-28 16:13:14 +04:00
specifications : 'Характеристики' ,
2026-02-26 23:09:20 +04:00
reviews : 'Отзывы' ,
yourReview : 'Ваш отзыв' ,
leaveReview : 'Оставить отзыв' ,
rating : 'Оценка:' ,
reviewPlaceholder : 'Поделитесь своими впечатлениями о товаре...' ,
reviewPlaceholderDexar : 'Поделитесь впечатлениями о товаре...' ,
anonymous : 'Анонимно' ,
submitting : 'Отправка...' ,
submit : 'Отправить' ,
reviewSuccess : 'Спасибо за ваш отзыв!' ,
reviewError : 'Ошибка отправки. Попробуйте позже.' ,
defaultUser : 'Пользователь' ,
defaultUserDexar : 'Аноним' ,
noReviews : 'Пока нет отзывов. Станьте первым!' ,
qna : 'Вопросы и ответы' ,
photo : 'Фото' ,
reviewsCount : 'отзывов' ,
today : 'Сегодня' ,
yesterday : 'Вчера' ,
daysAgo : 'дн. назад' ,
weeksAgo : 'нед. назад' ,
2026-03-24 00:09:11 +04:00
colour : 'Цвет' ,
size : 'Размер' ,
2026-07-05 01:07:53 +04:00
relatedProducts : 'Похожие товары' ,
2026-02-26 23:09:20 +04:00
} ,
app : {
connecting : 'Подключение к серверу...' ,
serverUnavailable : 'Сервер недоступен' ,
serverError : 'Н е удалось подключиться к серверу. Проверьте подключение к интернету.' ,
retryConnection : 'Повторить попытку' ,
pageTitle : 'Маркетплейс товаров и услуг' ,
} ,
2026-07-09 02:29:12 +04:00
platform : {
loadingPage : 'Загрузка страницы платформы...' ,
emptyConfig : 'Конфигурация страницы не найдена.' ,
} ,
backoffice : {
title : 'Песочница Backoffice' ,
subtitle : 'Домен управления бизнес-данными (mock для платформенного фундамента).' ,
loading : 'Загрузка данных backoffice...' ,
products : 'Товары' ,
categories : 'Категории' ,
otherDomains : 'Другие домены' ,
sku : 'SKU' ,
titleColumn : 'Название' ,
price : 'Цена' ,
status : 'Статус' ,
itemsCount : 'шт.' ,
orders : 'Заказы' ,
customers : 'Клиенты' ,
inventory : 'Склад' ,
media : 'Медиа' ,
settings : 'Настройки' ,
notAvailable : 'н/д' ,
} ,
builder : {
feat(builder): redesign marketplace builder experience and navigation
Renamed the experience consistently to Marketplace Builder everywhere
visible (page title/subtitle, breadcrumbs, sidebar, dashboard quick
action/shortcut copy) - internal ProjectEditor class/selector names
kept as-is to avoid regressions. builder.title/subtitle no longer say
'bootstrap-config editing surface' to end users.
New business-oriented IA (builder-groups.model.ts): 12 existing
ProjectEditorSectionIds regrouped into 8 groups (Marketplace, Branding
and Design, Homepage, Content, Languages, Marketplace Features,
Navigation and Search, Preview) - every existing section mapped to
exactly one group, none dropped, no group points at a page that
doesn't exist.
New Builder landing page at /edit (was a redirect straight into the
General form): readiness percent, recommended next step, one overview
card per group (purpose + real complete/in-progress/not-started/unknown
status, icon+text never color-alone), a Marketplace Readiness
checklist, quick links. All derived from real facade/schema signals
(required-field fill state, modifiedSections, staticPages, catalog
counts via BackofficeDataService) or explicitly marked unknown
(the "preview reviewed" check has no tracking - shown as unknown,
never guessed).
Section pages (/edit/:section) now share one consistent header:
breadcrumb (Builder > Group > Section), draft/published + modified
badges, and a contextual help panel (what is this / where visible /
what happens if you skip it) sourced per group. Sidebar nav rewritten
as grouped, icon-led sections with per-section and per-group status
indicators; layout converted from a top pill-tab bar to a responsive
sidebar (desktop 280px, tablet 72px icon rail, mobile drawer with
Escape-to-close), matching the Sprint 1 admin shell pattern. Section
form components themselves untouched.
Routes: 'edit' is now its own landing route instead of redirecting to
'edit/general'; /builder and /project-editor redirect to 'edit'.
Sprint 1/2 destinations that pointed at edit/general now point at the
new edit landing page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 09:43:03 +04:00
title : 'Конструктор маркетплейса' ,
subtitle : 'Соберите свой маркетплейс шаг за шагом.' ,
2026-07-10 13:43:53 +04:00
general : 'Общие' ,
2026-07-09 02:29:12 +04:00
branding : 'Брендинг' ,
2026-07-10 13:43:53 +04:00
theme : 'Тема' ,
header : 'Хедер' ,
footer : 'Футер' ,
homepage : 'Главная страница' ,
widgets : 'Виджеты' ,
2026-07-10 13:52:01 +04:00
staticPages : 'Статические страницы' ,
2026-07-10 13:43:53 +04:00
marketplaceFeatures : 'Функции маркетплейса' ,
preview : 'Превью' ,
2026-07-09 02:29:12 +04:00
brandName : 'Название бренда' ,
2026-07-10 13:43:53 +04:00
marketplaceName : 'Название маркетплейса' ,
domain : 'Домен' ,
descriptionLabel : 'Описание' ,
defaultLanguage : 'Язык по умолчанию' ,
supportedLanguages : 'Поддерживаемые языки' ,
logo : 'Логотип' ,
smallLogo : 'Малый логотип' ,
favicon : 'Favicon' ,
2026-07-17 15:22:45 +04:00
socialImage : 'Изображение для соцсетей' ,
gallery : 'Галерея' ,
addGalleryImage : 'Добавить изображение' ,
2026-07-17 15:29:55 +04:00
headerLayout : 'Расположение шапки' ,
headerLayoutDefault : 'По умолчанию' ,
headerLayoutCentered : 'По центру' ,
headerSticky : 'Липкая шапка' ,
2026-07-10 13:43:53 +04:00
marketplaceTitle : 'Заголовок маркетплейса' ,
primaryColor : 'Основной цвет' ,
secondaryColor : 'Вторичный цвет' ,
backgroundColor : 'Фон' ,
surfaceColor : 'Поверхность' ,
textColor : 'Текст' ,
successColor : 'Success' ,
warningColor : 'Warning' ,
dangerColor : 'Danger' ,
showLogo : 'Логотип' ,
showSearch : 'Поиск' ,
showCategories : 'Категории' ,
showLanguages : 'Языки' ,
showCart : 'Корзина' ,
showProfile : 'Профиль' ,
showWishlist : 'Избранное' ,
showCompare : 'Сравнение' ,
showRegion : 'Регион' ,
companyName : 'Информация о компании' ,
address : 'Адрес' ,
phone : 'Телефон' ,
email : 'Email' ,
copyright : 'Копирайт' ,
paymentIcons : 'Иконки оплаты' ,
socialLinks : 'Социальные ссылки' ,
2026-07-16 02:06:26 +04:00
footerLogo : 'Логотип в футере' ,
addPaymentIcon : 'Добавить иконку оплаты' ,
removePaymentIcon : 'Удалить' ,
iconAltLabel : 'Подпись иконки' ,
addSocialLink : 'Добавить соцсеть' ,
removeSocialLink : 'Удалить' ,
socialLinkLabel : 'Платформа' ,
socialLinkUrl : 'URL' ,
invalidUrl : 'Введите корректный URL, начинающийся с http:// или https://.' ,
2026-07-10 13:52:01 +04:00
createPage : 'Создать страницу' ,
deletePage : 'Удалить страницу' ,
pageId : 'ID страницы' ,
slug : 'Slug' ,
iconLabel : 'Иконка' ,
showInFooter : 'Показывать в футере' ,
showInHeader : 'Показывать в хедере' ,
showInSitemap : 'Показывать в sitemap' ,
requiresAuthentication : 'Требует авторизацию' ,
footerGroup : 'Группа футера' ,
orderLabel : 'Порядок' ,
translationTitle : 'Заголовок перевода' ,
htmlPreview : 'HTML' ,
2026-07-15 04:11:18 +04:00
seoSection : 'SEO' ,
seoTitle : 'SEO заголовок' ,
seoDescription : 'SEO описание' ,
seoKeywords : 'Ключевые слова' ,
seoCanonical : 'Canonical URL' ,
seoOgTitle : 'OG заголовок' ,
seoOgDescription : 'OG описание' ,
seoOgImage : 'OG изображение' ,
2026-07-10 13:43:53 +04:00
visible : 'Видимость' ,
layoutLabel : 'Layout' ,
columns : 'Колонки' ,
height : 'Высота' ,
overlay : 'Overlay' ,
autoplay : 'Autoplay' ,
cardsPerRow : 'Карточек в ряд' ,
filtersLabel : 'Фильтры' ,
showBadges : 'Показывать badges' ,
showRating : 'Показывать рейтинг' ,
showPrice : 'Показывать цену' ,
widgetJson : 'JSON виджета' ,
reviews : 'Отзывы' ,
questions : 'Вопросы' ,
comments : 'Комментарии' ,
recommendations : 'Рекомендации' ,
recentlyViewed : 'Недавно просмотренные' ,
searchSuggestions : 'Поисковые подсказки' ,
searchHistory : 'История поиска' ,
livePreview : 'Живое превью' ,
2026-07-17 09:00:47 +04:00
previewChangesTitle : 'Изменения с последней публикации' ,
previewNoIssues : 'Нет проблем валидации.' ,
previewNoChanges : 'Нет изменений с последней публикации.' ,
previewChangeField : 'Поле' ,
previewChangeBefore : 'До' ,
previewChangeAfter : 'После' ,
2026-07-13 08:10:00 +04:00
languagesTab : 'Языки' ,
addLanguage : 'Добавить язык' ,
removeLanguage : 'Удалить' ,
setDefaultLanguage : 'Сделать языком по умолчанию' ,
defaultLanguageLabel : 'По умолчанию' ,
2026-07-13 08:57:42 +04:00
navigationTab : 'Навигация' ,
navigationHeader : 'Навигация в шапке' ,
navigationFooter : 'Навигация в подвале' ,
navigationFooterGrouped : 'Навигация подвала сгруппирована по колонкам и пока недоступна для редактирования здесь — используйте вкладку "Подвал".' ,
addLink : 'Добавить ссылку' ,
2026-07-17 10:18:08 +04:00
insertPageLink : 'Вставить ссылку на страницу' ,
linkedToPage : 'Связано с о страницей' ,
2026-07-13 08:57:42 +04:00
removeLink : 'Удалить' ,
linkLabel : 'Название' ,
linkUrl : 'URL' ,
2026-07-10 13:43:53 +04:00
exportBootstrap : 'Экспорт bootstrap' ,
importBootstrap : 'Импорт bootstrap' ,
exportedBootstrap : 'Экспортированный bootstrap' ,
importSource : 'Источник импорта' ,
importError : 'Импорт не удался. Некорректный JSON bootstrap.' ,
2026-07-09 02:29:12 +04:00
featureFlags : 'Фичи-флаги' ,
2026-07-13 10:51:05 +04:00
validationMissingLogo : 'В брендинге отсутствует логотип.' ,
validationNoLanguages : 'Н е настроены языки.' ,
2026-07-17 19:00:17 +04:00
validationDefaultLocaleNotSupported : 'Язык по умолчанию отсутствует в списке поддерживаемых языков.' ,
2026-07-13 10:51:05 +04:00
validationInvalidUrl : 'Некорректный URL маркетплейса.' ,
validationDuplicateSlugs : 'Две или более статические страницы имеют одинаковый slug.' ,
validationEmptyHomepage : 'Н а главной странице нет секций.' ,
validationMissingWidget : 'В секции главной страницы есть виджет без типа.' ,
validationDuplicateNavLinks : 'Две или более ссылки в навигации шапки дублируются.' ,
validationInvalidColors : 'Один или несколько цветов темы указаны некорректно.' ,
2026-07-14 12:21:33 +04:00
validationMissingTranslations : 'Часть контента не переведена на один из поддерживаемых языков.' ,
validationInvalidLayouts : 'Один или несколько макетов ссылаются на неизвестный тип раскладки.' ,
feat(project-editor): centralize schema-driven validation
Milestone 2 of the Configuration Engine sprint.
- Add schema/validators/primitives: pure isValidHexColor/HttpUrl/Email,
validateJson, validateCss, extractStyleBlocks, normalizeRoute. One function
per concern, no duplicated validator logic.
- Refactor ProjectValidator to compose the primitives and tag every issue with
section + fieldKey + severity ('error' blocks publish, 'warning' advisory).
Preserves all existing codes/messages; adds duplicate-routes, invalid-css,
invalid-widget-config checks.
- Facade: issuesByField, issuesBySection, blockingIssues, hasBlockingIssues;
publish() now gates on severity==='error' instead of any issue.
- i18n: add validationInvalidJson/Css/DuplicateRoutes/InvalidWidgetConfig to
the Translations interface + en/ru/hy.
- Specs: primitives + ProjectValidator (25 passing total).
Gate: tsc --noEmit, npm test (25/25), arch:check, build all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 01:58:36 +04:00
validationInvalidJson : 'Конфигурация не является допустимым JSON.' ,
validationInvalidCss : 'Статическая страница содержит недопустимый CSS.' ,
validationDuplicateRoutes : 'Две или более страницы используют один и тот же маршрут.' ,
validationInvalidWidgetConfig : 'У виджета отсутствует обязательное поле (id, type, version или props).' ,
2026-07-17 16:57:43 +04:00
validationInvalidContactEmail : 'Контактный email компании указан некорректно.' ,
validationInvalidSocialLinkUrl : 'У одной или нескольких социальных ссылок в футере некорректный URL.' ,
validationIncompletePaymentIcon : 'У иконки оплаты в футере отсутствует изображение или альтернативный текст.' ,
2026-07-17 02:13:34 +04:00
undo : 'Отменить' ,
redo : 'Повторить' ,
2026-07-13 15:00:03 +04:00
statusDraft : 'Черновик' ,
statusPublished : 'Опубликовано' ,
unsavedChanges : 'Есть несохранённые изменения' ,
save : 'Сохранить' ,
publish : 'Опубликовать' ,
2026-07-13 15:57:54 +04:00
confirmLeaveUnsaved : 'Есть несохранённые изменения. Всё равно уйти?' ,
promptLinkUrl : 'URL' ,
promptImageUrl : 'URL изображения' ,
2026-07-17 10:00:33 +04:00
promptEmbedUrl : 'URL для встраивания' ,
htmlEditorInvalidHtml : 'В этом HTML есть незакрытый или несовпадающий тег. Исправьте перед возвратом к визуальному редактору.' ,
2026-07-13 15:57:54 +04:00
htmlEditorCode : 'Код' ,
htmlEditorPreview : 'Предпросмотр' ,
2026-07-14 09:50:03 +04:00
lastSaved : 'Последнее сохранение' ,
draftRestored : 'Локальный черновик восстановлен из предыдущей сессии.' ,
dismiss : 'Скрыть' ,
resetDraft : 'Сбросить черновик' ,
resetSection : 'Сбросить секцию' ,
confirmResetDraft : 'Это отменит все неопубликованные изменения и восстановит последнюю опубликованную конфигурацию. Продолжить?' ,
confirmResetSection : 'Это отменит неопубликованные изменения только в этой секции. Продолжить?' ,
2026-07-14 16:05:09 +04:00
marketplaceNameDesc : 'Название, которое видят покупатели на витрине и во вкладке браузера.' ,
domainDesc : 'Домен, по которому покупатели заходят на маркетплейс. Изменение поля не переносит DNS.' ,
descriptionFieldDesc : 'Краткое описание для поисковых систем и превью в соцсетях.' ,
defaultLanguageDesc : 'Язык, который показывается, если у покупателя нет сохранённого предпочтения.' ,
supportedLanguagesDesc : 'Коды языков через запятую, между которыми может переключаться покупатель (например, en, ru, hy).' ,
logoDesc : 'URL полного логотипа, отображается в шапке на десктопе.' ,
smallLogoDesc : 'URL компактного логотипа для ограниченного пространства (например, мобильная шапка).' ,
faviconDesc : 'URL иконки вкладки браузера. Должен быть небольшим квадратным изображением.' ,
2026-07-17 15:22:45 +04:00
socialImageDesc : 'Изображение по умолчанию при публикации маркетплейса в соцсетях (Open Graph).' ,
galleryDesc : 'Дополнительные брендовые изображения для будущего использования в витрине.' ,
2026-07-17 15:29:55 +04:00
headerLayoutDesc : 'Как расположен контент шапки: по умолчанию (логотип слева, навигация разнесена) или по центру.' ,
headerStickyDesc : 'Закреплять шапку вверху экрана при прокрутке.' ,
2026-07-14 16:05:09 +04:00
marketplaceTitleDesc : 'Заголовок страницы для поисковых систем и вкладок браузера.' ,
primaryColorDesc : 'Основной цвет бренда для главных кнопок и акцентов. Должен быть корректным hex-цветом.' ,
secondaryColorDesc : 'Дополнительный цвет бренда для второстепенных элементов. Должен быть корректным hex-цветом.' ,
backgroundColorDesc : 'Цвет фона страницы по умолчанию. Должен быть корректным hex-цветом.' ,
surfaceColorDesc : 'Цвет фона карточек и приподнятых поверхностей. Должен быть корректным hex-цветом.' ,
textColorDesc : 'Цвет основного текста. Должен быть корректным hex-цветом.' ,
successColorDesc : 'Цвет для сообщений о б успехе и положительных состояний. Должен быть корректным hex-цветом.' ,
warningColorDesc : 'Цвет для предупреждающих сообщений. Должен быть корректным hex-цветом.' ,
dangerColorDesc : 'Цвет для ошибок и разрушительных действий. Должен быть корректным hex-цветом.' ,
themeModeLabel : 'Цветовой режим' ,
themeModeDesc : 'Определяет, отображается ли витрина в светлой, тёмной теме или по системным настройкам покупателя.' ,
themeModeLight : 'Светлый' ,
themeModeLightDesc : 'Всегда использовать светлую тему.' ,
themeModeDark : 'Тёмный' ,
themeModeDarkDesc : 'Всегда использовать тёмную тему.' ,
themeModeSystem : 'Системный' ,
themeModeSystemDesc : 'Использовать системные/браузерные настройки цветовой темы устройства покупателя.' ,
siteLayoutLabel : 'Макет сайта' ,
siteLayoutDesc : 'Общий режим оформления страниц на витрине.' ,
siteLayoutDefault : 'По умолчанию' ,
siteLayoutDefaultDesc : 'Стандартный макет с верхней навигацией.' ,
siteLayoutSidebarLeft : 'Боковая панель (слева)' ,
siteLayoutSidebarLeftDesc : 'Добавляет левую боковую панель, обычно для навигации по категориям.' ,
siteLayoutCarouselHome : 'Карусель на главной' ,
siteLayoutCarouselHomeDesc : 'Главная страница начинается с полноширинной карусели/hero-блока.' ,
siteLayoutMinimal : 'Минимальный' ,
siteLayoutMinimalDesc : 'Упрощённое оформление с минимумом элементов навигации.' ,
showLogoDesc : 'Показывать логотип маркетплейса в шапке.' ,
showSearchDesc : 'Показывать строку поиска в шапке.' ,
showCategoriesDesc : 'Показывать вход в меню категорий в шапке.' ,
showLanguagesDesc : 'Показывать переключатель языка в шапке.' ,
showCartDesc : 'Показывать иконку/ссылку корзины в шапке.' ,
showProfileDesc : 'Показывать вход в профиль/аккаунт в шапке.' ,
showWishlistDesc : 'Показывать вход в избранное в шапке.' ,
showCompareDesc : 'Показывать вход в сравнение товаров в шапке.' ,
showRegionDesc : 'Показывать выбор региона/страны в шапке.' ,
companyNameDesc : 'Юридическое название компании, показывается в футере и на статических страницах.' ,
addressDesc : 'Юридический/фактический адрес компании, показывается в футере.' ,
phoneDesc : 'Контактный телефон, показывается в футере.' ,
emailDesc : 'Контактный email, показывается в футере.' ,
copyrightDesc : 'Строка копирайта внизу каждой страницы.' ,
paymentIconsDesc : 'По одной иконке оплаты на строку (URL изображения и подпись), показываются в футере.' ,
socialLinksDesc : 'По одной социальной ссылке на строку (платформа и URL), показываются в футере.' ,
2026-07-16 02:06:26 +04:00
footerLogoDesc : 'Логотип, отображаемый в футере, если отличается от логотипа в шапке.' ,
iconAltLabelDesc : 'Альтернативный текст для иконки оплаты (для доступности).' ,
socialLinkUrlDesc : 'Полный URL профиля в соцсети, должен начинаться с http:// или https://.' ,
2026-07-14 16:05:09 +04:00
staticPagesFieldDesc : 'Статические страницы (о компании, условия, политика и т.д.), на которые ссылается футер.' ,
sectionVisibleDesc : 'Показывать ли эту секцию главной страницы покупателям.' ,
layoutStrategyLabel : 'Стратегия раскладки' ,
layoutStrategyDesc : 'Как располагаются виджеты внутри этой секции.' ,
layoutStrategyStack : 'Стопка' ,
layoutStrategyStackDesc : 'Виджеты располагаются друг под другом вертикально.' ,
layoutStrategyGrid : 'Сетка' ,
layoutStrategyGridDesc : 'Виджеты располагаются в многоколоночной сетке.' ,
layoutStrategyHero : 'Hero' ,
layoutStrategyHeroDesc : 'Один крупный полноширинный промо-блок.' ,
layoutStrategyCarousel : 'Карусель' ,
layoutStrategyCarouselDesc : 'Виджеты прокручиваются горизонтально как карусель.' ,
layoutStrategySplit : 'Разделение' ,
layoutStrategySplitDesc : 'Контент делится на две колонки рядом друг с другом.' ,
sectionColumnsDesc : 'Количество колонок, если стратегия раскладки их поддерживает.' ,
widgetLayoutDesc : 'Название варианта раскладки в свободной форме, понятное этому виджету (например, "full-bleed", "boxed").' ,
widgetHeightDesc : 'Предпочтительная высота виджета (например, "480px" или "60vh").' ,
widgetOverlayDesc : 'Показывать тёмную подложку под текстом hero для читаемости.' ,
widgetAutoplayDesc : 'Автоматически прокручивать слайды hero без участия покупателя.' ,
widgetColumnsDesc : 'Количество плиток категорий в ряду.' ,
widgetCardsPerRowDesc : 'Количество карточек товаров в ряду.' ,
widgetFiltersDesc : 'Показывать элементы управления фильтрами рядом с подборкой товаров.' ,
widgetShowBadgesDesc : 'Показывать бейджи, например "Новинка" или "Скидка", на карточках товаров.' ,
widgetShowRatingDesc : 'Показывать рейтинг звёздами на карточках товаров.' ,
widgetShowPriceDesc : 'Показывать цену на карточках товаров.' ,
widgetJsonDesc : 'Сырые свойства виджета в формате JSON. Используется, если для этого типа виджета нет отдельного редактора.' ,
2026-07-17 18:14:58 +04:00
widgetJsonInvalid : 'Некорректный JSON — сохранена последняя корректная версия.' ,
2026-07-14 16:05:09 +04:00
wishlistFeatureDesc : 'Разрешить покупателям сохранять товары в избранное.' ,
compareFeatureDesc : 'Разрешить покупателям сравнивать несколько товаров одновременно.' ,
reviewsFeatureDesc : 'Разрешить покупателям оставлять и читать отзывы о товарах.' ,
questionsFeatureDesc : 'Разрешить покупателям задавать вопросы о товарах и читать ответы.' ,
commentsFeatureDesc : 'Включить общие комментарии к контенту маркетплейса.' ,
recommendationsFeatureDesc : 'Показывать блоки рекомендованных товаров на витрине.' ,
recentlyViewedFeatureDesc : 'Показывать покупателям список "недавно просмотренные".' ,
searchSuggestionsDesc : 'Показывать живые подсказки поиска по мере ввода запроса.' ,
searchHistoryDesc : 'Запоминать и показывать недавние поисковые запросы покупателя.' ,
catalogNavigationModeLabel : 'Режим навигации каталога' ,
catalogNavigationModeDesc : 'Как покупатели перемещаются по категориям в каталоге.' ,
catalogNavDefault : 'По умолчанию' ,
catalogNavDefaultDesc : 'Стандартная навигация по категориям через хлебные крошки.' ,
catalogNavLeftCategory : 'Левая навигация по категориям' ,
catalogNavLeftCategoryDesc : 'Постоянное дерево категорий в левой боковой панели.' ,
catalogNavMegaCategory : 'М е г а -меню категорий' ,
catalogNavMegaCategoryDesc : 'Развёрнутый выпадающий список с подкатегориями и избранными товарами.' ,
catalogNavTopCarousel : 'Карусель категорий сверху' ,
catalogNavTopCarouselDesc : 'Горизонтально прокручиваемые чипы категорий над сеткой каталога.' ,
newLanguageDesc : 'Код языка ISO для добавления в поддерживаемые языки витрины (например, de, fr).' ,
2026-07-17 18:31:01 +04:00
languageAlreadyAdded : 'Этот язык уже добавлен.' ,
2026-07-14 16:05:09 +04:00
languagesTabDesc : 'Языки, доступные покупателям. Язык по умолчанию используется как резервный везде.' ,
linkLabelDesc : 'Текст, отображаемый для этой ссылки навигации.' ,
linkUrlDesc : 'Путь или URL, на который ведёт эта ссылка навигации.' ,
linkVisibleDesc : 'Показывать ли эту ссылку навигации покупателям.' ,
feat(builder): redesign marketplace builder experience and navigation
Renamed the experience consistently to Marketplace Builder everywhere
visible (page title/subtitle, breadcrumbs, sidebar, dashboard quick
action/shortcut copy) - internal ProjectEditor class/selector names
kept as-is to avoid regressions. builder.title/subtitle no longer say
'bootstrap-config editing surface' to end users.
New business-oriented IA (builder-groups.model.ts): 12 existing
ProjectEditorSectionIds regrouped into 8 groups (Marketplace, Branding
and Design, Homepage, Content, Languages, Marketplace Features,
Navigation and Search, Preview) - every existing section mapped to
exactly one group, none dropped, no group points at a page that
doesn't exist.
New Builder landing page at /edit (was a redirect straight into the
General form): readiness percent, recommended next step, one overview
card per group (purpose + real complete/in-progress/not-started/unknown
status, icon+text never color-alone), a Marketplace Readiness
checklist, quick links. All derived from real facade/schema signals
(required-field fill state, modifiedSections, staticPages, catalog
counts via BackofficeDataService) or explicitly marked unknown
(the "preview reviewed" check has no tracking - shown as unknown,
never guessed).
Section pages (/edit/:section) now share one consistent header:
breadcrumb (Builder > Group > Section), draft/published + modified
badges, and a contextual help panel (what is this / where visible /
what happens if you skip it) sourced per group. Sidebar nav rewritten
as grouped, icon-led sections with per-section and per-group status
indicators; layout converted from a top pill-tab bar to a responsive
sidebar (desktop 280px, tablet 72px icon rail, mobile drawer with
Escape-to-close), matching the Sprint 1 admin shell pattern. Section
form components themselves untouched.
Routes: 'edit' is now its own landing route instead of redirecting to
'edit/general'; /builder and /project-editor redirect to 'edit'.
Sprint 1/2 destinations that pointed at edit/general now point at the
new edit landing page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 09:43:03 +04:00
appName : 'Конструктор маркетплейса' ,
breadcrumbRoot : 'Конструктор маркетплейса' ,
statusComplete : 'Готово' ,
statusInProgress : 'В процессе' ,
statusNotStarted : 'Н е начато' ,
statusUnknown : 'Пока не отслеживается' ,
draftBadge : 'Черновик' ,
publishedBadge : 'Опубликовано' ,
modifiedBadge : 'Есть несохранённые изменения' ,
helpToggleShow : 'Что это такое?' ,
helpToggleHide : 'Скрыть подсказку' ,
helpWhatIsThis : 'Что это' ,
helpWhySkip : 'Зачем это настраивать' ,
helpWhereVisible : 'Где это видят покупатели' ,
helpWhatIfSkip : 'Что будет, если пропустить' ,
helpWhenReturn : 'Когда возвращаться к этому разделу' ,
openSidebar : 'Открыть меню разделов' ,
closeSidebar : 'Закрыть меню разделов' ,
overviewTitle : 'Конструктор маркетплейса' ,
overviewSubtitle : 'Соберите свой маркетплейс шаг за шагом' ,
overviewReadinessLabel : 'Маркетплейс настроен на {{percent}}%' ,
overviewReadinessHint : 'Основано на обязательных полях, которые вы уже заполнили.' ,
overviewNextStepLabel : 'Рекомендуемый следующий шаг' ,
overviewNextStepFallback : 'В с е обязательные шаги выполнены — можно опубликовать маркетплейс.' ,
overviewQuickLinksTitle : 'Быстрые ссылки' ,
overviewSectionsTitle : 'Разделы конструктора' ,
overviewOpenSection : 'Открыть раздел' ,
overviewReadinessTitle : 'Готовность маркетплейса' ,
readinessLogoUploaded : 'Логотип загружен' ,
readinessHomepageConfigured : 'Главная страница настроена' ,
readinessThemeConfigured : 'Тема настроена' ,
readinessLanguagesConfigured : 'Языки настроены' ,
readinessContentPagesAdded : 'Добавлены информационные страницы' ,
readinessPreviewReviewed : 'Просмотр проверен' ,
readinessPublished : 'Маркетплейс опубликован' ,
readinessCategoriesExist : 'Есть категории' ,
readinessProductsExist : 'Есть товары' ,
groupMarketplaceLabel : 'Маркетплейс' ,
groupMarketplaceDescription : 'Название, адрес и основная информация о вашем маркетплейсе.' ,
groupMarketplacePurpose : 'Базовая информация, которая определяет ваш маркетплейс: название, домен и язык по умолчанию.' ,
groupMarketplaceWhere : 'Название и адрес видны во вкладке браузера, поисковой выдаче и на всех страницах магазина.' ,
groupMarketplaceSkip : 'Без названия и адреса маркетплейс не будет выглядеть завершённым для покупателей.' ,
groupBrandingLabel : 'Брендинг и оформление' ,
groupBrandingDescription : 'Логотип, цвета, шапка и подвал — визуальный стиль вашего магазина.' ,
groupBrandingPurpose : 'Настройте, как выглядит ваш маркетплейс: логотип, цветовую палитру и элементы шапки/подвала сайта.' ,
groupBrandingWhere : 'Изменения видны на каждой странице, которую видят покупатели.' ,
groupBrandingSkip : 'Маркетплейс будет использовать оформление по умолчанию, не отражающее ваш бренд.' ,
groupHomepageLabel : 'Главная страница' ,
groupHomepageDescription : 'Баннеры, витрины и виджеты, которые покупатели видят первыми.' ,
groupHomepagePurpose : 'Соберите главную страницу из блоков: приветственный баннер, подборки категорий и товаров, акции.' ,
groupHomepageWhere : 'Это первая страница, которую видит покупатель, открыв ваш маркетплейс.' ,
groupHomepageSkip : 'Главная страница останется пустой или будет использовать макет по умолчанию.' ,
groupContentLabel : 'Контент' ,
groupContentDescription : 'О компании, контакты, доставка, возврат и другие информационные страницы.' ,
groupContentPurpose : 'Добавьте страницы, которым покупатели доверяют: о компании, контакты, условия доставки и возврата.' ,
groupContentWhere : 'Ссылки на эти страницы обычно показываются в подвале сайта.' ,
groupContentSkip : 'У покупателей не будет ответов на вопросы о доставке, возврате и контактах — это снижает доверие.' ,
groupLanguagesLabel : 'Языки' ,
groupLanguagesDescription : 'Н а каких языках работает ваш маркетплейс.' ,
groupLanguagesPurpose : 'Выберите язык по умолчанию и добавьте дополнительные языки для покупателей из других регионов.' ,
groupLanguagesWhere : 'Переключатель языка виден в шапке сайта на каждой странице.' ,
groupLanguagesSkip : 'Маркетплейс будет доступен только на одном языке по умолчанию.' ,
groupFeaturesLabel : 'Функции маркетплейса' ,
groupFeaturesDescription : 'Список желаний, сравнение, отзывы, оформление заказа без регистрации и другое.' ,
groupFeaturesPurpose : 'Включите или отключите функции для покупателей: список желаний, сравнение товаров, гостевой заказ.' ,
groupFeaturesWhere : 'Влияет на страницы каталога, товара и оформления заказа.' ,
groupFeaturesSkip : 'Маркетплейс будет использовать функции по умолчанию.' ,
groupNavigationLabel : 'Навигация и поиск' ,
groupNavigationDescription : 'Меню сайта и то, как покупатели находят товары.' ,
groupNavigationPurpose : 'Настройте пункты меню и то, как устроена навигация по каталогу.' ,
groupNavigationWhere : 'Видно в шапке сайта на каждой странице.' ,
groupNavigationSkip : 'Покупатели будут использовать навигацию по умолчанию.' ,
groupPreviewLabel : 'Просмотр' ,
groupPreviewDescription : 'Посмотрите, как маркетплейс выглядит на десктопе, планшете и телефоне.' ,
groupPreviewPurpose : 'Проверьте маркетплейс глазами покупателя перед публикацией — на разных экранах.' ,
groupPreviewWhere : 'Это предпросмотр — покупатели е г о не видят.' ,
groupPreviewSkip : 'Вы можете опубликовать изменения непроверенными.' ,
feat(builder): implement professional brand management experience
New BrandOverviewComponent, mounted at the top of the existing
Branding section page (no route/schema/business-logic changes):
- Completion ring + recommended next step + last-modified timestamp,
computed from real facade signals (branding.logoUrl/faviconUrl/
socialImageUrl, theme.palette, theme.typography, lastSavedAt) -
nothing fabricated.
- Brand Health checklist (6 items: logo, favicon, colors, typography,
social image, accessibility) - icon+text, never color alone.
- Color palette preview: 10 swatches from the real ThemePaletteConfig
(primary/secondary/accent/success/warning/danger/backgrounds/text/
border), each with a readable label.
- Real WCAG contrast check (contrast.util.ts, relative-luminance
formula) between configured text and background colors - shows an
inline warning when below 4.5:1, never blocks publishing.
- Typography live preview using the configured heading/body font
families and base size.
- Social share preview card (Open Graph-style) using the existing
socialImageUrl + seo.default.title/description, with an explicit
empty state when no image is set yet.
Scope cut from the full brief given this session's cost already well
over budget entering this sprint - see Known limitations in the final
report (no multi-variant logo/favicon management, no live responsive
device preview, no new media library/asset picker; all reuse the
existing single-logo/single-favicon fields and image-field upload
component as-is).
Could not verify live in-browser this sprint: port 4200 is held by
another chat's dev server. Verified via `tsc --noEmit` (clean) and
manual template/binding review only; one binding (`--pct` custom-
property style binding) was replaced with a plain computed string to
remove an unverifiable risk rather than ship it unverified.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 10:13:35 +04:00
brandOverviewTitle : 'Идентичность бренда' ,
brandOverviewSubtitle : 'Логотип, цвета и шрифты, которые видят покупатели на каждой странице.' ,
brandOverviewComplete : 'Бренд полностью настроен.' ,
brandLastModified : 'Последнее изменение' ,
brandFaviconUploaded : 'Иконка сайта загружена' ,
brandColorsSelected : 'Цвета бренда выбраны' ,
brandTypographyConfigured : 'Шрифты настроены' ,
brandSocialImageUploaded : 'Изображение для соцсетей загружено' ,
brandAccessibilityPassed : 'Контрастность текста в норме' ,
brandColorsPreviewTitle : 'Цвета маркетплейса' ,
brandTypographyPreviewTitle : 'Шрифты' ,
brandSocialPreviewTitle : 'Как это выглядит при публикации ссылки' ,
brandTypeSampleHeading : 'Пример заголовка' ,
brandTypeSampleBody : 'Пример основного текста, который видят покупатели.' ,
brandContrastWarning : 'Текст на фоне читается плохо — рассмотрите более контрастные цвета. Публикацию это не блокирует.' ,
brandSocialEmpty : 'Изображение для соцсетей ещё не загружено — при публикации ссылки покупатели увидят пустую карточку.' ,
brandAccentColor : 'Акцентный' ,
brandBorderColor : 'Границы' ,
feat(builder): implement visual homepage builder
New HomepageOverviewComponent (Tasks 1+8), mounted at the top of the
existing Homepage section page: completion ring, active/hidden section
counts, recommended next step, last-modified timestamp, and a 6-item
Homepage Health checklist (hero/categories/products/promotion/
newsletter/any-sections) - all derived from the real page.sections/
widgets data already in the facade, nothing fabricated.
Existing page-level drag-and-drop reordering (homepage-section's
CdkDragDrop over page.sections) was already implemented pre-Sprint 5 -
left as-is per "build on top of, do not replace."
Widgets section (Task 2) rewritten from a bare list into visual cards:
per-widget icon + humanized type label (hero/categories/product-
collection), a visible/hidden toggle and badge, up/down move buttons
(keyboard-accessible reorder within a section - see Known limitations
for why this replaces pointer drag for widgets specifically), duplicate,
and remove (with confirm). The existing per-type field editors (hero/
categories/product-collection) are unchanged; the raw-JSON fallback for
unknown widget types now sits behind a collapsed "Advanced settings"
disclosure instead of being the default view.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 10:24:13 +04:00
homepageOverviewTitle : 'Главная страница' ,
homepageOverviewSubtitle : 'Из чего состоит главная страница вашего маркетплейса.' ,
homepageOverviewComplete : 'Главная страница полностью настроена.' ,
homepageActiveSections : 'Активные блоки' ,
homepageDisabledSections : 'Скрытые блоки' ,
homepageHealthHero : 'Приветственный баннер добавлен' ,
homepageHealthCategories : 'Витрина категорий добавлена' ,
homepageHealthProducts : 'Витрина товаров добавлена' ,
homepageHealthPromotion : 'Блок акции добавлен' ,
homepageHealthNewsletter : 'Форма подписки добавлена' ,
homepageHealthAnySections : 'Н а странице есть хотя бы один блок' ,
widgetTypeHero : 'Приветственный баннер' ,
widgetTypeCategories : 'Витрина категорий' ,
widgetTypeProducts : 'Витрина товаров' ,
widgetHidden : 'Скрыт' ,
widgetVisible : 'Показывать' ,
widgetMoveUp : 'Переместить выше' ,
widgetMoveDown : 'Переместить ниже' ,
widgetDuplicate : 'Дублировать' ,
widgetRemove : 'Удалить' ,
widgetRemoveConfirm : 'Удалить этот блок с главной страницы?' ,
widgetAdvancedSettings : 'Дополнительные настройки' ,
2026-07-09 02:29:12 +04:00
} ,
2026-07-14 12:21:33 +04:00
dashboard : {
title : 'Панель управления' ,
subtitle : 'Обзор вашего маркетплейса' ,
cardMarketplaceStatus : 'Статус маркетплейса' ,
cardProjectName : 'Название проекта' ,
cardCurrentTheme : 'Текущая тема' ,
cardLanguages : 'Языки' ,
cardCategoriesCount : 'Категории' ,
cardProductsCount : 'Товары' ,
cardOrders : 'Заказы' ,
cardRevenue : 'Выручка' ,
cardLastPublish : 'Последняя публикация' ,
cardLastDraftSave : 'Последнее сохранение черновика' ,
cardBootstrapVersion : 'Версия конфигурации' ,
cardActiveLayout : 'Активный макет' ,
cardEnabledWidgets : 'Активные виджеты' ,
stateLoading : 'Загрузка...' ,
stateEmpty : 'Пока нет данных' ,
stateError : 'Н е удалось загрузить карточку' ,
statePendingBackend : 'Ожидает интеграции с бэкендом' ,
never : 'Никогда' ,
quickActionsTitle : 'Быстрые действия' ,
feat(builder): redesign marketplace builder experience and navigation
Renamed the experience consistently to Marketplace Builder everywhere
visible (page title/subtitle, breadcrumbs, sidebar, dashboard quick
action/shortcut copy) - internal ProjectEditor class/selector names
kept as-is to avoid regressions. builder.title/subtitle no longer say
'bootstrap-config editing surface' to end users.
New business-oriented IA (builder-groups.model.ts): 12 existing
ProjectEditorSectionIds regrouped into 8 groups (Marketplace, Branding
and Design, Homepage, Content, Languages, Marketplace Features,
Navigation and Search, Preview) - every existing section mapped to
exactly one group, none dropped, no group points at a page that
doesn't exist.
New Builder landing page at /edit (was a redirect straight into the
General form): readiness percent, recommended next step, one overview
card per group (purpose + real complete/in-progress/not-started/unknown
status, icon+text never color-alone), a Marketplace Readiness
checklist, quick links. All derived from real facade/schema signals
(required-field fill state, modifiedSections, staticPages, catalog
counts via BackofficeDataService) or explicitly marked unknown
(the "preview reviewed" check has no tracking - shown as unknown,
never guessed).
Section pages (/edit/:section) now share one consistent header:
breadcrumb (Builder > Group > Section), draft/published + modified
badges, and a contextual help panel (what is this / where visible /
what happens if you skip it) sourced per group. Sidebar nav rewritten
as grouped, icon-led sections with per-section and per-group status
indicators; layout converted from a top pill-tab bar to a responsive
sidebar (desktop 280px, tablet 72px icon rail, mobile drawer with
Escape-to-close), matching the Sprint 1 admin shell pattern. Section
form components themselves untouched.
Routes: 'edit' is now its own landing route instead of redirecting to
'edit/general'; /builder and /project-editor redirect to 'edit'.
Sprint 1/2 destinations that pointed at edit/general now point at the
new edit landing page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 09:43:03 +04:00
actionEditProject : 'Конструктор маркетплейса' ,
2026-07-14 12:21:33 +04:00
actionCategories : 'Категории' ,
actionProducts : 'Товары' ,
actionStaticPages : 'Статические страницы' ,
actionTransactions : 'Транзакции' ,
actionOrders : 'Заказы' ,
actionMediaLibrary : 'Медиатека' ,
2026-07-15 20:25:12 +04:00
actionUsers : 'Пользователи и права' ,
actionMonitoring : 'Мониторинг' ,
actionAnalytics : 'Аналитика' ,
2026-07-14 12:21:33 +04:00
actionPreviewMarketplace : 'Просмотр маркетплейса' ,
activityTitle : 'Недавняя активность' ,
feat(admin): redesign dashboard into professional SaaS homepage
Replaced the placeholder dashboard with a real business homepage built
on 6 new reusable widget components (DashboardSection, DashboardCard,
DashboardMetric, DashboardStatusRow, DashboardTimeline,
DashboardShortcutCard), all wired through shared app-card/app-skeleton/
app-empty-state.
Sections: Welcome (tenant, env badge, current user, last publish/save -
all real facade signals, never blank), Quick Actions (large cards: add
product, create category, open builder, edit homepage, media, orders),
Draft Status (real dirty/modifiedFields/publish/discard from
ProjectEditorFacade), Marketplace Health (9 checks - config, product/
category counts, missing translations, draft, static-pages-unpublished,
homepage/theme configured, all real; images-without-alt shown as
'not tracked yet' rather than fabricated), Recent Activity (existing
localStorage-backed history service, loading/empty states), Useful
Shortcuts, Documentation (honest coming-soon list, no dead links).
12-column responsive grid: 3-across cards on desktop, 2-column on
tablet, single column on mobile, no horizontal scroll. Keyboard/focus/
ARIA per shortcut card and status row; health status never conveyed by
color alone (icon + text every time).
AdminDashboardHealthCheck (boolean 'healthy' shape) and its facade
signal are untouched - AdminMonitoringPageComponent also consumes them.
New richer status data lives in a separate homeHealthChecks signal/
AdminDashboardHomeHealthCheck type instead of widening the shared one.
Added ~50 new dashboard.* / kept existing i18n strings across ru/en/hy;
no raw keys.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 08:59:29 +04:00
activityEmpty : 'Пока нет активности' ,
2026-07-14 12:21:33 +04:00
activityDraftSaved : 'Черновик сохранён' ,
activityPublished : 'Опубликовано' ,
healthTitle : 'Состояние системы' ,
healthAllClear : 'В с е проверки пройдены' ,
healthBootstrapValid : 'Bootstrap корректен' ,
healthConfigurationValid : 'Конфигурация корректна' ,
healthMissingTranslations : 'Отсутствуют переводы' ,
healthInvalidColors : 'Некорректные цвета' ,
healthInvalidWidgetReferences : 'Некорректные ссылки виджетов' ,
healthInvalidLayouts : 'Некорректные макеты' ,
comingSoonTitle : 'Скоро' ,
comingSoonDescription : 'Этот раздел ещё не реализован. Загляните позже.' ,
backToDashboard : 'Вернуться на панель управления' ,
feat(admin): redesign dashboard into professional SaaS homepage
Replaced the placeholder dashboard with a real business homepage built
on 6 new reusable widget components (DashboardSection, DashboardCard,
DashboardMetric, DashboardStatusRow, DashboardTimeline,
DashboardShortcutCard), all wired through shared app-card/app-skeleton/
app-empty-state.
Sections: Welcome (tenant, env badge, current user, last publish/save -
all real facade signals, never blank), Quick Actions (large cards: add
product, create category, open builder, edit homepage, media, orders),
Draft Status (real dirty/modifiedFields/publish/discard from
ProjectEditorFacade), Marketplace Health (9 checks - config, product/
category counts, missing translations, draft, static-pages-unpublished,
homepage/theme configured, all real; images-without-alt shown as
'not tracked yet' rather than fabricated), Recent Activity (existing
localStorage-backed history service, loading/empty states), Useful
Shortcuts, Documentation (honest coming-soon list, no dead links).
12-column responsive grid: 3-across cards on desktop, 2-column on
tablet, single column on mobile, no horizontal scroll. Keyboard/focus/
ARIA per shortcut card and status row; health status never conveyed by
color alone (icon + text every time).
AdminDashboardHealthCheck (boolean 'healthy' shape) and its facade
signal are untouched - AdminMonitoringPageComponent also consumes them.
New richer status data lives in a separate homeHealthChecks signal/
AdminDashboardHomeHealthCheck type instead of widening the shared one.
Added ~50 new dashboard.* / kept existing i18n strings across ru/en/hy;
no raw keys.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 08:59:29 +04:00
welcomeEyebrow : 'С возвращением' ,
welcomeFallbackTenant : 'Ваш маркетплейс' ,
envProduction : 'Продакшн' ,
envDevelopment : 'Разработка' ,
factCurrentUser : 'Текущий пользователь' ,
factTenant : 'Магазин' ,
quickActionsDescription : 'Самые частые задачи — начните здесь' ,
actionAddProduct : 'Добавить товар' ,
actionAddProductDescription : 'Создать новую карточку товара' ,
actionCreateCategory : 'Создать категорию' ,
actionCreateCategoryDescription : 'Добавить категорию в каталог' ,
actionEditProjectDescription : 'Открыть конструктор маркетплейса' ,
actionEditHomepage : 'Редактировать главную' ,
actionEditHomepageDescription : 'Настроить виджеты главной страницы' ,
actionMediaLibraryDescription : 'Загрузить и организовать файлы' ,
actionOrdersDescription : 'Просмотреть последние заказы' ,
draftStatusTitle : 'Статус черновика' ,
draftStatusHasChanges : 'Есть несохранённые изменения, ожидающие публикации.' ,
draftStatusAllPublished : 'Всё опубликовано. Черновика нет.' ,
draftStatusMoreFields : 'ещё {{count}}' ,
draftOpenBuilder : 'Открыть конструктор' ,
draftPublish : 'Опубликовать' ,
draftDiscard : 'Отменить черновик' ,
healthProductsCount : 'Товары' ,
healthCategoriesCount : 'Категории' ,
healthDraftExists : 'Черновик' ,
healthImagesWithoutAlt : 'Изображения без alt-текста' ,
healthStaticPagesUnpublished : 'Неопубликованные статические страницы' ,
healthHomepageConfigured : 'Главная страница настроена' ,
healthThemeConfigured : 'Тема настроена' ,
statusHealthy : 'В порядке' ,
statusAttention : 'Требует внимания' ,
statusUnhealthy : 'Проблема' ,
statusUnknown : 'Пока не отслеживается' ,
activityEmptyHint : 'Сохраните или опубликуйте изменение, чтобы увидеть е г о здесь.' ,
activityUnavailable : 'История активности недоступна' ,
activityUnavailableHint : 'Н е удалось подключиться к источнику данных. Попробуйте обновить страницу позже.' ,
activityErrorHint : 'Н е удалось загрузить недавнюю активность.' ,
shortcutsTitle : 'Полезные ссылки' ,
shortcutsDescription : 'Часто используемые разделы админ-панели' ,
shortcutMarketplaceBuilder : 'Конструктор маркетплейса' ,
shortcutSettings : 'Настройки' ,
shortcutContent : 'Контент' ,
docTitle : 'Документация' ,
docDocumentation : 'Документация' ,
docKeyboardShortcuts : 'Горячие клавиши' ,
docReportIssue : 'Сообщить о проблеме' ,
docReleaseNotes : 'Список изменений' ,
2026-07-14 12:21:33 +04:00
} ,
2026-07-10 13:52:01 +04:00
staticPages : {
notFound : 'Страница не найдена' ,
backHome : 'Н а главную' ,
duplicateSlug : 'Дублирующиеся slug запрещены.' ,
emptyTitle : 'У каждой страницы должен быть хотя бы один заголовок.' ,
feat(static-pages): CRUD completion + search/filter/bulk actions
Milestone 2 of the Static Pages Module sprint.
- StaticPagesEditorComponent: duplicate page, confirm-before-delete/bulk-
delete (matches the resetDraft confirm pattern), route/enabled/customTemplate/
media(hero/thumbnail/gallery) fields wired into the card, per-page publish/
unpublish action, status + duplicate-route/invalid-html/invalid-seo badges.
- Search (id/slug/route/title across all locales), filter by status
(draft/published) and by locale (hides pages missing a translation for the
selected locale) - all local computed() filters, no new service.
- Bulk selection (per-row + select-all-visible checkboxes) with bulk delete/
enable/disable/publish/unpublish, one updateBootstrap() call each.
- Correctness note: introduced `allPages` (unfiltered) vs `pages` (filtered
view) computeds. Every mutation (create/duplicate/delete/move/bulk) reads
from allPages(), never the filtered pages() - reading from the filtered
view would have silently deleted whatever an active search/filter hid on
the next persist(). Documented inline on persist() as a guardrail for
future edits.
- Fixed a template compile error found by the build gate: Angular templates
don't support inline arrow functions in binding expressions
((ngModelChange)="...map(v => v.trim())..." failed to parse) - moved the
gallery CSV-parsing into a component method (updateGallery).
- SEO robots field added to the page card (validated against a known-token
set from M1).
- i18n: staticPages.* extended (search/filter/bulk/route/enabled/status/
media/robots/disabled labels) across the interface + en/ru/hy.
Gate: tsc --noEmit, npm test (57/57), arch:check, build all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 09:55:21 +04:00
duplicateRoute : 'Два или более страниц используют один и тот же маршрут.' ,
invalidHtml : 'Н а этой странице некорректный HTML-контент.' ,
invalidSeo : 'У этой страницы некорректное SEO-поле (canonical/OG-изображение или значение robots).' ,
searchPlaceholder : 'Поиск страниц…' ,
filterAll : 'В с е статусы' ,
filterAllLocales : 'В с е языки' ,
confirmDeletePage : 'Удалить эту страницу? Это действие нельзя отменить.' ,
confirmBulkDelete : 'Удалить выбранные страницы? Это действие нельзя отменить.' ,
duplicatePage : 'Дублировать' ,
selectAll : 'Выбрать все' ,
selectedCount : 'выбрано' ,
bulkDelete : 'Удалить выбранные' ,
bulkEnable : 'Включить выбранные' ,
bulkDisable : 'Отключить выбранные' ,
bulkPublishAction : 'Опубликовать выбранные' ,
bulkUnpublish : 'Снять с публикации выбранные' ,
routeLabel : 'Маршрут' ,
enabledLabel : 'Включена' ,
statusLabel : 'Статус' ,
publishPageAction : 'Опубликовать страницу' ,
unpublishPageAction : 'Снять страницу с публикации' ,
heroImageLabel : 'Главное изображение' ,
thumbnailLabel : 'Миниатюра' ,
galleryLabel : 'Галерея' ,
customTemplateLabel : 'Пользовательский шаблон' ,
seoRobotsLabel : 'Robots' ,
disabledBadge : 'Отключена' ,
2026-07-17 10:11:31 +04:00
previewDesktop : 'Десктоп' ,
previewTablet : 'Планшет' ,
previewMobile : 'Телефон' ,
previewToggle : 'Превью' ,
2026-07-10 13:52:01 +04:00
} ,
2026-07-18 11:02:26 +04:00
contentManagement : {
publishedPages : 'Опубликованные страницы' ,
draftPages : 'Черновики' ,
missingLegalPages : 'Отсутствующие юридические страницы' ,
seoHealth : 'SEO-здоровье' ,
lastEdited : 'Последнее изменение' ,
lastEditedNever : 'Никогда' ,
completionLabel : 'Готовность' ,
recommendedNext : 'Рекомендуемый следующий шаг' ,
recommendAddTitles : 'У некоторых страниц отсутствует заголовок хотя бы на одном языке.' ,
recommendFixSeo : 'Н а одной из страниц есть SEO-поле, которое нужно исправить (canonical/OG-изображение или robots).' ,
recommendPublish : 'Обязательная юридическая страница всё ещё черновик — опубликуйте её.' ,
recommendNone : 'Отлично — контент в хорошем состоянии.' ,
openAction : 'Открыть' ,
backToPages : 'Назад к страницам' ,
groupContent : 'Контент' ,
groupSeo : 'SEO' ,
groupSharing : 'Публикация в соцсетях' ,
groupAdvanced : 'Дополнительно' ,
groupAdvancedHtml : 'Исходный HTML (дополнительно)' ,
seoExplainDesc : 'Это то, что видно в результатах поиска — понятный заголовок и описание помогают клиентам найти страницу.' ,
seoTitleHelp : 'Заголовок, отображаемый в результатах поиска. Делайте е г о коротким и понятным.' ,
seoDescriptionHelp : 'Краткое описание под заголовком в результатах поиска.' ,
seoCanonicalHelp : 'Официальный адрес страницы — помогает избежать дублирования контента.' ,
seoRobotsHelp : 'Определяет, могут ли поисковые системы показывать эту страницу.' ,
sharingExplain : 'Так страница выглядит при публикации в соцсетях (Facebook, Twitter/X и другие).' ,
mediaSelect : 'Выбрать изображение' ,
mediaReplace : 'Заменить' ,
mediaRemove : 'Удалить' ,
mediaAlt : 'Альтернативный текст' ,
mediaCaption : 'Подпись' ,
emptyStateGuideTitle : 'Начните создавать страницы магазина' ,
emptyStateGuideBody : 'Юридические страницы, такие как О нас, Конфиденциальность и Условия, повышают доверие клиентов. Рекомендуем сначала опубликовать О нас, Контакты, Конфиденциальность и Условия, затем добавить Cookies, Доставку, Возвраты и FAQ.' ,
seoStatusGood : 'SEO в порядке' ,
seoStatusPartial : 'SEO частично' ,
seoStatusWarning : 'Проблема SEO' ,
seoStatusMissing : 'SEO отсутствует' ,
needsAttention : 'Требует внимания' ,
legal : {
about : { label : 'О нас' , why : 'Рассказывает клиентам, кто вы, и повышает доверие перед покупкой.' } ,
contacts : { label : 'Контакты' , why : 'Даёт клиентам способ связаться с вами по вопросам.' } ,
privacy : { label : 'Конфиденциальность' , why : 'Объясняет, как обрабатываются данные клиентов — часто обязательно по закону.' } ,
terms : { label : 'Условия' , why : 'Устанавливает правила использования магазина — защищает вас и клиентов.' } ,
cookies : { label : 'Cookies' , why : 'Раскрывает использование cookie — требуется во многих регионах.' } ,
delivery : { label : 'Доставка' , why : 'Задаёт понятные ожидания по доставке и снижает число обращений в поддержку.' } ,
returns : { label : 'Возвраты' , why : 'Объясняет политику возврата и повышает уверенность в покупке.' } ,
faq : { label : 'Вопросы и ответы' , why : 'Отвечает на частые вопросы заранее.' } ,
} ,
} ,
2026-07-09 02:29:12 +04:00
widgets : {
unavailable : 'Виджет недоступен' ,
} ,
2026-02-26 23:09:20 +04:00
carousel : {
loading : 'Загрузка товаров...' ,
addToCart : 'Добавить в корзину' ,
} ,
common : {
retry : 'Попробовать снова' ,
loading : 'Загрузка...' ,
2026-07-17 15:22:45 +04:00
remove : 'Удалить' ,
2026-02-26 23:09:20 +04:00
} ,
2026-02-28 17:18:24 +04:00
location : {
allRegions : 'В с е регионы' ,
chooseRegion : 'Выберите регион' ,
detectAuto : 'Определить автоматически' ,
} ,
auth : {
loginRequired : 'Требуется авторизация' ,
loginDescription : 'Для оформления заказа войдите через Telegram' ,
checking : 'Проверка...' ,
loginWithTelegram : 'Войти через Telegram' ,
orScanQr : 'Или отсканируйте QR-код' ,
loginNote : 'После входа вы будете перенаправлены обратно' ,
2026-03-25 15:32:50 +04:00
qrExpired : 'QR-код устарел. Нажмите, чтобы обновить' ,
2026-06-01 00:47:26 +04:00
qrError : 'Н е удалось создать сессию входа. Нажмите, чтобы повторить' ,
2026-02-28 17:18:24 +04:00
} ,
2026-07-09 01:13:54 +04:00
ux : {
items : 'товаров' ,
wishlistTitle : 'Избранное' ,
wishlistEmptyTitle : 'Избранное пока пусто' ,
wishlistEmptyDescription : 'Сохраняйте товары, чтобы быстро вернуться к ним позже.' ,
clearWishlist : 'Очистить избранное' ,
2026-07-09 02:29:12 +04:00
wishlistCleared : 'Избранное очищено' ,
2026-07-09 01:13:54 +04:00
compareTitle : 'Сравнение товаров' ,
compareEmptyTitle : 'Нет товаров для сравнения' ,
compareEmptyDescription : 'Добавьте товары из каталога, чтобы сравнить характеристики и цену.' ,
clearCompare : 'Очистить сравнение' ,
hideIdentical : 'Скрыть одинаковые значения' ,
highlightDifferences : 'Подсвечивать различия' ,
clearRecentlyViewed : 'Очистить просмотренные' ,
recentlyViewedEmpty : 'Вы пока не просматривали товары.' ,
saveSearch : 'Сохранить поиск' ,
goToCatalog : 'Перейти в каталог' ,
2026-07-09 01:40:22 +04:00
wishlistAdded : 'Добавлено в избранное' ,
wishlistRemoved : 'Удалено из избранного' ,
compareAdded : 'Добавлено в сравнение' ,
compareRemoved : 'Удалено из сравнения' ,
compareLimitReached : 'Достигнут лимит сравнения ({{maxItems}})' ,
productShared : 'Товар отправлен' ,
productLinkCopied : 'Ссылка на товар скопирована' ,
sharingUnsupported : 'Н а этом устройстве нет поддержки шаринга' ,
2026-07-09 02:29:12 +04:00
addedToCart : 'Добавлено в корзину' ,
2026-07-09 01:40:22 +04:00
enterQueryBeforeSave : 'Введите поисковый запрос перед сохранением' ,
savedSearchNamed : 'Сохраненный поиск: {{name}}' ,
2026-07-09 02:29:12 +04:00
recentlyViewedTitle : 'Недавно просмотренные' ,
compareAttribute : 'Атрибут' ,
comparePrice : 'Цена' ,
compareRating : 'Рейтинг' ,
compareStock : 'Наличие' ,
compareDiscount : 'Скидка' ,
compareColor : 'Цвет' ,
compareSize : 'Размер' ,
compareUnknown : 'неизвестно' ,
2026-07-09 01:13:54 +04:00
} ,
2026-07-10 13:34:25 +04:00
diagnostics : {
title : 'Диагностика маркетплейса' ,
disabledTitle : 'Диагностика недоступна' ,
disabledDescription : 'Страница диагностики доступна только в режиме разработки.' ,
generatedAt : 'Сформировано: {{value}}' ,
healthScore : 'Оценка состояния' ,
summary : 'Сводка' ,
passedChecks : '{{count}} успешных проверок' ,
warnings : '{{count}} предупреждений' ,
errors : '{{count}} ошибок' ,
critical : '{{count}} критических' ,
healthChecks : 'Проверки состояния' ,
results : 'Подробные результаты' ,
noIssues : 'Проблем диагностики не найдено.' ,
ok : 'OK' ,
failed : 'Ошибка' ,
affectedComponent : 'Затронутый компонент' ,
suggestedResolution : 'Рекомендация' ,
severity : { info : 'Инфо' , warning : 'Предупреждение' , error : 'Ошибка' , critical : 'Критично' } ,
checks : {
bootstrapLoaded : 'Bootstrap загружен' ,
tenantResolved : 'Tenant определен' ,
runtimeInitialized : 'Runtime инициализирован' ,
themeLoaded : 'Тема загружена' ,
widgetManifestLoaded : 'Манифест виджетов загружен' ,
sectionEngineInitialized : 'Section Engine доступен' ,
configurationEngineInitialized : 'Configuration Engine инициализирован' ,
translationResourcesAvailable : 'Переводы доступны' ,
requiredAssetsAvailable : 'Обязательные assets доступны' ,
} ,
bootstrapMissingTitle : 'Bootstrap отсутствует' ,
bootstrapMissingDescription : 'Конфигурация bootstrap не загружена.' ,
bootstrapMissingResolution : 'Проверьте provider bootstrap и локальный mock.' ,
requiredPropertyMissingTitle : 'Отсутствует обязательное свойство' ,
requiredPropertyMissingDescription : 'В bootstrap отсутствует обязательное свойство.' ,
requiredPropertyMissingResolution : 'Добавьте свойство в bootstrap payload.' ,
unknownWidgetTypeTitle : 'Неизвестный тип виджета' ,
unknownWidgetTypeDescription : 'Тип виджета отсутствует в widget manifest.' ,
unknownWidgetTypeResolution : 'Добавьте виджет в manifest или удалите неверную конфигурацию.' ,
duplicateIdTitle : 'Дублирующийся идентификатор' ,
duplicatePageIdDescription : 'Обнаружен дублирующийся id страницы.' ,
duplicateSectionIdDescription : 'Обнаружен дублирующийся id секции.' ,
duplicateWidgetIdDescription : 'Обнаружен дублирующийся id виджета.' ,
duplicateIdResolution : 'Сделайте id уникальными в bootstrap конфигурации.' ,
unknownLayoutTitle : 'Неизвестный layout' ,
unknownLayoutDescription : 'Значение layout страницы не распознано.' ,
unknownLayoutResolution : 'Используйте поддерживаемый layout или расширьте allow-list.' ,
invalidFeatureFlagTitle : 'Некорректный feature flag' ,
invalidFeatureFlagDescription : 'Значение feature flag должно быть boolean.' ,
invalidFeatureFlagResolution : 'Нормализуйте значение к true или false.' ,
brokenPageDefinitionTitle : 'Некорректное описание страницы' ,
brokenPageDefinitionDescription : 'Описание страницы неполное.' ,
brokenPageDefinitionResolution : 'Добавьте route, title, key или sections.' ,
invalidNavigationTargetTitle : 'Некорректная цель навигации' ,
invalidNavigationTargetDescription : 'Route навигации не совпадает с известными route.' ,
invalidNavigationTargetResolution : 'Исправьте target route или добавьте route.' ,
missingTranslationTitle : 'Отсутствует перевод' ,
missingTranslationDescription : 'Ключ перевода не разрешается.' ,
missingTranslationResolution : 'Добавьте ключ в translation resources.' ,
missingMediaTitle : 'Отсутствует media' ,
missingMediaDescription : 'Ожидаемый branding media р е с у р с отсутствует.' ,
missingMediaResolution : 'Укажите корректные media URL в branding конфиге.' ,
runtimeNotInitializedTitle : 'Runtime не инициализирован' ,
runtimeNotInitializedDescription : 'Platform runtime state не помечен как initialized.' ,
runtimeNotInitializedResolution : 'Проверьте цепочку initialize в PlatformRuntimeService.' ,
configFallbackUsageTitle : 'Используется fallback конфигурация' ,
configFallbackUsageDescription : 'Runtime разработки использует fallback или mock конфигурацию.' ,
configFallbackUsageResolution : 'Смените provider mode, если нужна проверка реального bootstrap.' ,
missingDatasourceTitle : 'Отсутствует datasource' ,
missingDatasourceDescription : 'Виджет поддерживает datasource, но он не задан.' ,
missingDatasourceResolution : 'Укажите source в props виджета или default settings manifest.' ,
widgetRenderFailureTitle : 'Сбой рендера виджета' ,
widgetRenderFailureDescription : 'Виджет откатился на unknown widget renderer.' ,
widgetRenderFailureResolution : 'Зарегистрируйте компонент виджета или исправьте component key.' ,
brokenRouteTitle : 'Нарушено ожидание route' ,
brokenRouteDescription : 'Ожидаемый route отсутствует.' ,
brokenRouteResolution : 'Верните регистрацию route или обновите правило диагностики.' ,
imageLoadFailedTitle : 'Ошибка загрузки изображения' ,
imageLoadFailedDescription : 'Отображаемое изображение не загрузилось.' ,
imageLoadFailedResolution : 'Проверьте asset path, CORS и доступность media.' ,
optionalDataMissingTitle : 'Отсутствуют необязательные данные' ,
optionalDataMissingDescription : 'Необязательное конфигурационное значение отсутствует.' ,
optionalDataMissingResolution : 'Добавьте значение, если оно нужно UX.' ,
} ,
feat(media): add Media Manager UI (grid, upload, delete)
MediaLibraryPageComponent replaces the coming-soon placeholder at
/backoffice/media. Built entirely on Sprint 6 Design System primitives
(app-card, app-button, app-input, app-empty-state, app-dialog, app-pagination,
app-skeleton) and Sprint 4 Task 2's MediaRepository/MockMediaRepository.
- Grid view with per-tile filename/size and delete action
- Hidden native file input triggered by an app-button, uploads via
MediaLibraryFacade -> MediaRepository.upload()
- Delete requires confirmation through app-dialog (destructive action)
- Search + pagination wired to MockMediaRepository's list() params
- Loading state shows app-skeleton tiles; empty state shows app-empty-state
- New mediaLibrary.* translation namespace across en/ru/hy
Verified in browser (via a temporary unguarded route, reverted before
commit - /backoffice/media itself requires Telegram QR admin auth not
available in this session): empty state renders correctly with translated
copy, search input and upload button present, no console errors.
2026-07-15 07:14:16 +04:00
mediaLibrary : {
title : 'Медиатека' ,
upload : 'Загрузить' ,
uploading : 'Загрузка...' ,
searchPlaceholder : 'Поиск файлов...' ,
delete : 'Удалить' ,
deleteConfirmTitle : 'Удалить файл?' ,
deleteConfirmBody : 'Это действие необратимо.' ,
cancel : 'Отмена' ,
confirm : 'Удалить' ,
emptyTitle : 'Пока нет файлов' ,
emptyDescription : 'Загрузите изображение или документ, чтобы начать.' ,
feat(builder): implement reusable media library
Media dashboard (real total/images/SVG/logos/unused/storage/alt-coverage, computed from actual assets + a bootstrap usage scan, no fabricated stats); gallery gets grid/list toggle, type filter, sort, drag-and-drop + multi-file upload with cancel/retry and friendly error mapping, lazy thumbnails, multi-select with bulk delete/download/export-metadata; asset details drawer shows real dimensions/size/format/date/usage locations (walks bootstrap config for exact URL matches, reports not-used rather than guessing) plus editable alt text/caption/description/decorative flag with missing-alt warning; shared MediaPickerComponent (already the one reusable picker used by content management) gains type filter, a recent shortcut, and keyboard grid navigation.
2026-07-18 16:09:47 +04:00
allFolders : 'В с е папки' ,
newFolder : 'Новая папка' ,
editTags : 'Изменить теги' ,
totalAssets : 'В с е г о файлов' ,
logos : 'Логотипы' ,
unused : 'Неиспользуемые' ,
storageUsed : 'Использовано места' ,
altCoverage : 'Покрытие alt-текстом' ,
allTypes : 'В с е типы' ,
typeImage : 'Изображения' ,
typeSvg : 'SVG' ,
typePdf : 'PDF' ,
sortRecent : 'Недавние' ,
sortName : 'Имя' ,
sortSize : 'Размер' ,
viewMode : 'Вид' ,
viewGrid : 'Сетка' ,
viewList : 'Список' ,
dropHint : 'Перетащите изображения сюда или используйте кнопку «Загрузить» выше.' ,
cancelUpload : 'Отменить' ,
retry : 'Повторить' ,
errorTooLarge : 'Файл слишком большой. Попробуйте файл меньшего размера.' ,
errorUnsupportedType : 'Этот тип файла не поддерживается. Используйте JPG, PNG, WebP, GIF, SVG или PDF.' ,
errorGeneric : 'Н е удалось загрузить файл. Попробуйте ещё раз.' ,
selectedCount : 'выбрано' ,
download : 'Скачать' ,
exportMetadata : 'Экспортировать метаданные' ,
bulkDelete : 'Удалить выбранные' ,
bulkDeleteConfirm : 'Удалить выбранные файлы? Это действие нельзя отменить.' ,
clearSelection : 'Снять выделение' ,
guideCopy : 'Повторное использование существующего файла избавляет от дублей и экономит место. Для баннеров и главных изображений рекомендуем размер около 1200× 1200px и сжатие крупных фото перед загрузкой.' ,
missingAlt : 'Нет alt-текста' ,
usageCount : 'исп.' ,
detailsTitle : 'Информация о файле' ,
filename : 'Имя файла' ,
format : 'Формат' ,
fileSize : 'Размер файла' ,
dimensions : 'Размеры' ,
uploadDate : 'Загружен' ,
lastUsed : 'Последнее использование' ,
usageCountLabel : 'Количество использований' ,
usedIn : 'Используется в' ,
notUsed : 'Пока нигде не используется.' ,
unknownValue : 'Неизвестно' ,
altText : 'Alt-текст' ,
altTextHelp : 'Описывает изображение для программ чтения с экрана и поисковых систем.' ,
decorative : 'Декоративное (alt-текст не нужен)' ,
missingAltWarning : 'У этого изображения нет alt-текста, и оно не отмечено как декоративное — пользователи с программами чтения с экрана не узнают, что на нём изображено.' ,
caption : 'Подпись' ,
description : 'Описание' ,
usage : {
brand : 'Логотип' ,
theme : 'Тема' ,
header : 'Шапка' ,
footer : 'Подвал' ,
staticPage : 'Статическая страница' ,
homepage : 'Главная страница' ,
catalog : 'Каталог' ,
productPage : 'Страница товара' ,
widget : 'Виджет' ,
company : 'Информация о компании' ,
seo : 'SEO' ,
navigation : 'Навигация' ,
other : 'Другое' ,
} ,
feat(media): add Media Manager UI (grid, upload, delete)
MediaLibraryPageComponent replaces the coming-soon placeholder at
/backoffice/media. Built entirely on Sprint 6 Design System primitives
(app-card, app-button, app-input, app-empty-state, app-dialog, app-pagination,
app-skeleton) and Sprint 4 Task 2's MediaRepository/MockMediaRepository.
- Grid view with per-tile filename/size and delete action
- Hidden native file input triggered by an app-button, uploads via
MediaLibraryFacade -> MediaRepository.upload()
- Delete requires confirmation through app-dialog (destructive action)
- Search + pagination wired to MockMediaRepository's list() params
- Loading state shows app-skeleton tiles; empty state shows app-empty-state
- New mediaLibrary.* translation namespace across en/ru/hy
Verified in browser (via a temporary unguarded route, reverted before
commit - /backoffice/media itself requires Telegram QR admin auth not
available in this session): empty state renders correctly with translated
copy, search input and upload button present, no console errors.
2026-07-15 07:14:16 +04:00
} ,
fix(static-pages): backfill enabled/status in export, fix missing i18n key
Independent review pass over the Static Pages Module sprint (M1-M7),
including live browser E2E per the task's own verification checklist.
- ProjectEditorFacade.normalize() now backfills enabled/status on
record-format static pages (defaulting missing values to enabled+published,
same rule ContentPageService.normalizePage applies for display - mirrored
rather than imported, to avoid a project-editor <-> content-management
circular dependency since ContentManagementFacade already depends on this
facade). Found live: exporting a page that predates this sprint and was
never touched/re-saved in the current session produced JSON missing
enabled/status entirely - the editor UI and storefront resolver both
normalize-on-read so nothing was actually broken live, but Export/Import
fidelity should match what the editor shows. Verified fixed live (export
now includes "enabled":true,"status":"published" for an untouched legacy
page) and via the full gate.
- Added the missing adminCategories.chooseImage i18n key (interface +
en/ru/hy). Found live: the media-picker "choose image" button rendered as
the literal string "adminCategories.chooseImage" - a pre-existing,
repo-wide bug (5 templates reference this key; none of the locale files
ever defined it) that I propagated into a 3rd/4th/5th... well, 2 new
occurrences by copying the existing branding-section/footer-section
pattern into static-pages-editor. Fixed the actual defect (missing
translation) rather than renaming the key, which would have required
touching 2 unrelated admin components outside this sprint's scope.
Live-verified this pass: Static Pages editor renders with all new fields;
create page works (page count 4->confirmed); device preview toggles
desktop/tablet/mobile widths correctly; navigation "Insert page link"
creates a real type:'staticPage' nav item end-to-end (confirmed in the
exported JSON); export includes all Sprint X+2 fields after the fix; no
console errors throughout.
Gate: tsc --noEmit, npm test (57/57), arch:check, build all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:27:29 +04:00
adminCategories : {
chooseImage : 'Выбрать изображение' ,
2026-07-17 15:22:45 +04:00
replaceImage : 'Заменить изображение' ,
fix(static-pages): backfill enabled/status in export, fix missing i18n key
Independent review pass over the Static Pages Module sprint (M1-M7),
including live browser E2E per the task's own verification checklist.
- ProjectEditorFacade.normalize() now backfills enabled/status on
record-format static pages (defaulting missing values to enabled+published,
same rule ContentPageService.normalizePage applies for display - mirrored
rather than imported, to avoid a project-editor <-> content-management
circular dependency since ContentManagementFacade already depends on this
facade). Found live: exporting a page that predates this sprint and was
never touched/re-saved in the current session produced JSON missing
enabled/status entirely - the editor UI and storefront resolver both
normalize-on-read so nothing was actually broken live, but Export/Import
fidelity should match what the editor shows. Verified fixed live (export
now includes "enabled":true,"status":"published" for an untouched legacy
page) and via the full gate.
- Added the missing adminCategories.chooseImage i18n key (interface +
en/ru/hy). Found live: the media-picker "choose image" button rendered as
the literal string "adminCategories.chooseImage" - a pre-existing,
repo-wide bug (5 templates reference this key; none of the locale files
ever defined it) that I propagated into a 3rd/4th/5th... well, 2 new
occurrences by copying the existing branding-section/footer-section
pattern into static-pages-editor. Fixed the actual defect (missing
translation) rather than renaming the key, which would have required
touching 2 unrelated admin components outside this sprint's scope.
Live-verified this pass: Static Pages editor renders with all new fields;
create page works (page count 4->confirmed); device preview toggles
desktop/tablet/mobile widths correctly; navigation "Insert page link"
creates a real type:'staticPage' nav item end-to-end (confirmed in the
exported JSON); export includes all Sprint X+2 fields after the fix; no
console errors throughout.
Gate: tsc --noEmit, npm test (57/57), arch:check, build all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:27:29 +04:00
} ,
2026-07-16 00:19:41 +04:00
adminProducts : {
emptyTitle : 'Товары не найдены' ,
emptyDescription : 'Измените фильтры или создайте новый товар.' ,
feat(products): implement professional product management experience
Products dashboard (real total/published/drafts/out-of-stock/hidden/missing-images/missing-SEO/low-quality counts, recently-edited list, recommended next action); list gains table/grid view toggle, density, saved column visibility and saved sort (persisted via LocalStorageService), plus real bulk assign-category/assign-tags/duplicate/CSV-export alongside existing publish/hide/delete; per-row and per-editor reusable ProductHealthWidget (images/SEO/price/category/description/inventory checklist + completion %); editor reorganized into General/Media/Pricing/Inventory/Categories/Attributes/SEO/Visibility/Advanced tabs, media now uses the shared MediaPickerComponent/ImageFieldComponent (primary image + reorderable gallery) instead of raw URL textareas, specifications/attributes/variants moved off pipe-delimited textareas onto the shared KeyValueEditorComponent, SEO tab explains fields in plain language with a live search-result preview, inventory relabeled in business language, toggles/badges use the shared Toggle/Badge components. Filled in the adminProducts i18n namespace (previously ~98% missing, rendering raw translation keys) across en/ru/hy.
2026-07-18 16:34:06 +04:00
emptyGuide : 'Хорошему товару нужны понятное название, минимум одно фото, цена и короткое описание — этого достаточно для публикации. Остальное можно добавить позже.' ,
search : 'Поиск товаров…' ,
category : 'Категория' ,
allCategories : 'В с е категории' ,
visibility : 'Видимость' ,
allVisibility : 'Любая видимость' ,
visible : 'Видимый' ,
hidden : 'Скрытый' ,
stockStatus : 'Статус наличия' ,
allStock : 'Любой остаток' ,
inStock : 'В наличии' ,
lowStock : 'Мало на складе' ,
outOfStock : 'Нет в наличии' ,
sortTitle : 'Имя' ,
sortPrice : 'Цена' ,
sortPriority : 'Приоритет' ,
sortStock : 'Остаток' ,
sortUpdated : 'Последнее изменение' ,
showArchived : 'Показать архивные' ,
infiniteScroll : 'Бесконечная прокрутка' ,
viewMode : 'Вид' ,
viewTable : 'Таблица' ,
viewGrid : 'Сетка' ,
density : 'Плотность' ,
densityComfortable : 'Комфортная' ,
densityCompact : 'Компактная' ,
columns : 'Столбцы' ,
column_sku : 'Артикул' ,
column_brand : 'Бренд' ,
column_price : 'Цена' ,
column_stock : 'Остаток' ,
column_visibility : 'Видимость' ,
column_updated : 'Последнее изменение' ,
create : 'Создать товар' ,
edit : 'Редактировать товар' ,
duplicate : 'Дублировать' ,
selectedCount : 'выбрано' ,
bulkShow : 'Опубликовать' ,
bulkHide : 'Скрыть' ,
bulkAssignCategory : 'Назначить категорию' ,
bulkAssignTags : 'Назначить теги' ,
bulkDuplicateAction : 'Дублировать' ,
bulkExportAction : 'Экспорт' ,
bulkDelete : 'Удалить' ,
tagsPlaceholder : 'например, лето, скидка' ,
name : 'Название' ,
brand : 'Бренд' ,
healthColumn : 'Качество' ,
actions : 'Действия' ,
archive : 'В архив' ,
delete : 'Удалить' ,
items : 'товаров' ,
loadMore : 'Загрузить ещё' ,
noImage : 'Нет изображения' ,
slug : 'URL-адрес' ,
barcode : 'Штрихкод' ,
priority : 'Приоритет' ,
shortDescription : 'Краткое описание' ,
translations : 'Переводы' ,
primaryImage : 'Главное изображение' ,
primaryImageHint : 'Основное фото, показываемое в списках и результатах поиска.' ,
gallery : 'Галерея' ,
galleryHint : 'Дополнительные фото на странице товара. Порядок меняется стрелками.' ,
moveLeft : 'Переместить раньше' ,
moveRight : 'Переместить позже' ,
videos : 'Видео (по одной ссылке на строку)' ,
discount : 'Скидка %' ,
currency : 'Валюта' ,
stockQuantity : 'Количество на складе' ,
stockQuantityHint : 'Сколько единиц доступно для продажи прямо сейчас.' ,
availabilityStatus : 'Доступность' ,
availabilityStatusHint : 'Что видит покупатель: в наличии, заканчивается или нет в наличии.' ,
availabilityNote : 'Примечание о доступности' ,
availabilityNoteHint : 'Дополнительная информация для покупателя, например «Доставка за 3 дня».' ,
reservedNote : 'Резерв пока не учитывается отдельно — здесь показано общее доступное количество.' ,
relatedProducts : 'Похожие товары' ,
specifications : 'Характеристики' ,
attributes : 'Атрибуты' ,
addRow : 'Добавить строку' ,
removeRow : 'Удалить' ,
rowKey : 'Название' ,
rowValue : 'Значение' ,
addVariant : 'Добавить вариант' ,
variantName : 'Название варианта' ,
variantsHint : 'Каждый вариант — это отдельный покупаемый вариант товара (например, размер или цвет) с о своей ценой и остатком.' ,
seoExplain : 'Это то, что видно в результатах поиска — понятные заголовок и описание помогают найти товар.' ,
searchTitle : 'Заголовок для поиска' ,
searchTitleHint : 'Заголовок, показываемый в результатах поиска. Делайте е г о коротким.' ,
searchDescription : 'Описание для поиска' ,
searchDescriptionHint : 'Краткое описание под заголовком в результатах поиска.' ,
seoMissingTitle : 'Добавьте заголовок для поиска, чтобы товар можно было найти.' ,
seoMissingDescription : 'Добавьте описание для поиска, чтобы улучшить отображение товара.' ,
keywords : 'Ключевые слова' ,
featured : 'Рекомендуемый' ,
recommended : 'В подборке' ,
new : 'Новинка' ,
bestseller : 'Хит продаж' ,
badges : 'Значки (через запятую)' ,
htmlDescription : 'Подробное описание' ,
customer : 'Отзывы покупателей' ,
reviewsReadonly : 'Отзывы' ,
noReviews : 'Пока нет отзывов.' ,
questionsReadonly : 'Вопросы' ,
noQuestions : 'Пока нет вопросов.' ,
save : 'Сохранить товар' ,
groupGeneral : 'Основное' ,
groupMedia : 'Медиа' ,
groupPricing : 'Цена' ,
groupInventory : 'Склад' ,
groupCategories : 'Категории' ,
groupAttributes : 'Атрибуты' ,
groupSeo : 'SEO' ,
groupVisibility : 'Видимость' ,
groupAdvanced : 'Дополнительно' ,
healthImages : 'Изображения' ,
healthSeo : 'SEO' ,
healthPrice : 'Цена' ,
healthCategory : 'Категория' ,
healthDescription : 'Описание' ,
healthInventory : 'Склад' ,
totalProducts : 'В с е г о товаров' ,
publishedCount : 'Опубликовано' ,
draftsCount : 'Черновики' ,
outOfStockCount : 'Нет в наличии' ,
hiddenCount : 'Скрыто' ,
missingImagesCount : 'Без изображений' ,
missingSeoCount : 'Без SEO' ,
lowQualityCount : 'Низкое качество' ,
recentlyEdited : 'Недавно изменённые' ,
recommendedNext : 'Рекомендуемый следующий шаг' ,
openAction : 'Открыть' ,
recommendAddImages : 'У товара нет фото — добавьте хотя бы одно изображение.' ,
recommendAddSeo : 'У товара нет заголовка или описания для поиска — добавьте их.' ,
recommendRestock : 'Товар закончился на складе — пополните запас или скройте е г о .' ,
recommendNone : 'Отлично — каталог в хорошем состоянии.' ,
2026-07-16 00:19:41 +04:00
} ,
adminUsers : {
emptyTitle : 'Пользователи не найдены' ,
emptyDescription : 'Пригласите коллегу, чтобы начать.' ,
invitationsEmptyTitle : 'Нет ожидающих приглашений' ,
} ,
adminMonitoring : {
eventsEmptyTitle : 'События не найдены' ,
eventsEmptyDescription : 'Попробуйте изменить фильтр категории или поисковый запрос.' ,
} ,
adminAnalytics : {
topProductsEmptyTitle : 'Нет продаж товаров за этот период' ,
topProductsEmptyDescription : 'Попробуйте выбрать более широкий диапазон дат.' ,
} ,
feat(admin): build shared admin shell
Sidebar (Dashboard/Catalog group/Products/Categories/Orders/Transactions/
Reviews/Reports/Content/Media/Marketplace Builder/Users/Settings/
Monitoring/Analytics + Documentation/Help/Logout), sticky topbar
(breadcrumbs, page title/description, search, notifications, tenant
selector and quick-publish placeholders, current user), reserved
right-rail slot, scrollable content area. Desktop 280px sidebar, tablet
icon rail, mobile drawer with focus management and Escape-to-close.
Nav items without a built page (Reviews, Reports, Settings, Docs, Help)
render disabled with a coming-soon badge instead of dead links; Content
and Marketplace Builder route to the existing project-editor pages
(static-pages / general) rather than duplicating them.
All 15 /backoffice/** routes now render through AdminLayoutComponent;
the public storefront header/back-button/footer no longer render on
admin routes (app.ts/app.html gate on a new isAdminRoute signal).
Added the adminShell i18n namespace (ru/en/hy) for every new shell
string so this doesn't add to the existing untranslated-admin-UI gap
tracked in KNOWN-ISSUES.md.
Colors/type sizes follow DESIGN.md tokens; the two rgba() modal-scrim
values are a documented, intentional exception (neutral overlay,
not a themed token).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 00:12:19 +04:00
adminShell : {
skipToContent : 'Перейти к содержимому' ,
openSidebar : 'Открыть меню' ,
closeSidebar : 'Закрыть меню' ,
collapseSidebar : 'Свернуть меню' ,
expandSidebar : 'Развернуть меню' ,
nav : {
dashboard : 'Панель управления' ,
catalogGroup : 'Каталог' ,
products : 'Товары' ,
categories : 'Категории' ,
orders : 'Заказы' ,
transactions : 'Транзакции' ,
reviews : 'Отзывы' ,
reports : 'Отчёты' ,
content : 'Контент' ,
mediaLibrary : 'Медиатека' ,
marketplaceBuilder : 'Конструктор маркетплейса' ,
users : 'Пользователи' ,
settings : 'Настройки' ,
monitoring : 'Мониторинг' ,
analytics : 'Аналитика' ,
documentation : 'Документация' ,
help : 'Помощь' ,
logout : 'Выйти' ,
comingSoonBadge : 'Скоро' ,
} ,
topbar : {
searchLabel : 'Поиск по админ-панели' ,
searchPlaceholder : 'Искать товары, заказы, страницы...' ,
notifications : 'Уведомления' ,
notificationsEmpty : 'Новых уведомлений нет' ,
account : 'Аккаунт администратора' ,
tenantSelector : 'Магазин' ,
tenantSelectorComingSoon : 'Переключение между магазинами скоро появится' ,
quickPublish : 'Опубликовать' ,
quickPublishComingSoon : 'Быстрая публикация скоро появится' ,
} ,
breadcrumbHome : 'Админ-панель' ,
pages : {
dashboard : { title : 'Панель управления' , description : 'Обзор состояния вашего маркетплейса' } ,
products : { title : 'Товары' , description : 'Управляйте карточками товаров и их видимостью' } ,
productCreate : { title : 'Новый товар' , description : 'Заполните карточку, чтобы добавить товар в каталог' } ,
productEdit : { title : 'Редактирование товара' , description : 'Измените данные товара' } ,
productDuplicate : { title : 'Копия товара' , description : 'Создайте новый товар на основе существующего' } ,
categories : { title : 'Категории' , description : 'Постройте дерево категорий каталога' } ,
categoryCreate : { title : 'Новая категория' , description : 'Добавьте категорию в дерево каталога' } ,
categoryEdit : { title : 'Редактирование категории' , description : 'Измените данные категории' } ,
orders : { title : 'Заказы' , description : 'Просматривайте и обрабатывайте заказы покупателей' } ,
orderDetail : { title : 'Заказ' , description : 'Детали и статус заказа' } ,
transactions : { title : 'Транзакции' , description : 'Платежи, возвраты и проверка мошенничества' } ,
media : { title : 'Медиатека' , description : 'Изображения и файлы для товаров и страниц' } ,
users : { title : 'Пользователи' , description : 'Команда администраторов и права доступа' } ,
monitoring : { title : 'Мониторинг' , description : 'Состояние очередей, вебхуков и системных событий' } ,
analytics : { title : 'Аналитика' , description : 'Продажи, товары и поведение покупателей' } ,
} ,
} ,
2026-02-26 23:09:20 +04:00
} ;