feat(translation,fulfillment,customer,product,region,tax,core-flows,medusa,types): Implement dynamic translation settings management (#14536)

* Add is_active field to translation_settings model

* Types

* Workflows

* Api layer

* Tests

* Add changeset

* Add comment

* Hook to create or deactivate translatable entities on startup

* Cleanup old code

* Configure translatable option for core entities

* Validation step and snake case correction

* Cleanup

* Tests

* Comment in PR

* Update changeset

* Mock DmlEntity.getTranslatableEntities

* Move validation to module service layer

* Remove validation from remaining workflow

* Return object directly

* Type improvements

* Remove .only from tests

* Apply snakeCase

* Fix tests

* Fix tests

* Remove unnecessary map and use set instead

* Fix tests

* Comments

* Include translatable product properties

* Avoid race condition in translations tests

* Update test
This commit is contained in:
Nicolas Gorga
2026-01-14 07:09:49 -03:00
committed by GitHub
parent 42235825ee
commit d60ea7268a
50 changed files with 1397 additions and 199 deletions

View File

@@ -0,0 +1,34 @@
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { CreateTranslationSettingsDTO } from "@medusajs/types"
export const createTranslationSettingsStepId = "create-translation-settings"
export type CreateTranslationSettingsStepInput =
| CreateTranslationSettingsDTO
| CreateTranslationSettingsDTO[]
export const createTranslationSettingsStep = createStep(
createTranslationSettingsStepId,
async (data: CreateTranslationSettingsStepInput, { container }) => {
const service = container.resolve(Modules.TRANSLATION)
const normalizedInput = Array.isArray(data) ? data : [data]
const created = await service.createTranslationSettings(normalizedInput)
return new StepResponse(
created,
created.map((translationSettings) => translationSettings.id)
)
},
async (createdIds, { container }) => {
if (!createdIds?.length) {
return
}
const service = container.resolve(Modules.TRANSLATION)
await service.deleteTranslationSettings(createdIds)
}
)

View File

@@ -0,0 +1,28 @@
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
export const deleteTranslationSettingsStepId = "delete-translation-settings"
export const deleteTranslationSettingsStep = createStep(
deleteTranslationSettingsStepId,
async (data: string[], { container }) => {
const service = container.resolve(Modules.TRANSLATION)
const previous = await service.listTranslationSettings({
id: data,
})
await service.deleteTranslationSettings(data)
return new StepResponse(void 0, previous)
},
async (previous, { container }) => {
if (!previous?.length) {
return
}
const service = container.resolve(Modules.TRANSLATION)
await service.createTranslationSettings(previous)
}
)

View File

@@ -2,3 +2,6 @@ export * from "./create-translations"
export * from "./delete-translations"
export * from "./update-translations"
export * from "./validate-translations"
export * from "./create-translation-settings"
export * from "./update-translation-settings"
export * from "./delete-translation-settings"

View File

@@ -0,0 +1,35 @@
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { UpdateTranslationSettingsDTO } from "@medusajs/types"
export const updateTranslationSettingsStepId = "update-translation-settings"
export type UpdateTranslationSettingsStepInput =
| UpdateTranslationSettingsDTO
| UpdateTranslationSettingsDTO[]
export const updateTranslationSettingsStep = createStep(
updateTranslationSettingsStepId,
async (data: UpdateTranslationSettingsStepInput, { container }) => {
const service = container.resolve(Modules.TRANSLATION)
const normalizedInput = Array.isArray(data) ? data : [data]
const previous = await service.listTranslationSettings({
id: normalizedInput.map((d) => d.id),
})
const updated = await service.updateTranslationSettings(normalizedInput)
return new StepResponse(updated, previous)
},
async (previous, { container }) => {
if (!previous?.length) {
return
}
const service = container.resolve(Modules.TRANSLATION)
await service.updateTranslationSettings(previous)
}
)

View File

@@ -0,0 +1,35 @@
import {
createWorkflow,
parallelize,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import {
UpdateTranslationSettingsDTO,
CreateTranslationSettingsDTO,
} from "@medusajs/types"
import {
createTranslationSettingsStep,
deleteTranslationSettingsStep,
updateTranslationSettingsStep,
} from "../steps"
export const batchTranslationSettingsWorkflowId = "batch-translation-settings"
export interface BatchTranslationSettingsWorkflowInput {
create: CreateTranslationSettingsDTO[]
update: UpdateTranslationSettingsDTO[]
delete: string[]
}
export const batchTranslationSettingsWorkflow = createWorkflow(
batchTranslationSettingsWorkflowId,
(input: BatchTranslationSettingsWorkflowInput) => {
const [created, updated, deleted] = parallelize(
createTranslationSettingsStep(input.create),
updateTranslationSettingsStep(input.update),
deleteTranslationSettingsStep(input.delete)
)
return new WorkflowResponse({ created, updated, deleted })
}
)

View File

@@ -7,7 +7,6 @@ import {
} from "@medusajs/framework/workflows-sdk"
import { emitEventStep } from "../../common/steps/emit-event"
import { createTranslationsStep } from "../steps"
import { validateTranslationsStep } from "../steps"
import { TranslationWorkflowEvents } from "@medusajs/framework/utils"
/**
@@ -27,7 +26,7 @@ export const createTranslationsWorkflowId = "create-translations"
*
* You can use this workflow within your own customizations or custom workflows, allowing you
* to create translations in your custom flows.
*
*
* @since 2.12.3
* @featureFlag translation
*
@@ -55,7 +54,6 @@ export const createTranslationsWorkflow = createWorkflow(
(
input: WorkflowData<CreateTranslationsWorkflowInput>
): WorkflowResponse<TranslationDTO[]> => {
validateTranslationsStep(input.translations)
const translations = createTranslationsStep(input.translations)
const translationIdEvents = transform(

View File

@@ -2,3 +2,4 @@ export * from "./create-translations"
export * from "./delete-translations"
export * from "./update-translations"
export * from "./batch-translations"
export * from "./batch-translation-settings"

View File

@@ -7,7 +7,6 @@ import {
} from "@medusajs/framework/workflows-sdk"
import { emitEventStep } from "../../common/steps/emit-event"
import { updateTranslationsStep, UpdateTranslationsStepInput } from "../steps"
import { validateTranslationsStep } from "../steps"
import { TranslationWorkflowEvents } from "@medusajs/framework/utils"
/**
@@ -22,13 +21,13 @@ export const updateTranslationsWorkflowId = "update-translations"
*
* You can use this workflow within your own customizations or custom workflows, allowing you
* to update translations in your custom flows.
*
*
* @since 2.12.3
* @featureFlag translation
*
* @example
* To update translations by their IDs:
*
*
* ```ts
* const { result } = await updateTranslationsWorkflow(container)
* .run({
@@ -61,11 +60,6 @@ export const updateTranslationsWorkflow = createWorkflow(
(
input: WorkflowData<UpdateTranslationsWorkflowInput>
): WorkflowResponse<TranslationDTO[]> => {
const validateInput = transform(input, (input) => {
return "translations" in input ? input.translations : [input.update]
})
validateTranslationsStep(validateInput)
const translations = updateTranslationsStep(input)
const translationIdEvents = transform(