fix(i18n): eliminate all raw translation key leaks across admin pages

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

- Audited every 'key | translate' and translateService.t() usage under features/admin against en/ru/hy; 37 static keys and 8 dynamic namespaces were missing and rendered as raw keys
- Added full adminTransactions namespace (was entirely absent), adminUsers table/invite/session keys with scopeValue/statusValue/invitationStatus maps, adminMonitoring section titles and categoryValue/queueStatus/webhookStatus/levelValue maps, adminAnalytics.topProducts, adminProducts.variants/archived
- Resolved leaf/object key conflicts: dynamic 'adminMonitoring.category.*' renamed to categoryValue.*, 'adminTransactions.type.*' to typeValue.* so the leaf labels translate correctly
- Monitoring event severity now translated (levelValue) instead of raw English enum
- Merchant wording over technical: 'Background queues', 'Webhook deliveries', 'Activity log', 'Running smoothly/Slowed down/Stopped'
- Verified zero missing keys in en/ru/hy via AST-level key extraction
This commit is contained in:
sdarbinyan
2026-07-18 22:44:39 +04:00
parent 6af746c561
commit 574f038738
6 changed files with 369 additions and 5 deletions

View File

@@ -1535,6 +1535,8 @@ export const en: Translations = {
addVariant: 'Add variant',
variantName: 'Variant name',
variantsHint: 'Each variant is a purchasable option of this product, e.g. a size or color, with its own price and stock.',
variants: 'Variants',
archived: 'Archived',
seoExplain: 'This is what shows up in search results — a clear title and description help customers find this product.',
searchTitle: 'Search title',
searchTitleHint: 'The headline shown in search results. Keep it short and descriptive.',
@@ -1590,10 +1592,98 @@ export const en: Translations = {
emptyTitle: 'No users found',
emptyDescription: 'Invite a teammate to get started.',
invitationsEmptyTitle: 'No pending invitations',
title: 'Team members',
name: 'Name',
email: 'Email',
scope: 'Workspace',
role: 'Role',
roles: 'Roles',
lastLogin: 'Last sign-in',
sessions: 'Active sessions',
currentSession: 'This session',
invite: 'Invite member',
sendInvite: 'Send invitation',
revoke: 'Revoke',
passwordlessHint: 'Team members sign in with Telegram - no passwords to manage.',
confirmSuspend: 'Suspend this team member? They will lose access immediately.',
scopeValue: {
marketplace: 'Storefront',
office: 'Back office',
},
statusValue: {
active: 'Active',
invited: 'Invited',
suspended: 'Suspended',
},
invitationStatus: {
pending: 'Pending',
accepted: 'Accepted',
expired: 'Expired',
revoked: 'Revoked',
},
},
adminTransactions: {
search: 'Search transactions',
type: 'Type',
method: 'Payment method',
fraud: 'Fraud check',
flagged: 'Flagged',
retry: 'Retry',
audit: 'History',
emptyTitle: 'No transactions found',
emptyDescription: 'Try a different filter or search term.',
status: {
all: 'All statuses',
pending: 'Pending',
success: 'Successful',
failed: 'Failed',
retried: 'Retried',
},
typeValue: {
all: 'All types',
payment: 'Payment',
refund: 'Refund',
qr_payment: 'QR payment',
},
},
adminMonitoring: {
eventsEmptyTitle: 'No events found',
eventsEmptyDescription: 'Try a different category filter or search term.',
health: 'Health checks',
queues: 'Background queues',
depth: 'Waiting',
webhooks: 'Webhook deliveries',
endpoint: 'Destination',
event: 'Event',
events: 'Activity log',
category: 'Category',
level: 'Severity',
message: 'Description',
categoryValue: {
all: 'All categories',
audit: 'Admin activity',
security: 'Security',
login: 'Sign-in',
failed_login: 'Failed sign-in',
api: 'API',
error: 'Error',
warning: 'Warning',
},
queueStatus: {
healthy: 'Running smoothly',
degraded: 'Slowed down',
down: 'Stopped',
},
webhookStatus: {
delivered: 'Delivered',
failed: 'Failed',
pending: 'Pending',
},
levelValue: {
info: 'Info',
warning: 'Warning',
error: 'Error',
},
systemState: 'System state',
backendConnectivity: 'Backend',
connected: 'Connected',
@@ -1608,6 +1698,7 @@ export const en: Translations = {
adminAnalytics: {
topProductsEmptyTitle: 'No product sales in this period',
topProductsEmptyDescription: 'Try a wider date range.',
topProducts: 'Top products',
print: 'Print',
tabsLabel: 'Analytics sections',
tab: {

View File

@@ -1530,6 +1530,8 @@ export const hy: Translations = {
addVariant: 'Ավելացնել տարբերակ',
variantName: 'Տարբերակի անուն',
variantsHint: 'Յուրաքանչյուր տարբերակ այս ապրանքի առանձին գնվող տարբերակ է (օր․՝ չափս կամ գույն)՝ իր գնով և մնացորդով։',
variants: 'Տարբերակներ',
archived: 'Արխիվում',
seoExplain: 'Սա այն է, ինչ երևում է որոնման արդյունքներում․ հստակ վերնագիրն ու նկարագրությունը օգնում են գտնել այս ապրանքը։',
searchTitle: 'Որոնման վերնագիր',
searchTitleHint: 'Վերնագիրը, որ երևում է որոնման արդյունքներում։ Պահեք կարճ։',
@@ -1585,10 +1587,98 @@ export const hy: Translations = {
emptyTitle: 'Օգտատերեր չեն գտնվել',
emptyDescription: 'Հրավիրեք գործընկերոջ՝ սկսելու համար։',
invitationsEmptyTitle: 'Սպասող հրավերներ չկան',
title: 'Թիմ',
name: 'Անուն',
email: 'Էլ. փոստ',
scope: 'Աշխատանքային տարածք',
role: 'Դեր',
roles: 'Դերեր',
lastLogin: 'Վերջին մուտք',
sessions: 'Ակտիվ նստաշրջաններ',
currentSession: 'Ընթացիկ նստաշրջան',
invite: 'Հրավիրել անդամ',
sendInvite: 'Ուղարկել հրավեր',
revoke: 'Չեղարկել',
passwordlessHint: 'Անդամները մուտք են գործում Telegram-ով — գաղտնաբառեր պետք չեն։',
confirmSuspend: 'Արգելափակե՞լ այս անդամին։ Մուտքը կփակվի անմիջապես։',
scopeValue: {
marketplace: 'Խանութ',
office: 'Բեք-օֆիս',
},
statusValue: {
active: 'Ակտիվ',
invited: 'Հրավիրված',
suspended: 'Արգելափակված',
},
invitationStatus: {
pending: 'Սպասում է',
accepted: 'Ընդունված',
expired: 'Ժամկետանց',
revoked: 'Չեղարկված',
},
},
adminTransactions: {
search: 'Գործարքների որոնում',
type: 'Տեսակ',
method: 'Վճարման եղանակ',
fraud: 'Խարդախության ստուգում',
flagged: 'Նշված',
retry: 'Կրկնել',
audit: 'Պատմություն',
emptyTitle: 'Գործարքներ չեն գտնվել',
emptyDescription: 'Փորձեք այլ ֆիլտր կամ որոնման բառ։',
status: {
all: 'Բոլոր կարգավիճակները',
pending: 'Մշակվում է',
success: 'Հաջողված',
failed: 'Ձախողված',
retried: 'Կրկնված',
},
typeValue: {
all: 'Բոլոր տեսակները',
payment: 'Վճարում',
refund: 'Վերադարձ',
qr_payment: 'QR վճարում',
},
},
adminMonitoring: {
eventsEmptyTitle: 'Իրադարձություններ չեն գտնվել',
eventsEmptyDescription: 'Փորձեք այլ կատեգորիայի ֆիլտր կամ որոնման բառ։',
health: 'Վիճակի ստուգումներ',
queues: 'Ֆոնային հերթեր',
depth: 'Սպասման մեջ',
webhooks: 'Վեբհուքերի առաքում',
endpoint: 'Ստացող',
event: 'Իրադարձություն',
events: 'Ակտիվության մատյան',
category: 'Կատեգորիա',
level: 'Կարևորություն',
message: 'Նկարագրություն',
categoryValue: {
all: 'Բոլոր կատեգորիաները',
audit: 'Ադմինի գործողություններ',
security: 'Անվտանգություն',
login: 'Մուտք',
failed_login: 'Ձախողված մուտք',
api: 'API',
error: 'Սխալ',
warning: 'Զգուշացում',
},
queueStatus: {
healthy: 'Աշխատում է կայուն',
degraded: 'Դանդաղել է',
down: 'Կանգնած է',
},
webhookStatus: {
delivered: 'Առաքված',
failed: 'Ձախողված',
pending: 'Սպասում է',
},
levelValue: {
info: 'Տեղեկություն',
warning: 'Զգուշացում',
error: 'Սխալ',
},
systemState: 'Համակարգի վիճակ',
backendConnectivity: 'Բեքենդ',
connected: 'Կապակցված է',
@@ -1603,6 +1693,7 @@ export const hy: Translations = {
adminAnalytics: {
topProductsEmptyTitle: 'Այս ժամանակահատվածում ապրանքների վաճառք չկա',
topProductsEmptyDescription: 'Փորձեք ընտրել ավելի լայն ամսաթվերի միջակայք։',
topProducts: 'Թոփ ապրանքներ',
print: 'Տպել',
tabsLabel: 'Վերլուծության բաժիններ',
tab: {

View File

@@ -1530,6 +1530,8 @@ export const ru: Translations = {
addVariant: 'Добавить вариант',
variantName: 'Название варианта',
variantsHint: 'Каждый вариант — это отдельный покупаемый вариант товара (например, размер или цвет) со своей ценой и остатком.',
variants: 'Варианты',
archived: 'В архиве',
seoExplain: 'Это то, что видно в результатах поиска — понятные заголовок и описание помогают найти товар.',
searchTitle: 'Заголовок для поиска',
searchTitleHint: 'Заголовок, показываемый в результатах поиска. Делайте его коротким.',
@@ -1585,10 +1587,98 @@ export const ru: Translations = {
emptyTitle: 'Пользователи не найдены',
emptyDescription: 'Пригласите коллегу, чтобы начать.',
invitationsEmptyTitle: 'Нет ожидающих приглашений',
title: 'Команда',
name: 'Имя',
email: 'Email',
scope: 'Рабочая область',
role: 'Роль',
roles: 'Роли',
lastLogin: 'Последний вход',
sessions: 'Активные сессии',
currentSession: 'Текущая сессия',
invite: 'Пригласить участника',
sendInvite: 'Отправить приглашение',
revoke: 'Отозвать',
passwordlessHint: 'Участники входят через Telegram — пароли не нужны.',
confirmSuspend: 'Заблокировать этого участника? Доступ будет закрыт немедленно.',
scopeValue: {
marketplace: 'Витрина',
office: 'Бэк-офис',
},
statusValue: {
active: 'Активен',
invited: 'Приглашён',
suspended: 'Заблокирован',
},
invitationStatus: {
pending: 'Ожидает',
accepted: 'Принято',
expired: 'Истекло',
revoked: 'Отозвано',
},
},
adminTransactions: {
search: 'Поиск транзакций',
type: 'Тип',
method: 'Способ оплаты',
fraud: 'Проверка на мошенничество',
flagged: 'Помечено',
retry: 'Повторить',
audit: 'История',
emptyTitle: 'Транзакции не найдены',
emptyDescription: 'Попробуйте изменить фильтр или поисковый запрос.',
status: {
all: 'Все статусы',
pending: 'В обработке',
success: 'Успешно',
failed: 'Ошибка',
retried: 'Повторено',
},
typeValue: {
all: 'Все типы',
payment: 'Оплата',
refund: 'Возврат',
qr_payment: 'Оплата по QR',
},
},
adminMonitoring: {
eventsEmptyTitle: 'События не найдены',
eventsEmptyDescription: 'Попробуйте изменить фильтр категории или поисковый запрос.',
health: 'Проверки состояния',
queues: 'Фоновые очереди',
depth: 'В ожидании',
webhooks: 'Доставка вебхуков',
endpoint: 'Получатель',
event: 'Событие',
events: 'Журнал активности',
category: 'Категория',
level: 'Важность',
message: 'Описание',
categoryValue: {
all: 'Все категории',
audit: 'Действия администраторов',
security: 'Безопасность',
login: 'Вход',
failed_login: 'Неудачный вход',
api: 'API',
error: 'Ошибка',
warning: 'Предупреждение',
},
queueStatus: {
healthy: 'Работает штатно',
degraded: 'Замедлена',
down: 'Остановлена',
},
webhookStatus: {
delivered: 'Доставлено',
failed: 'Ошибка',
pending: 'Ожидает',
},
levelValue: {
info: 'Инфо',
warning: 'Предупреждение',
error: 'Ошибка',
},
systemState: 'Состояние системы',
backendConnectivity: 'Бэкенд',
connected: 'Подключено',
@@ -1603,6 +1693,7 @@ export const ru: Translations = {
adminAnalytics: {
topProductsEmptyTitle: 'Нет продаж товаров за этот период',
topProductsEmptyDescription: 'Попробуйте выбрать более широкий диапазон дат.',
topProducts: 'Топ товаров',
print: 'Печать',
tabsLabel: 'Разделы аналитики',
tab: {

View File

@@ -1542,6 +1542,8 @@ export interface Translations {
addVariant: string;
variantName: string;
variantsHint: string;
variants: string;
archived: string;
seoExplain: string;
searchTitle: string;
searchTitleHint: string;
@@ -1597,10 +1599,98 @@ export interface Translations {
emptyTitle: string;
emptyDescription: string;
invitationsEmptyTitle: string;
title: string;
name: string;
email: string;
scope: string;
role: string;
roles: string;
lastLogin: string;
sessions: string;
currentSession: string;
invite: string;
sendInvite: string;
revoke: string;
passwordlessHint: string;
confirmSuspend: string;
scopeValue: {
marketplace: string;
office: string;
};
statusValue: {
active: string;
invited: string;
suspended: string;
};
invitationStatus: {
pending: string;
accepted: string;
expired: string;
revoked: string;
};
};
adminTransactions: {
search: string;
type: string;
method: string;
fraud: string;
flagged: string;
retry: string;
audit: string;
emptyTitle: string;
emptyDescription: string;
status: {
all: string;
pending: string;
success: string;
failed: string;
retried: string;
};
typeValue: {
all: string;
payment: string;
refund: string;
qr_payment: string;
};
};
adminMonitoring: {
eventsEmptyTitle: string;
eventsEmptyDescription: string;
health: string;
queues: string;
depth: string;
webhooks: string;
endpoint: string;
event: string;
events: string;
category: string;
level: string;
message: string;
categoryValue: {
all: string;
audit: string;
security: string;
login: string;
failed_login: string;
api: string;
error: string;
warning: string;
};
queueStatus: {
healthy: string;
degraded: string;
down: string;
};
webhookStatus: {
delivered: string;
failed: string;
pending: string;
};
levelValue: {
info: string;
warning: string;
error: string;
};
systemState: string;
backendConnectivity: string;
connected: string;
@@ -1615,6 +1705,7 @@ export interface Translations {
adminAnalytics: {
topProductsEmptyTitle: string;
topProductsEmptyDescription: string;
topProducts: string;
print: string;
tabsLabel: string;
tab: {