Add catalog EN/AR translations with AI translate-all by locale.

Store product/category translations in entity_translations, expose CMS APIs, and gate the MultiLanguage Data module for businesses.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-09-04 09:51:11 +03:30
co-authored by Cursor
parent 42cf29bc4e
commit d14f91a606
13 changed files with 950 additions and 10 deletions
+65
View File
@@ -26,6 +26,9 @@ import {
SuggestCategoryTechnicalFormDto,
} from './dto/category-technical-form.dto';
import { ReplaceCategoryVariationsDto } from './dto/category-variation.dto';
import { TranslationEntityType } from '@prisma/client';
import { UpsertTranslationDto, TranslateAllDto } from '../translations/dto/translation.dto';
import { TranslationsService } from '../translations/translations.service';
import { GenerateCategoriesDto } from './dto/category-ai.dto';
@Controller('businesses/:businessId/categories')
@@ -37,6 +40,7 @@ export class CategoriesController {
private readonly technicalFormService: CategoryTechnicalFormService,
private readonly technicalFormAiService: CategoryTechnicalFormAiService,
private readonly categoryAiService: CategoryAiService,
private readonly translations: TranslationsService,
) {}
@Get('color-presets')
@@ -65,6 +69,16 @@ export class CategoriesController {
return this.categoryAiService.generateProductCategories(businessId, dto, user);
}
@Post('translations/ai-all')
@RequireBusinessPermission('categories.update')
translateAllWithAi(
@Param('businessId') businessId: string,
@Body() dto: TranslateAllDto,
@CurrentUser() user: AuthUser,
) {
return this.translations.translateAllCategories(businessId, user, dto.locale);
}
@Post()
@RequireBusinessPermission('categories.create')
create(
@@ -86,6 +100,57 @@ export class CategoriesController {
return this.service.update(businessId, categoryId, dto, user);
}
@Get(':categoryId/translations')
@RequireBusinessPermission('categories.read')
listTranslations(
@Param('businessId') businessId: string,
@Param('categoryId') categoryId: string,
@CurrentUser() user: AuthUser,
) {
return this.translations.list(
businessId,
TranslationEntityType.category,
categoryId,
user,
);
}
@Post(':categoryId/translations/:locale/ai')
@RequireBusinessPermission('categories.update')
translateWithAi(
@Param('businessId') businessId: string,
@Param('categoryId') categoryId: string,
@Param('locale') locale: string,
@CurrentUser() user: AuthUser,
) {
return this.translations.translateWithAi(
businessId,
TranslationEntityType.category,
categoryId,
locale,
user,
);
}
@Put(':categoryId/translations/:locale')
@RequireBusinessPermission('categories.update')
saveTranslation(
@Param('businessId') businessId: string,
@Param('categoryId') categoryId: string,
@Param('locale') locale: string,
@Body() dto: UpsertTranslationDto,
@CurrentUser() user: AuthUser,
) {
return this.translations.save(
businessId,
TranslationEntityType.category,
categoryId,
locale,
dto,
user,
);
}
@Get(':categoryId/variations')
@RequireBusinessPermission('categories.read')
listVariations(