Translate Custom Data Models
In this chapter, you'll learn how to support translations for your custom data models using the Translation Module.
Summary#
The Translation Module allows you to extend translation capabilities to custom data models in your Medusa application. Then, you can manage translations from the Medusa Admin, and serve translated resources in your configured locales.
By following this guide, you'll learn how to:
- Configure the Translation Module to support translations for your custom data models.
- Manage translations for your custom data models from the Medusa Admin.
- Serve translated resources in your configured locales.
Prerequisites: Custom Data Model#
This guide assumes you already have a custom module with a data model. The guide will use a Blog Module with the following Post data model as an example:
The module must also be registered in medusa-config.ts. For example:
Step 1: Configure Translatable Entities#
The first step is to configure the Translation Module with the custom entities you want to support translations for.
Before proceeding, run the build command to ensure the generated types are up-to-date:
This will allow you to benefit from auto-completion when configuring the Translation Module.
Next, in medusa-config.ts, add the options.entities property to the Translation Module configuration:
The options.entities option is an array of objects indicating the custom data models to support translations for. Each object has the following properties:
type: The name of the table where the custom data model is stored. This is the same value passed as the first parameter tomodel.define.fields: An array of fields in the custom data model to support translations for.
Step 2: Manage Translations from Medusa Admin#
After configuring the Translation Module, you can manage translations for your custom data models from the Medusa Admin.
Run the following command to start the Medusa application:
Then, open the Medusa Admin and go to Settings -> Translations. You should see your custom data model in the list of translatable resources.

Click the Edit button for your custom data model to manage translations for its resources. You can manage translations for the configured locales and fields.
Learn more in the Translations User Guide.
Step 3: Serve Translated Resources#
Finally, you can serve translated resources for your custom data models in your configured locales. This section focuses on returning records with translated fields from API routes.
Pass Locale in API Requests#
Medusa supports passing the desired locale in API requests to /store routes using either:
- The
localequery parameter. - The
x-medusa-localeheader.
For example, assuming you have a /store/posts API route, you can pass the locale in the request as follows:
If your API route isn't under the /store prefix, you must apply the applyLocale middleware. For example, add the middleware to the src/api/middlewares.ts file:
This allows you to pass the locale in the query parameter or request header for the /posts API route.
Handle Translations in API Routes#
In your custom API routes, you can retrieve the request's locale from the locale property of the MedusaRequest object. Pass that property to Query to retrieve your data models with translated fields.
For example, to retrieve blog posts with translated titles in the /store/posts API route:
1import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"2 3export async function GET(4 req: MedusaRequest,5 res: MedusaResponse6) {7 const query = req.scope.resolve("query")8 9 const { data: posts } = await query.graph(10 {11 entity: "post",12 fields: ["id", "title"],13 },14 {15 locale: req.locale,16 }17 )18 19 res.json({ posts })20}
In this example, the locale option is set to req.locale. Medusa will set the title field of each post to its translated value if a translation is available for the requested locale. Otherwise, it returns the original value stored in the data model.
Step 4: Test the Implementation#
To test the implementation, start the Medusa application if you haven't already:
Then, send a request to your custom API route with the desired locale. For example:
This should return the list of blog posts with their French translations for the title field if available:
Pass Locale to useQueryGraphStep#
If your API route executes a workflow and returns its result, you can retrieve data models with translated fields in the workflow by passing the locale to useQueryGraphStep.
For example:
1import { createWorkflow, WorkflowResponse } from "@medusajs/framework/workflows-sdk"2import { useQueryGraphStep } from "@medusajs/medusa/core-flows"3 4type WorkflowInput = {5 locale: string;6}7 8export const handlePostsWorkflow = createWorkflow(9 "handle-posts",10 (input: WorkflowInput) => {11 // do something...12 13 const { data: posts } = useQueryGraphStep({14 entity: "post",15 fields: ["id", "title"],16 options: {17 locale: input.locale,18 },19 })20 21 return new WorkflowResponse({22 posts,23 })24 }25)
In this example, the workflow accepts a locale input parameter. You then retrieve the posts with translated titles by passing the locale input to useQueryGraphStep.
The returned posts will have their title field set to the translated value if a translation is available for the requested locale.
You can execute the workflow in your custom API routes and pass the request locale as an input parameter:
1import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"2import { handlePostsWorkflow } from "../../workflows/handle-posts"3 4export async function GET(5 req: MedusaRequest,6 res: MedusaResponse7) {8 const { result } = await handlePostsWorkflow(req.scope)9 .run({10 input: {11 locale: req.locale,12 },13 })14 15 res.json(result)16}
The returned posts in the API response will have their title field set to the translated value if a translation is available for the requested locale.
Manage Translations with the Translation Module Service#
For more complex cases, you can manage translations for your custom data models programmatically using the Translation Module's service. You can create, update, delete, and retrieve translations of any resource using the service's methods.
Refer to the Translation Module service reference for a full list of available methods and how to use them.