diff --git a/www/apps/book/app/learn/fundamentals/api-routes/localization/page.mdx b/www/apps/book/app/learn/fundamentals/api-routes/localization/page.mdx index dce92bb1a9..1097557cdd 100644 --- a/www/apps/book/app/learn/fundamentals/api-routes/localization/page.mdx +++ b/www/apps/book/app/learn/fundamentals/api-routes/localization/page.mdx @@ -176,12 +176,12 @@ The `req.locale` property contains the locale value from either the query parame ### Retrieve Localized Data with Query -To retrieve data models with translated fields, pass the `locale` option to [Query](/learn/fundamentals/module-links/query) when querying your data. +To retrieve data models with translated fields, pass the `locale` property in the second parameter object of [Query](/learn/fundamentals/module-links/query) when querying your data. For example, to retrieve products with translated names and descriptions: export const queryHighlights = [ - ["10", "locale", "Pass the request locale to retrieve localized data"], + ["12", "locale", "Pass the request locale to retrieve localized data"], ] ```ts title="src/api/store/products/route.ts" highlights={queryHighlights} @@ -190,13 +190,15 @@ import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" export const GET = async (req: MedusaRequest, res: MedusaResponse) => { const query = req.scope.resolve("query") - const { data: products } = await query.graph({ - entity: "product", - fields: ["id", "title", "description"], - options: { - locale: req.locale, + const { data: products } = await query.graph( + { + entity: "product", + fields: ["id", "title", "description"], }, - }) + { + locale: req.locale, + } + ) res.json({ products }) } diff --git a/www/apps/book/app/learn/fundamentals/module-links/index-module/page.mdx b/www/apps/book/app/learn/fundamentals/module-links/index-module/page.mdx index 0ace6e7281..9455ea551c 100644 --- a/www/apps/book/app/learn/fundamentals/module-links/index-module/page.mdx +++ b/www/apps/book/app/learn/fundamentals/module-links/index-module/page.mdx @@ -856,19 +856,21 @@ This will retrieve all brands that are linked to at least one product. ]} /> -To retrieve localized data for data models that have translations, pass an `options.locale` property to the first parameter of the `query.index` method: +To retrieve localized data for data models that have translations, pass a `locale` property in the second parameter object of the `query.index` method. -```ts highlights={[["5", "locale", "Pass the locale to retrieve localized data."]]} -const { data: products } = await query.index({ - entity: "product", - fields: ["id", "title", "description"], - options: { - locale: "fr-FR", +```ts highlights={[["7", "locale", "Pass the locale to retrieve localized data."]]} +const { data: products } = await query.index( + { + entity: "product", + fields: ["id", "title", "description"], }, -}) + { + locale: "fr-FR", + } +) ``` -The `options.locale` property is a string representing the locale code following the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). +The `locale` property is a string representing the locale code following the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). The returned products will have their `title` and `description` properties in French (`fr-FR`), if translations are available. diff --git a/www/apps/book/app/learn/fundamentals/module-links/query/page.mdx b/www/apps/book/app/learn/fundamentals/module-links/query/page.mdx index 841f928426..37bb7d8a8d 100644 --- a/www/apps/book/app/learn/fundamentals/module-links/query/page.mdx +++ b/www/apps/book/app/learn/fundamentals/module-links/query/page.mdx @@ -869,19 +869,21 @@ In the example above, you retrieve only deleted posts by enabling the `withDelet ]} /> -To retrieve localized data for data models that have translations, pass an `options.locale` property to the first parameter of the `query.graph` method. +To retrieve localized data for data models that have translations, pass a `locale` property in the second parameter object of the `query.graph` method. -```ts highlights={[["5", "locale", "Pass the locale to retrieve localized data."]]} -const { data: products } = await query.graph({ - entity: "product", - fields: ["id", "title", "description"], - options: { - locale: "fr-FR", +```ts highlights={[["7", "locale", "Pass the locale to retrieve localized data."]]} +const { data: products } = await query.graph( + { + entity: "product", + fields: ["id", "title", "description"], }, -}) + { + locale: "fr-FR", + } +) ``` @@ -900,7 +902,7 @@ const { data: products } = useQueryGraphStep({ -The `options.locale` property is a string representing the locale code following the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). +The `locale` property is a string representing the locale code following the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). The returned products will have their `title` and `description` properties in French (`fr-FR`), if translations are available. diff --git a/www/apps/book/generated/edit-dates.mjs b/www/apps/book/generated/edit-dates.mjs index f1fc206ed6..6708f051e3 100644 --- a/www/apps/book/generated/edit-dates.mjs +++ b/www/apps/book/generated/edit-dates.mjs @@ -65,7 +65,7 @@ export const generatedEditDates = { "app/learn/fundamentals/module-links/custom-columns/page.mdx": "2025-12-09T13:27:05.446Z", "app/learn/fundamentals/module-links/directions/page.mdx": "2025-03-17T12:52:06.161Z", "app/learn/fundamentals/module-links/page.mdx": "2025-11-28T13:45:06.742Z", - "app/learn/fundamentals/module-links/query/page.mdx": "2026-01-06T10:34:40.077Z", + "app/learn/fundamentals/module-links/query/page.mdx": "2026-01-06T15:51:26.135Z", "app/learn/fundamentals/modules/db-operations/page.mdx": "2025-10-28T16:02:06.265Z", "app/learn/fundamentals/modules/multiple-services/page.mdx": "2025-03-18T15:11:44.632Z", "app/learn/fundamentals/modules/page.mdx": "2025-12-23T07:00:14.586Z", @@ -121,7 +121,7 @@ export const generatedEditDates = { "app/learn/fundamentals/workflows/errors/page.mdx": "2025-04-25T14:26:25.000Z", "app/learn/fundamentals/api-routes/override/page.mdx": "2025-12-22T12:56:06.558Z", "app/learn/fundamentals/module-links/index/page.mdx": "2025-05-23T07:57:58.958Z", - "app/learn/fundamentals/module-links/index-module/page.mdx": "2026-01-06T10:34:35.671Z", + "app/learn/fundamentals/module-links/index-module/page.mdx": "2026-01-06T15:53:03.957Z", "app/learn/introduction/build-with-llms-ai/page.mdx": "2025-12-09T14:17:13.295Z", "app/learn/installation/docker/page.mdx": "2025-12-18T11:18:25.856Z", "app/learn/fundamentals/generated-types/page.mdx": "2026-01-06T06:38:15.719Z", @@ -138,5 +138,5 @@ export const generatedEditDates = { "app/learn/fundamentals/admin/translations/page.mdx": "2025-12-16T13:56:21.400Z", "app/learn/configurations/medusa-config/asymmetric-encryption/page.mdx": "2025-10-31T09:53:38.607Z", "app/learn/best-practices/third-party-sync/page.mdx": "2025-12-03T11:48:58.209Z", - "app/learn/fundamentals/api-routes/localization/page.mdx": "2026-01-06T10:34:44.853Z" + "app/learn/fundamentals/api-routes/localization/page.mdx": "2026-01-06T15:51:48.131Z" } \ No newline at end of file diff --git a/www/apps/book/public/llms-full.txt b/www/apps/book/public/llms-full.txt index 06b827ad58..3fb877b2df 100644 --- a/www/apps/book/public/llms-full.txt +++ b/www/apps/book/public/llms-full.txt @@ -10419,6 +10419,8 @@ For example, the following store routes have localization enabled by default: - `/store/collections` -> Get collections with translated fields - `/store/categories` -> Get categories with translated fields +Refer to the [Translation Module](https://docs.medusajs.com/resources/commerce-modules/translation#supported-module-translations/index.html.md) documentation for a list of supported core data models with localization support. + ### Apply Localization to Custom Routes If you're creating custom API routes outside the `/store` prefix, you must manually apply the `applyLocale` [middleware](https://docs.medusajs.com/learn/fundamentals/api-routes/middlewares/index.html.md) to enable localization support. @@ -10522,7 +10524,7 @@ The `req.locale` property contains the locale value from either the query parame ### Retrieve Localized Data with Query -To retrieve data models with translated fields, pass the `locale` option to [Query](https://docs.medusajs.com/docs/learn/fundamentals/module-links/query/index.html.md) when querying your data. +To retrieve data models with translated fields, pass the `locale` property in the second parameter object of [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query/index.html.md) when querying your data. For example, to retrieve products with translated names and descriptions: @@ -10532,13 +10534,15 @@ import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" export const GET = async (req: MedusaRequest, res: MedusaResponse) => { const query = req.scope.resolve("query") - const { data: products } = await query.graph({ - entity: "product", - fields: ["id", "title", "description"], - options: { - locale: req.locale, + const { data: products } = await query.graph( + { + entity: "product", + fields: ["id", "title", "description"], }, - }) + { + locale: req.locale, + } + ) res.json({ products }) } @@ -14146,43 +14150,43 @@ const Post = model.define("post", { id: model.id().primaryKey(), title: model.text(), author: model.belongsTo(() => Author, { - mappedBy: "posts" - }) + mappedBy: "posts", + }), }) const Author = model.define("author", { id: model.id().primaryKey(), name: model.text(), posts: model.hasMany(() => Post, { - mappedBy: "author" - }) + mappedBy: "author", + }), }) ``` To create a migration that reflects this relationship in the database, you can create a migration file as follows: ```ts title="src/modules/blog/migrations/Migration202507021200_create_author_and_post.ts" -import { Migration } from "@medusajs/framework/mikro-orm/migrations"; +import { Migration } from "@medusajs/framework/mikro-orm/migrations" export class Migration20251230112505 extends Migration { override async up(): Promise { - this.addSql(`create table if not exists "author" ("id" text not null, "name" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "author_pkey" primary key ("id"));`); - this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_author_deleted_at" ON "author" ("deleted_at") WHERE deleted_at IS NULL;`); + this.addSql(`create table if not exists "author" ("id" text not null, "name" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "author_pkey" primary key ("id"));`) + this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_author_deleted_at" ON "author" ("deleted_at") WHERE deleted_at IS NULL;`) - this.addSql(`create table if not exists "post" ("id" text not null, "title" text not null, "author_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "post_pkey" primary key ("id"));`); - this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_post_author_id" ON "post" ("author_id") WHERE deleted_at IS NULL;`); - this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_post_deleted_at" ON "post" ("deleted_at") WHERE deleted_at IS NULL;`); + this.addSql(`create table if not exists "post" ("id" text not null, "title" text not null, "author_id" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "post_pkey" primary key ("id"));`) + this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_post_author_id" ON "post" ("author_id") WHERE deleted_at IS NULL;`) + this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_post_deleted_at" ON "post" ("deleted_at") WHERE deleted_at IS NULL;`) - this.addSql(`alter table if exists "post" add constraint "post_author_id_foreign" foreign key ("author_id") references "author" ("id") on update cascade;`); + this.addSql(`alter table if exists "post" add constraint "post_author_id_foreign" foreign key ("author_id") references "author" ("id") on update cascade;`) } override async down(): Promise { - this.addSql(`alter table if exists "post" drop constraint if exists "post_author_id_foreign";`); + this.addSql(`alter table if exists "post" drop constraint if exists "post_author_id_foreign";`) - this.addSql(`drop table if exists "author" cascade;`); + this.addSql(`drop table if exists "author" cascade;`) - this.addSql(`drop table if exists "post" cascade;`); + this.addSql(`drop table if exists "post" cascade;`) } } @@ -14197,16 +14201,16 @@ Consider you have an existing `Post` data model, and you added a new `published_ You can create a migration file to add this new column as follows: ```ts title="src/modules/blog/migrations/Migration202507021300_add_published_at_to_post.ts" -import { Migration } from "@medusajs/framework/mikro-orm/migrations"; +import { Migration } from "@medusajs/framework/mikro-orm/migrations" export class Migration20251230113025 extends Migration { override async up(): Promise { - this.addSql(`alter table if exists "post" add column if not exists "published_at" timestamptz null;`); + this.addSql(`alter table if exists "post" add column if not exists "published_at" timestamptz null;`) } override async down(): Promise { - this.addSql(`alter table if exists "post" drop column if exists "published_at";`); + this.addSql(`alter table if exists "post" drop column if exists "published_at";`) } } @@ -14221,16 +14225,16 @@ Consider you have an existing `Post` data model, and you removed the `published_ You can create a migration file to remove this column as follows: ```ts title="src/modules/blog/migrations/Migration202507021400_remove_published_at_from_post.ts" -import { Migration } from "@medusajs/framework/mikro-orm/migrations"; +import { Migration } from "@medusajs/framework/mikro-orm/migrations" export class Migration20251230113125 extends Migration { override async up(): Promise { - this.addSql(`alter table if exists "post" drop column if exists "published_at";`); + this.addSql(`alter table if exists "post" drop column if exists "published_at";`) } override async down(): Promise { - this.addSql(`alter table if exists "post" add column if not exists "published_at" timestamptz null;`); + this.addSql(`alter table if exists "post" add column if not exists "published_at" timestamptz null;`) } } @@ -14245,16 +14249,16 @@ Consider you have an existing `Post` data model with a `title` column, and you r You can create a migration file to rename this column as follows: ```ts title="src/modules/blog/migrations/Migration202507021500_rename_title_to_headline_in_post.ts" -import { Migration } from "@medusajs/framework/mikro-orm/migrations"; +import { Migration } from "@medusajs/framework/mikro-orm/migrations" export class Migration20251230113214 extends Migration { override async up(): Promise { - this.addSql(`alter table if exists "post" rename column "title" to "headline";`); + this.addSql(`alter table if exists "post" rename column "title" to "headline";`) } override async down(): Promise { - this.addSql(`alter table if exists "post" rename column "headline" to "title";`); + this.addSql(`alter table if exists "post" rename column "headline" to "title";`) } } @@ -14274,24 +14278,24 @@ export const Post = model.define("post", { id: model.id().primaryKey(), headline: model.text().index(), author: model.belongsTo(() => Author, { - mappedBy: "posts" - }) + mappedBy: "posts", + }), }) ``` You can create a migration file to create this index as follows: ```ts title="src/modules/blog/migrations/Migration202507021600_create_index_on_headline_in_post.ts" -import { Migration } from "@medusajs/framework/mikro-orm/migrations"; +import { Migration } from "@medusajs/framework/mikro-orm/migrations" export class Migration20251230113322 extends Migration { override async up(): Promise { - this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_post_headline" ON "post" ("headline") WHERE deleted_at IS NULL;`); + this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_post_headline" ON "post" ("headline") WHERE deleted_at IS NULL;`) } override async down(): Promise { - this.addSql(`drop index if exists "IDX_post_headline";`); + this.addSql(`drop index if exists "IDX_post_headline";`) } } @@ -14306,16 +14310,16 @@ Consider you have an existing `Post` data model with an index on the `headline` You can create a migration file to drop this index as follows: ```ts title="src/modules/blog/migrations/Migration202507021700_drop_index_on_headline_in_post.ts" -import { Migration } from "@medusajs/framework/mikro-orm/migrations"; +import { Migration } from "@medusajs/framework/mikro-orm/migrations" export class Migration20251230113350 extends Migration { override async up(): Promise { - this.addSql(`drop index if exists "IDX_post_headline";`); + this.addSql(`drop index if exists "IDX_post_headline";`) } override async down(): Promise { - this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_post_headline" ON "post" ("headline") WHERE deleted_at IS NULL;`); + this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_post_headline" ON "post" ("headline") WHERE deleted_at IS NULL;`) } } @@ -16899,19 +16903,21 @@ This will retrieve all brands that are linked to at least one product. - [Medusa v2.12.4 or later](https://github.com/medusajs/medusa/releases/tag/v2.12.4) - [Translation Module Configured](https://docs.medusajs.com/resources/commerce-modules/translation#configure-translation-module/index.html.md) -To retrieve localized data for data models that have translations, pass an `options.locale` property to the first parameter of the `query.index` method: +To retrieve localized data for data models that have translations, pass a `locale` property in the second parameter object of the `query.index` method. -```ts highlights={[["5", "options", "Pass the locale to retrieve localized data."]]} -const { data: products } = await query.index({ - entity: "product", - fields: ["id", "title", "description"], - options: { - locale: "fr-FR", +```ts highlights={[["7", "locale", "Pass the locale to retrieve localized data."]]} +const { data: products } = await query.index( + { + entity: "product", + fields: ["id", "title", "description"], }, -}) + { + locale: "fr-FR", + } +) ``` -The `options.locale` property is a string representing the locale code following the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). +The `locale` property is a string representing the locale code following the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). The returned products will have their `title` and `description` properties in French (`fr-FR`), if translations are available. @@ -18493,23 +18499,25 @@ In the example above, you retrieve only deleted posts by enabling the `withDelet - [Medusa v2.12.4 or later](https://github.com/medusajs/medusa/releases/tag/v2.12.4) - [Translation Module Configured](https://docs.medusajs.com/resources/commerce-modules/translation#configure-translation-module/index.html.md) -To retrieve localized data for data models that have translations, pass an `options.locale` property to the first parameter of the `query.graph` method. +To retrieve localized data for data models that have translations, pass a `locale` property in the second parameter object of the `query.graph` method. ### query.graph -```ts highlights={[["5", "options", "Pass the locale to retrieve localized data."]]} -const { data: products } = await query.graph({ - entity: "product", - fields: ["id", "title", "description"], - options: { - locale: "fr-FR", +```ts highlights={[["7", "locale", "Pass the locale to retrieve localized data."]]} +const { data: products } = await query.graph( + { + entity: "product", + fields: ["id", "title", "description"], }, -}) + { + locale: "fr-FR", + } +) ``` ### useQueryGraphStep -```ts highlights={[["5", "options", "Pass the locale to retrieve localized data."]]} +```ts highlights={[["5", "locale", "Pass the locale to retrieve localized data."]]} const { data: products } = useQueryGraphStep({ entity: "product", fields: ["id", "title", "description"], @@ -18519,7 +18527,7 @@ const { data: products } = useQueryGraphStep({ }) ``` -The `options.locale` property is a string representing the locale code following the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). +The `locale` property is a string representing the locale code following the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). The returned products will have their `title` and `description` properties in French (`fr-FR`), if translations are available. @@ -43594,13 +43602,15 @@ export async function GET( ) { const query = req.scope.resolve("query") - const { data: posts } = await query.graph({ - entity: "post", - fields: ["id", "title"], - options: { - locale: req.locale, + const { data: posts } = await query.graph( + { + entity: "post", + fields: ["id", "title"], }, - }) + { + locale: req.locale, + } + ) res.json({ posts }) } diff --git a/www/apps/resources/app/commerce-modules/translation/custom-data-models/page.mdx b/www/apps/resources/app/commerce-modules/translation/custom-data-models/page.mdx index f808b4b27d..9d2428bc5b 100644 --- a/www/apps/resources/app/commerce-modules/translation/custom-data-models/page.mdx +++ b/www/apps/resources/app/commerce-modules/translation/custom-data-models/page.mdx @@ -190,7 +190,7 @@ In your custom API routes, you can retrieve the request's locale from the `local For example, to retrieve blog posts with translated titles in the `/store/posts` API route: export const apiRouteHighlights = [ - ["13", "locale", "Pass the request locale to the query options."], + ["15", "locale", "Pass the request locale to the query options."], ] ```ts title="src/api/routes/store/posts.ts" highlights={apiRouteHighlights} @@ -202,13 +202,15 @@ export async function GET( ) { const query = req.scope.resolve("query") - const { data: posts } = await query.graph({ - entity: "post", - fields: ["id", "title"], - options: { - locale: req.locale, + const { data: posts } = await query.graph( + { + entity: "post", + fields: ["id", "title"], }, - }) + { + locale: req.locale, + } + ) res.json({ posts }) } @@ -324,4 +326,4 @@ The returned posts in the API response will have their `title` field set to the 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](/references/translation) for a full list of available methods and how to use them. \ No newline at end of file +Refer to the [Translation Module service reference](/references/translation) for a full list of available methods and how to use them. diff --git a/www/apps/resources/generated/edit-dates.mjs b/www/apps/resources/generated/edit-dates.mjs index bfcb4c8b2f..c5cb752a5f 100644 --- a/www/apps/resources/generated/edit-dates.mjs +++ b/www/apps/resources/generated/edit-dates.mjs @@ -6937,5 +6937,5 @@ export const generatedEditDates = { "app/how-to-tutorials/how-to/admin/auth/page.mdx": "2025-12-30T06:35:28.828Z", "app/integrations/guides/okta/page.mdx": "2025-12-30T06:35:28.653Z", "app/nextjs-starter/guides/remove-country-code/page.mdx": "2025-12-30T10:28:10.072Z", - "app/commerce-modules/translation/custom-data-models/page.mdx": "2026-01-06T08:49:12.704Z" + "app/commerce-modules/translation/custom-data-models/page.mdx": "2026-01-06T15:54:25.801Z" } \ No newline at end of file