1 Commits

Author SHA1 Message Date
sdarbinyan
905c8be8c5 translations 2026-07-04 23:34:00 +04:00
10 changed files with 39 additions and 13 deletions

View File

@@ -31,8 +31,14 @@ export interface Subcategory {
itemCount?: number; itemCount?: number;
hasItems?: boolean; hasItems?: boolean;
subcategories?: Subcategory[]; subcategories?: Subcategory[];
names?: ItemName[];
translations?: Record<string, SubcategoryTranslation>;
} }
interface CategoryTranslation { interface CategoryTranslation {
name?: string; name?: string;
} }
interface SubcategoryTranslation {
name?: string;
}

View File

@@ -401,7 +401,7 @@ export class CartComponent implements OnDestroy {
telegramUserId: telegramUserId, telegramUserId: telegramUserId,
items: this.paidItems.map((item: CartItem) => ({ items: this.paidItems.map((item: CartItem) => ({
itemID: item.itemID, itemID: item.itemID,
name: item.name, name: this.itemName(item),
price: item.discount > 0 price: item.discount > 0
? item.price * (1 - item.discount / 100) ? item.price * (1 - item.discount / 100)
: item.price, : item.price,
@@ -470,7 +470,7 @@ export class CartComponent implements OnDestroy {
telegramUserId: this.getTelegramUserId(), telegramUserId: this.getTelegramUserId(),
items: this.paidItems.map((item: CartItem) => ({ items: this.paidItems.map((item: CartItem) => ({
itemID: item.itemID, itemID: item.itemID,
name: item.name, name: this.itemName(item),
price: item.discount > 0 price: item.discount > 0
? item.price * (1 - item.discount / 100) ? item.price * (1 - item.discount / 100)
: item.price, : item.price,

View File

@@ -52,7 +52,7 @@
</div> </div>
</a> </a>
<button class="add-to-cart-btn" (click)="addToCart(item.itemID, $event)" [attr.aria-label]="('category.addToCart' | translate) + ': ' + item.name"> <button class="add-to-cart-btn" (click)="addToCart(item.itemID, $event)" [attr.aria-label]="('category.addToCart' | translate) + ': ' + itemName(item)">
{{ 'category.addToCart' | translate }} {{ 'category.addToCart' | translate }}
</button> </button>
</div> </div>

View File

@@ -25,13 +25,13 @@
<a [routerLink]="['/category', sub.id] | langRoute" class="category-card"> <a [routerLink]="['/category', sub.id] | langRoute" class="category-card">
<div class="category-image"> <div class="category-image">
@if (sub.img) { @if (sub.img) {
<img [src]="sub.img" [alt]="sub.name" loading="lazy" decoding="async" /> <img [src]="sub.img" [alt]="categoryName(sub)" loading="lazy" decoding="async" />
} @else { } @else {
<div class="category-fallback">{{ sub.name.charAt(0) }}</div> <div class="category-fallback">{{ categoryName(sub).charAt(0) }}</div>
} }
</div> </div>
<div class="category-info"> <div class="category-info">
<h3 class="category-name">{{ sub.name }}</h3> <h3 class="category-name">{{ categoryName(sub) }}</h3>
@if (sub.itemCount) { @if (sub.itemCount) {
<span class="category-count">{{ sub.itemCount }}</span> <span class="category-count">{{ sub.itemCount }}</span>
} }

View File

@@ -150,5 +150,5 @@ export class SubcategoriesComponent implements OnInit, OnDestroy {
itemName(item: Item): string { return getTranslatedField(item, 'name', this.langService.currentLanguage()); } itemName(item: Item): string { return getTranslatedField(item, 'name', this.langService.currentLanguage()); }
categoryName(cat: Category): string { return getTranslatedCategoryName(cat, this.langService.currentLanguage()); } categoryName(cat: Category | Subcategory): string { return getTranslatedCategoryName(cat, this.langService.currentLanguage()); }
} }

View File

@@ -23,7 +23,7 @@
@if (item()!.photos![selectedPhotoIndex()]?.video) { @if (item()!.photos![selectedPhotoIndex()]?.video) {
<video [src]="item()!.photos![selectedPhotoIndex()].url" controls></video> <video [src]="item()!.photos![selectedPhotoIndex()].url" controls></video>
} @else { } @else {
<img [src]="item()!.photos![selectedPhotoIndex()].url" [alt]="item()!.name" /> <img [src]="item()!.photos![selectedPhotoIndex()].url" [alt]="getItemName()" />
} }
</div> </div>
@@ -337,7 +337,7 @@
@if (item()!.photos![selectedPhotoIndex()]?.video) { @if (item()!.photos![selectedPhotoIndex()]?.video) {
<video [src]="item()!.photos![selectedPhotoIndex()].url" controls></video> <video [src]="item()!.photos![selectedPhotoIndex()].url" controls></video>
} @else { } @else {
<img [src]="item()!.photos![selectedPhotoIndex()].url" [alt]="item()!.name" fetchpriority="high" decoding="async" /> <img [src]="item()!.photos![selectedPhotoIndex()].url" [alt]="getItemName()" fetchpriority="high" decoding="async" />
} }
} @else { } @else {
<div class="dx-no-image"> <div class="dx-no-image">

View File

@@ -218,7 +218,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
getSimpleDescription(): string { getSimpleDescription(): string {
const currentItem = this.item(); const currentItem = this.item();
if (!currentItem) return ''; if (!currentItem) return '';
return currentItem.simpleDescription || currentItem.description || ''; return getTranslatedField(currentItem, 'simpleDescription', this.languageService.currentLanguage());
} }
hasDescriptionFields(): boolean { hasDescriptionFields(): boolean {

View File

@@ -105,7 +105,7 @@
</div> </div>
</a> </a>
<button class="add-to-cart-btn" (click)="addToCart(item.itemID, $event)" [attr.aria-label]="('search.addToCart' | translate) + ': ' + item.name"> <button class="add-to-cart-btn" (click)="addToCart(item.itemID, $event)" [attr.aria-label]="('search.addToCart' | translate) + ': ' + itemName(item)">
{{ 'search.addToCart' | translate }} {{ 'search.addToCart' | translate }}
</button> </button>
</div> </div>

View File

@@ -147,6 +147,23 @@ export class ApiService {
: [], : [],
}; };
if (raw.names && Array.isArray(raw.names)) {
subcategory.names = raw.names;
subcategory.translations = subcategory.translations || {};
for (const entry of raw.names) {
const lang = this.normalizeLang(entry.language);
const val = entry.value || entry.valuue || '';
if (val) {
if (!subcategory.translations[lang]) subcategory.translations[lang] = {};
subcategory.translations[lang].name = val;
}
}
if (!subcategory.name && raw.names.length > 0) {
const ruName = raw.names.find((n: any) => n.language === 'RU' || n.language === 'ru');
subcategory.name = ruName?.value || ruName?.valuue || raw.names[0].value || raw.names[0].valuue || '';
}
}
return subcategory; return subcategory;
} }

View File

@@ -1,5 +1,5 @@
import { Item } from '../models'; import { Item } from '../models';
import { Category } from '../models/category.model'; import { Category, Subcategory } from '../models/category.model';
export function getDiscountedPrice(item: Item): number { export function getDiscountedPrice(item: Item): number {
return item.price * (1 - (item.discount || 0) / 100); return item.price * (1 - (item.discount || 0) / 100);
@@ -68,6 +68,9 @@ export function getTranslatedField(
const val = entry?.value || (entry as any)?.valuue || ''; const val = entry?.value || (entry as any)?.valuue || '';
if (val) return val; if (val) return val;
} }
if (field === 'simpleDescription' && item.translations?.[lang]?.simpleDescription) {
return item.translations[lang].simpleDescription!;
}
// 3. Fallback to base field // 3. Fallback to base field
if (field === 'name') return item.name; if (field === 'name') return item.name;
if (field === 'simpleDescription') return item.simpleDescription || item.description || ''; if (field === 'simpleDescription') return item.simpleDescription || item.description || '';
@@ -77,7 +80,7 @@ export function getTranslatedField(
/** /**
* Get translated category name for the current language. * Get translated category name for the current language.
*/ */
export function getTranslatedCategoryName(cat: Category, lang: string): string { export function getTranslatedCategoryName(cat: Category | Subcategory, lang: string): string {
const translation = cat.translations?.[lang]; const translation = cat.translations?.[lang];
if (translation?.name) return translation.name; if (translation?.name) return translation.name;