feat(pcat): translate part descriptions + vehicle attributes #36

Merged
root merged 2 commits from dev into main 2026-05-19 11:32:54 +03:00
4 changed files with 41 additions and 14 deletions

View File

@@ -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<typeof parts.$inferInsert> = 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

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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,