fix(catalog): translate product-card stock badge and action-button labels

P0-1: stock badge rendered the raw item.remainings value ('High',
etc) untranslated on every product card sitewide. Now maps to
catalog.stockHigh/Medium/Low/Out via the translate pipe; the 'out'
class check is now case-insensitive to match.

P0-2: favorite/share/quick-view action-button aria-labels rendered
literal 'catalog.favorite'/'catalog.share'/'catalog.quickView' keys
because they never existed in translations.ts/en.ts/ru.ts/hy.ts
(only catalog.compare existed, and it was likewise unused). Added
all 4 keys to the Translations interface and all 3 locales.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-07-19 22:04:13 +04:00
parent 8d995105f4
commit 1a5d43523a
6 changed files with 44 additions and 1 deletions

View File

@@ -6,7 +6,7 @@
<div class="discount-badge" [attr.aria-label]="'Discount ' + item.discount + '%'">-{{ item.discount }}%</div>
}
@if (showStock && item.remainings) {
<span class="stock-badge" [class.out]="item.remainings === 'out'">{{ item.remainings }}</span>
<span class="stock-badge" [class.out]="item.remainings.toLowerCase() === 'out'">{{ stockLabelKey(item.remainings) | translate }}</span>
}
@if (showFavoriteControl() || showCompareControl() || showShareAction || showQuickViewPlaceholder) {

View File

@@ -6,6 +6,13 @@ import { LangRoutePipe } from '../../pipes/lang-route.pipe';
import { TranslatePipe } from '../../i18n/translate.pipe';
import { getBadgeClass, getDiscountedPrice, getMainImage } from '../../utils/item.utils';
const STOCK_LABEL_KEYS: Record<string, string> = {
high: 'catalog.stockHigh',
medium: 'catalog.stockMedium',
low: 'catalog.stockLow',
out: 'catalog.stockOut'
};
export type ProductCardAppearance = 'standard' | 'compact';
@Component({
@@ -83,6 +90,10 @@ export class ProductCardComponent {
this.shareRequested.emit(this.item.itemID);
}
stockLabelKey(remainings: string): string {
return STOCK_LABEL_KEYS[remainings.toLowerCase()] ?? STOCK_LABEL_KEYS['high'];
}
showFavoriteControl(): boolean {
return this.showFavoriteAction || this.showFavoritePlaceholder;
}

View File

@@ -261,6 +261,14 @@ export const en: Translations = {
filterColor: 'Color',
filterSize: 'Size',
filterAttributes: 'Attributes',
favorite: 'Add to favorites',
compare: 'Compare',
share: 'Share',
quickView: 'Quick view',
stockHigh: 'In stock',
stockMedium: 'Limited stock',
stockLow: 'Almost gone',
stockOut: 'Out of stock',
},
productDetails: {
loading: 'Loading product...',

View File

@@ -261,6 +261,14 @@ export const hy: Translations = {
filterColor: 'Գույն',
filterSize: 'Չափ',
filterAttributes: 'Հատկանիշներ',
favorite: 'Ավելացնել ընտրյալներում',
compare: 'Համեմատել',
share: 'Կիսվել',
quickView: 'Արագ դիտում',
stockHigh: 'Առկա է',
stockMedium: 'Սահմանափակ քանակ',
stockLow: 'Գրեթե սպառված է',
stockOut: 'Առկա չէ',
},
productDetails: {
loading: 'Ապրանքի բեռնում...',

View File

@@ -261,6 +261,14 @@ export const ru: Translations = {
filterColor: 'Цвет',
filterSize: 'Размер',
filterAttributes: 'Атрибуты',
favorite: 'В избранное',
compare: 'Сравнить',
share: 'Поделиться',
quickView: 'Быстрый просмотр',
stockHigh: 'В наличии',
stockMedium: 'Ограниченно',
stockLow: 'Почти распродано',
stockOut: 'Нет в наличии',
},
productDetails: {
loading: 'Загрузка товара...',

View File

@@ -259,6 +259,14 @@ export interface Translations {
filterColor: string;
filterSize: string;
filterAttributes: string;
favorite: string;
compare: string;
share: string;
quickView: string;
stockHigh: string;
stockMedium: string;
stockLow: string;
stockOut: string;
};
productDetails: {
loading: string;