diff --git a/apps/api/src/categories/categories.service.ts b/apps/api/src/categories/categories.service.ts index b386fc5..ed06b60 100644 --- a/apps/api/src/categories/categories.service.ts +++ b/apps/api/src/categories/categories.service.ts @@ -705,9 +705,10 @@ export class CategoriesService { } } - const trMap = await this.translationsService.translateMany( - rawParts.map((p) => p.name).filter(Boolean), - ); + const trMap = await this.translationsService.translateMany([ + ...rawParts.map((p) => p.name).filter(Boolean), + ...rawParts.map((p) => p.notice).filter((n): n is string => !!n), + ]); const allParts: Array = rawParts.map((p) => ({ vehicleId: vehicle.id, @@ -715,7 +716,7 @@ export class CategoriesService { oemCode: p.number, name: trMap.get(p.name) ?? p.name ?? "Unknown", nameOriginal: p.name || null, - description: p.notice, + description: p.notice ? (trMap.get(p.notice) ?? p.notice) : null, quantity: null, position: p.positionNumber, hotspotIndex: p.positionNumber diff --git a/apps/api/src/integrations/emex/emex.mapper.ts b/apps/api/src/integrations/emex/emex.mapper.ts index edefaa3..b85890d 100644 --- a/apps/api/src/integrations/emex/emex.mapper.ts +++ b/apps/api/src/integrations/emex/emex.mapper.ts @@ -91,7 +91,11 @@ function translateToTurkish( ): string | null { if (!term) return null; const normalized = term.toLowerCase().trim(); - return dictionary[normalized] || null; + // Dictionary miss → return original term unchanged. Upstream values are + // often heterogeneous (engine codes, multi-word descriptors) that the + // single-word dictionary can't cover; losing them would be worse than + // leaving them untranslated. + return dictionary[normalized] ?? term; } export function translateBodyType(bodyType: string | null): string | null { diff --git a/apps/api/src/jobs/processors/translation.processor.ts b/apps/api/src/jobs/processors/translation.processor.ts index 5f28362..cc9f4fe 100644 --- a/apps/api/src/jobs/processors/translation.processor.ts +++ b/apps/api/src/jobs/processors/translation.processor.ts @@ -127,6 +127,15 @@ export async function processTranslation( AND name_original = ${orig} AND name = name_original `); + // PCAT also stores the part `notice` field as `description`. We don't + // track a `description_original`, so match on the raw English value + // still being present — once translated, the row won't re-match. + await db.execute(drizzleSql` + UPDATE parts + SET description = ${tr} + WHERE source = 'parts-catalogs' + AND description = ${orig} + `); } // Invalidate translation lookup cache so next read sees DB value. diff --git a/apps/api/src/vehicles/vehicles.service.ts b/apps/api/src/vehicles/vehicles.service.ts index 92c7b0e..c27c126 100644 --- a/apps/api/src/vehicles/vehicles.service.ts +++ b/apps/api/src/vehicles/vehicles.service.ts @@ -21,6 +21,11 @@ import { vehicles, } from "../database/schema/core"; import { CorgiService } from "../integrations/corgi/corgi.service"; +import { + translateBodyType, + translateEngineType, + translateTransmission, +} from "../integrations/emex/emex.mapper"; import { EmexService } from "../integrations/emex/emex.service"; import { EmexCandidate } from "../integrations/emex/emex.service"; import { PartsCatalogsService } from "../integrations/parts-catalogs/parts-catalogs.service"; @@ -581,9 +586,11 @@ export class VehiclesService { brandName, model: car.name || null, year: this.extractYearFromPcatCar(car) || null, - engine: this.extractParamFromPcatCar(car, "engine") || null, - transmission: this.extractParamFromPcatCar(car, "transmission") || null, - bodyType: this.extractParamFromPcatCar(car, "body") || null, + engine: translateEngineType(this.extractParamFromPcatCar(car, "engine") || null), + transmission: translateTransmission( + this.extractParamFromPcatCar(car, "transmission") || null, + ), + bodyType: translateBodyType(this.extractParamFromPcatCar(car, "body") || null), rawData: { source: "parts-catalogs", catalogId: car.catalogId, @@ -611,9 +618,13 @@ export class VehiclesService { brandName, model: emexSingleVehicle.model || null, year: emexSingleVehicle.year || null, - engine: emexSingleVehicle.engineCode || emexSingleVehicle.engineType || null, - transmission: emexSingleVehicle.transmission || null, - bodyType: emexSingleVehicle.bodyType || null, + // engineCode is alphanumeric (e.g. "N20B20") — leave raw; only the + // engineType fallback ("Petrol"/"Diesel") goes through the dict. + engine: + emexSingleVehicle.engineCode || + translateEngineType(emexSingleVehicle.engineType || null), + transmission: translateTransmission(emexSingleVehicle.transmission || null), + bodyType: translateBodyType(emexSingleVehicle.bodyType || null), rawData: emexSingleVehicle.raw || null, source: "emex", corgiKnown, @@ -738,9 +749,11 @@ export class VehiclesService { brandName, model: car.name || null, year: this.extractYearFromPcatCar(car) || null, - engine: this.extractParamFromPcatCar(car, "engine") || null, - transmission: this.extractParamFromPcatCar(car, "transmission") || null, - bodyType: this.extractParamFromPcatCar(car, "body") || null, + engine: translateEngineType(this.extractParamFromPcatCar(car, "engine") || null), + transmission: translateTransmission( + this.extractParamFromPcatCar(car, "transmission") || null, + ), + bodyType: translateBodyType(this.extractParamFromPcatCar(car, "body") || null), rawData: { source: "parts-catalogs", catalogId: car.catalogId,