diff --git a/src/app/features/admin/products/components/admin-product-form.component.html b/src/app/features/admin/products/components/admin-product-form.component.html index 921d0a2..7131bda 100644 --- a/src/app/features/admin/products/components/admin-product-form.component.html +++ b/src/app/features/admin/products/components/admin-product-form.component.html @@ -49,17 +49,24 @@ -

{{ 'adminProducts.translations' | translate }}

- @for (locale of locales; track locale) { -
- - - - - - -
- } +
+ + + {{ 'adminProducts.translations' | translate }} + {{ translatedLocalesCount() }}/{{ locales.length }} + +

{{ 'adminProducts.translationsHint' | translate }}

+ @for (locale of locales; track locale) { +
+ + + + + + +
+ } +
} @if (activeGroup() === 'media') { @@ -233,14 +240,21 @@

{{ 'adminProducts.htmlDescription' | translate }}

- @for (locale of locales; track locale) { - - } +
+ + + {{ 'adminProducts.translations' | translate }} + +

{{ 'adminProducts.translationsHint' | translate }}

+ @for (locale of locales; track locale) { + + } +

{{ 'adminProducts.customer' | translate }}

diff --git a/src/app/features/admin/products/components/admin-product-form.component.scss b/src/app/features/admin/products/components/admin-product-form.component.scss index bd5bf09..e590eab 100644 --- a/src/app/features/admin/products/components/admin-product-form.component.scss +++ b/src/app/features/admin/products/components/admin-product-form.component.scss @@ -75,3 +75,33 @@ input[type='checkbox'] { width: auto; } .field-with-action { display: flex; gap: 8px; align-items: center; app-input { flex: 1; } } .seo-generate-row { display: flex; align-items: center; gap: 10px; } .seo-generate-row__hint { color: var(--text-secondary, #6b7280); font-size: 0.8rem; } + +.translations-block { + border: 1px solid var(--border-color, #d3dad9); + border-radius: var(--radius-sm); + padding: 10px 12px; + + summary { + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; + font-weight: 600; + font-size: 0.9rem; + + &:focus-visible { outline: 2px solid var(--color-primary, #2f8f5b); outline-offset: 2px; } + } + + &[open] summary { margin-bottom: 8px; } +} +.translations-block__count { + margin-left: auto; + color: var(--text-secondary, #6b7280); + font-size: 0.8rem; + font-weight: 400; +} +.translations-block__hint { + margin: 0 0 10px; + color: var(--text-secondary, #6b7280); + font-size: 0.85rem; +} diff --git a/src/app/features/admin/products/components/admin-product-form.component.ts b/src/app/features/admin/products/components/admin-product-form.component.ts index 0c7b901..5dc6d21 100644 --- a/src/app/features/admin/products/components/admin-product-form.component.ts +++ b/src/app/features/admin/products/components/admin-product-form.component.ts @@ -121,6 +121,13 @@ export class AdminProductFormComponent { return value.toLowerCase().trim().replace(/[^a-z0-9а-яёա-ֆ]+/gi, '-').replace(/(^-|-$)/g, ''); } + translatedLocalesCount(): number { + return this.locales.filter(locale => { + const tr = this.product.translations[locale]; + return !!(tr && (tr.name || tr.shortDescription || tr.htmlDescription)); + }).length; + } + updateTranslation(locale: string, field: 'name' | 'shortDescription' | 'htmlDescription' | 'seoTitle' | 'seoDescription', value: string): void { this.productChange.emit({ translations: { diff --git a/src/app/i18n/en.ts b/src/app/i18n/en.ts index a6f7d62..166ebba 100644 --- a/src/app/i18n/en.ts +++ b/src/app/i18n/en.ts @@ -1545,6 +1545,7 @@ export const en: Translations = { generate: 'Generate', seoGenerate: 'Fill from product details', seoGenerateHint: 'Fills empty fields from the product name and short description. Your existing text is kept.', + translationsHint: 'The main fields above are shown in your default store language. Add translations here for other languages - if a translation is empty, customers see the default text instead.', 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.', diff --git a/src/app/i18n/hy.ts b/src/app/i18n/hy.ts index e3e2128..1a1bd9b 100644 --- a/src/app/i18n/hy.ts +++ b/src/app/i18n/hy.ts @@ -1540,6 +1540,7 @@ export const hy: Translations = { generate: 'Գեներացնել', seoGenerate: 'Լրացնել ապրանքի տվյալներից', seoGenerateHint: 'Լրացնում է դատարկ դաշտերը անունից և կարճ նկարագրությունից։ Ձեր տեքստը չի փոխվում։', + translationsHint: 'Վերևի հիմնական դաշտերը ցուցադրվում են խանութի հիմնական լեզվով։ Այստեղ ավելացրեք թարգմանություններ այլ լեզուների համար — եթե թարգմանությունը դատարկ է, գնորդները կտեսնեն հիմնական տեքստը։', seoExplain: 'Սա այն է, ինչ երևում է որոնման արդյունքներում․ հստակ վերնագիրն ու նկարագրությունը օգնում են գտնել այս ապրանքը։', searchTitle: 'Որոնման վերնագիր', searchTitleHint: 'Վերնագիրը, որ երևում է որոնման արդյունքներում։ Պահեք կարճ։', diff --git a/src/app/i18n/ru.ts b/src/app/i18n/ru.ts index c2a8540..fefdcd9 100644 --- a/src/app/i18n/ru.ts +++ b/src/app/i18n/ru.ts @@ -1540,6 +1540,7 @@ export const ru: Translations = { generate: 'Сгенерировать', seoGenerate: 'Заполнить из данных товара', seoGenerateHint: 'Заполняет пустые поля из названия и краткого описания. Ваш текст не перезаписывается.', + translationsHint: 'Основные поля выше отображаются на языке магазина по умолчанию. Здесь добавьте переводы для других языков — если перевод пуст, покупатели увидят текст по умолчанию.', seoExplain: 'Это то, что видно в результатах поиска — понятные заголовок и описание помогают найти товар.', searchTitle: 'Заголовок для поиска', searchTitleHint: 'Заголовок, показываемый в результатах поиска. Делайте его коротким.', diff --git a/src/app/i18n/translations.ts b/src/app/i18n/translations.ts index ea6c6f0..2a319ee 100644 --- a/src/app/i18n/translations.ts +++ b/src/app/i18n/translations.ts @@ -1552,6 +1552,7 @@ export interface Translations { generate: string; seoGenerate: string; seoGenerateHint: string; + translationsHint: string; seoExplain: string; searchTitle: string; searchTitleHint: string;