docs: translation module (#14271)
* docs: translation module * fix link in JS SDK * add translations user guides [WIP] * updates * fix broken link * remove mentions of default locale * change header * updates * updated user guides * handle todos * fix build error * fix lint errors
This commit is contained in:
1 parent
1743ed7f04
commit
c1a5390fc6
133 files changed
+21304
-1661
No files matched your search
@@ -18,6 +18,20 @@ A cart holds information about:
|
||||
- The payment method and information necessary to complete the purchase.
|
||||
- These are stored and handled by the [Payment Module](../../payment/page.mdx).
|
||||
|
||||
### Cart Locale
|
||||
|
||||
<Note>
|
||||
|
||||
Cart locale is available starting [Medusa v2.12.3](https://github.com/medusajs/medusa/releases/tag/v2.12.3).
|
||||
|
||||
</Note>
|
||||
|
||||
The `Cart` data model has a `locale` property that indicates the locale of the cart. This locale is in the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1) format, such as `en-US` for American English or `fr-FR` for French (France).
|
||||
|
||||
When creating a cart, you can set the `locale` property to specify the desired locale for the cart. The information of the items in the cart, such as product titles and descriptions, will be displayed in the specified locale if translations are available.
|
||||
|
||||
Refer to the [Translation Module](../../translation/page.mdx) to learn more about how translations and locales work.
|
||||
|
||||
---
|
||||
|
||||
## Line Items
|
||||
|
||||
@@ -17,6 +17,22 @@ An order holds information about:
|
||||
- This is stored and handled by the [Customer Module](../../customer/page.mdx).
|
||||
- Payment and shipping information
|
||||
|
||||
## Order Locale
|
||||
|
||||
<Note>
|
||||
|
||||
Order locale is available starting [Medusa v2.12.3](https://github.com/medusajs/medusa/releases/tag/v2.12.3).
|
||||
|
||||
</Note>
|
||||
|
||||
The `Order` data model has a `locale` property that indicates the locale of the order. This locale is in the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1) format, such as `en-US` for American English or `fr-FR` for French (France).
|
||||
|
||||
When an order is created from a cart or a draft order, the order inherits their locale. This ensures that all item details in the order, such as product titles and descriptions, are presented in the correct language if translations are available.
|
||||
|
||||
When order items are changed through an edit, claim, or exchange, the new items added to the order will also have their details in the order's locale if translations are available.
|
||||
|
||||
You can also edit an order's locale using the [Update Order](!api!/admin#orders_postordersid) API route.
|
||||
|
||||
---
|
||||
|
||||
## Order Items
|
||||
|
||||
@@ -102,6 +102,12 @@ Similar to regular orders, draft orders can be [edited](../edit/page.mdx), allow
|
||||
|
||||
When the order edit is confirmed on the draft order, the changes are applied directly to the draft order and its [version](../order-versioning/page.mdx) is incremented.
|
||||
|
||||
### Draft Order Locale
|
||||
|
||||
A draft order's `locale` can be set and updated before converting it to a regular order. All item details in the draft order, such as product titles and descriptions, will be presented in the correct language if translations are available.
|
||||
|
||||
When the draft order is converted to a regular order, it retains its `locale` property. The details of the order items will remain in the specified locale.
|
||||
|
||||
### Converting Draft Orders to Regular Orders
|
||||
|
||||
Once a draft order is finalized and ready for processing, it can be converted to a regular order. This involves:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CardList } from "docs-ui"
|
||||
import { CardList, Card } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Commerce Modules`,
|
||||
@@ -85,12 +85,22 @@ A Commerce Module also defines data models, representing tables in the database.
|
||||
href: "/commerce-modules/tax"
|
||||
},
|
||||
{
|
||||
title: "User Module",
|
||||
href: "/commerce-modules/user"
|
||||
}
|
||||
title: "Translation Module",
|
||||
href: "/commerce-modules/translation",
|
||||
badge: {
|
||||
children: "Beta",
|
||||
variant: "blue"
|
||||
}
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<Card
|
||||
title="User Module"
|
||||
href="/commerce-modules/user"
|
||||
className="my-1"
|
||||
/>
|
||||
|
||||
---
|
||||
|
||||
## How to Use Modules
|
||||
|
||||
@@ -8,7 +8,7 @@ products:
|
||||
- sales channel
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab, Table } from "docs-ui"
|
||||
import { CodeTabs, CodeTab, Table, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Links between Product Module and Other Modules`,
|
||||
@@ -130,6 +130,118 @@ Read-only links are used to query data across modules, but the relations aren't
|
||||
[Learn more](#sales-channel-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[Product](/references/product/models/Product)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation) in [Translation Module](../../translation/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#translation-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductVariant](/references/product/models/ProductVariant)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation) in [Translation Module](../../translation/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#translation-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductCategory](/references/product/models/ProductCategory)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation) in [Translation Module](../../translation/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#translation-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductCollection](/references/product/models/ProductCollection)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation) in [Translation Module](../../translation/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#translation-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductTag](/references/product/models/ProductTag)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation) in [Translation Module](../../translation/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#translation-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductType](/references/product/models/ProductType)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation) in [Translation Module](../../translation/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#translation-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductOption](/references/product/models/ProductOption)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation) in [Translation Module](../../translation/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#translation-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductOptionValue](/references/product/models/ProductOptionValue)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation) in [Translation Module](../../translation/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#translation-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
|
||||
@@ -624,3 +736,72 @@ createRemoteLinkStep({
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
---
|
||||
|
||||
## Translation Module
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
title: "Translation Module",
|
||||
link: "/commerce-modules/translation",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
Medusa defines read-only links from several data models in the Product Module to the [Translation](/references/translation/models/Translation) data model in the [Translation Module](../../translation/page.mdx):
|
||||
|
||||
- `Product` (one-to-many) to `Translation`, and vice versa.
|
||||
- `ProductVariant` (one-to-many) to `Translation`. You can only retrieve the translations of a product variant, and not the other way around.
|
||||
- `ProductCategory` (one-to-many) to `Translation`. You can only retrieve the translations of a product category, and not the other way around.
|
||||
- `ProductCollection` (one-to-many) to `Translation`. You can only retrieve the translations of a product collection, and not the other way around.
|
||||
- `ProductTag` (one-to-many) to `Translation`. You can only retrieve the translations of a product tag, and not the other way around.
|
||||
- `ProductType` (one-to-many) to `Translation`. You can only retrieve the translations of a product type, and not the other way around.
|
||||
- `ProductOption` (one-to-many) to `Translation`. You can only retrieve the translations of a product option, and not the other way around.
|
||||
- `ProductOptionValue` (one-to-many) to `Translation`. You can only retrieve the translations of a product option value, and not the other way around.
|
||||
|
||||
### Retrieve with Query
|
||||
|
||||
To retrieve the translations of a product with [Query](!docs!/learn/fundamentals/module-links/query), pass `translations.*` in `fields`:
|
||||
|
||||
<Note>
|
||||
|
||||
You can pass the `translations.*` field when querying any of the above-mentioned data models to retrieve their associated translations.
|
||||
|
||||
</Note>
|
||||
|
||||
<CodeTabs group="relation-query">
|
||||
<CodeTab label="query.graph" value="method">
|
||||
|
||||
```ts
|
||||
const { data: products } = await query.graph({
|
||||
entity: "product",
|
||||
fields: [
|
||||
"translations.*",
|
||||
],
|
||||
})
|
||||
|
||||
// products[0].translations
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="useQueryGraphStep" value="step">
|
||||
|
||||
```ts
|
||||
import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
|
||||
|
||||
// ...
|
||||
|
||||
const { data: products } = useQueryGraphStep({
|
||||
entity: "product",
|
||||
fields: [
|
||||
"translations.*",
|
||||
],
|
||||
})
|
||||
|
||||
// products[0].translations
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
@@ -3,7 +3,7 @@ products:
|
||||
- currency
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab, Table } from "docs-ui"
|
||||
import { CodeTabs, CodeTab, Table, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Links between Store Module and Other Modules`,
|
||||
@@ -55,6 +55,20 @@ Read-only links are used to query data across modules, but the relations aren't
|
||||
[Learn more](#currency-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[StoreLocale](/references/store/models/StoreLocale)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Locale](/references/translation/models/Locale) in [Translation Module](../../translation/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - has many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#translation-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
|
||||
@@ -62,9 +76,9 @@ Read-only links are used to query data across modules, but the relations aren't
|
||||
|
||||
## Currency Module
|
||||
|
||||
The Store Module has a `Currency` data model that stores the supported currencies of a store. However, these currencies don't hold all the details of a currency, such as its name or symbol.
|
||||
The Store Module has a `StoreCurrency` data model that stores the supported currencies of a store. However, these currencies don't hold all the details of a currency, such as its name or symbol.
|
||||
|
||||
Instead, Medusa defines a read-only link between the [Currency Module](../../currency/page.mdx)'s `Currency` data model and the Store Module's `StoreCurrency` data model. This means you can retrieve the details of a store's supported currencies, but you don't manage the links in a pivot table in the database. The currencies of a store are determined by the `currency_code` of the [Currency](/references/store/models/StoreCurrency) data model in the Store Module (not in the Currency Module).
|
||||
Instead, Medusa defines a read-only link from the Store Module's `StoreCurrency` data model to the [Currency Module](../../currency/page.mdx)'s `Currency` data model. This means you can retrieve the details of a store's supported currencies, but you don't manage the links in a pivot table in the database.
|
||||
|
||||
### Retrieve with Query
|
||||
|
||||
@@ -104,3 +118,60 @@ const { data: stores } = useQueryGraphStep({
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Translation Module
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
The Store Module has a `StoreLocale` data model that stores the supported locales of a store. However, these locales don't hold all the details of a locale, such as its name.
|
||||
|
||||
Instead, Medusa defines a read-only link from the Store Module's `StoreLocale` data model to the [Translation Module](../../translation/page.mdx)'s `Locale` data model. This means you can retrieve the details of a store's supported locales, but you don't manage the links in a pivot table in the database.
|
||||
|
||||
### Retrieve with Query
|
||||
|
||||
To retrieve the details of a store's locales with [Query](!docs!/learn/fundamentals/module-links/query), pass `supported_locales.locale.*` in `fields`:
|
||||
|
||||
<CodeTabs group="relation-query">
|
||||
<CodeTab label="query.graph" value="method">
|
||||
|
||||
```ts
|
||||
const { data: stores } = await query.graph({
|
||||
entity: "store",
|
||||
fields: [
|
||||
"supported_locales.locale.*",
|
||||
],
|
||||
})
|
||||
|
||||
// stores[0].supported_locales[0].locale
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="useQueryGraphStep" value="step">
|
||||
|
||||
```ts
|
||||
import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
|
||||
|
||||
// ...
|
||||
|
||||
const { data: stores } = useQueryGraphStep({
|
||||
entity: "store",
|
||||
fields: [
|
||||
"supported_locales.locale.*",
|
||||
],
|
||||
})
|
||||
|
||||
// stores[0].supported_locales[0].locale
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Store Locales`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this guide, you'll learn about locales defined in the Store Module.
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Medusa v2.12.3 or later",
|
||||
link: "https://github.com/medusajs/medusa/releases/tag/v2.12.3",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<Note>
|
||||
|
||||
While the Store Module allows you to manage the locales for your store, the actual locale data and translations are managed by the [Translation Module](../../translation/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
## Supported Locales
|
||||
|
||||
The Store Module has a [StoreLocale](/references/store/models/StoreLocale) data model that represents the locales supported by your store. It has a `locale_code` property that follows the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). For example, `en-US` represents American English, while `fr-FR` represents French (France).
|
||||
|
||||
`StoreLocale` belongs to the [Store](/references/store/models/Store) data model, which has a `supported_locales` property that lists all the locales available in your store.
|
||||
|
||||
For example, if your store supports English (United States) and French (France), you'll have two `StoreLocale` records with the locale codes `en-US` and `fr-FR`.
|
||||
|
||||

|
||||
@@ -0,0 +1,129 @@
|
||||
import { Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Translation Concepts`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this guide, you'll learn about the key concepts related to the Translation Module, including locales and translations.
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
## Locales
|
||||
|
||||
The [Locale data model](/references/translation/models/Locale) represents a language that resources can be translated into.
|
||||
|
||||
Its `code` property follows the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). For example, `en-US` represents American English, while `fr-FR` represents French (France).
|
||||
|
||||
Locales are automatically populated in your Medusa application the first time the Translation Module is used.
|
||||
|
||||
### Default Locale
|
||||
|
||||
The Translation Module doesn't enforce a default locale. If a resource doesn't have a translation in the requested locale, it will fall back to the original value stored in the resource's data model.
|
||||
|
||||
---
|
||||
|
||||
## Translations
|
||||
|
||||
The [Translation data model](/references/translation/models/Translation) represents a translated value for a specific resource in a specific locale.
|
||||
|
||||
The data model has the following properties to associate the translation with the resource:
|
||||
|
||||
- `reference_id`: The ID of the resource being translated (for example, the ID of the product being translated).
|
||||
- `reference`: The name of the table where the resource is stored (for example, `product` when translating a product).
|
||||
|
||||
The locale of the translation is indicated by the `locale_code` property, which follows the same [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1) as the [Locale](#locales) data model.
|
||||
|
||||
A resource may have only one translation per locale. For example, a product can have only one translation in `fr-FR` and another translation in `es-ES`.
|
||||
|
||||
The actual translated values are stored in the `translations` property, which is a JSON object where each key represents a field of the resource being translated, and the value is the translated text.
|
||||
|
||||
For example, a translation for a product to French (`fr-FR`) may look like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"reference_id": "prod_123",
|
||||
"reference": "product",
|
||||
"locale_code": "fr-FR",
|
||||
"translations": {
|
||||
"title": "Produit Exemple",
|
||||
"description": "Ceci est une description en français."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each key in the `translations` object corresponds to a property in the product resource, such as `title` and `description`, with their respective translated values.
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Translations in Medusa
|
||||
|
||||
<Note>
|
||||
|
||||
To retrieve translations for the storefront, refer to the [Serve Translations in the Storefront](../storefront/page.mdx) guide.
|
||||
|
||||
</Note>
|
||||
|
||||
You can retrieve translations for a resource on the Medusa server using [Query](!docs!/learn/fundamentals/module-links/query). You can filter translations by `reference_id` and `locale_code` to get the specific translation you need.
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
const { data: translations } = await query.graph({
|
||||
entity: "translation",
|
||||
fields: ["reference_id", "locale_code", "translations"],
|
||||
filters: {
|
||||
reference_id: "prod_123",
|
||||
locale_code: "fr-FR",
|
||||
},
|
||||
})
|
||||
|
||||
console.log(translations)
|
||||
// Output:
|
||||
// [{
|
||||
// reference_id: "prod_123",
|
||||
// locale_code: "fr-FR",
|
||||
// translations: {
|
||||
// title: "Produit Exemple",
|
||||
// description: "Ceci est une description en français."
|
||||
// }
|
||||
// }]
|
||||
```
|
||||
|
||||
In this example, you retrieve the translation records of a product with the ID `prod_123` in French (`fr-FR`).
|
||||
|
||||
If you've enabled the [Caching Module](../../../infrastructure-modules/caching/page.mdx) in your Medusa application, you can also cache translation queries to improve performance:
|
||||
|
||||
```ts
|
||||
const { data: translations } = await query.graph({
|
||||
entity: "translation",
|
||||
fields: ["reference_id", "locale_code", "translations"],
|
||||
filters: {
|
||||
reference_id: "prod_123",
|
||||
locale_code: "fr-FR",
|
||||
},
|
||||
}, {
|
||||
cache: {
|
||||
enable: true,
|
||||
},
|
||||
})
|
||||
|
||||
console.log(translations)
|
||||
// Output:
|
||||
// [{
|
||||
// reference_id: "prod_123",
|
||||
// locale_code: "fr-FR",
|
||||
// translations: {
|
||||
// title: "Produit Exemple",
|
||||
// description: "Ceci est une description en français."
|
||||
// }
|
||||
// }]
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
import { ChildDocs } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Translation JS SDK Methods`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
The [JS SDK](../../../js-sdk/page.mdx) allows you to send requests to the Medusa server application from your client applications, such as a storefront or the Medusa Admin dashboard.
|
||||
|
||||
Use the following methods or properties to send requests to Translation related API routes in your Medusa application. They are provided by the `@medusajs/js-sdk` package.
|
||||
|
||||
The following links will take you to the reference documentation for the [JS SDK](../../../js-sdk/page.mdx).
|
||||
|
||||
<ChildDocs type="item" />
|
||||
@@ -0,0 +1,370 @@
|
||||
---
|
||||
products:
|
||||
- product
|
||||
- store
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab, Table } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Links between Translation Module and Other Modules`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
This document showcases the module links that Medusa defines between the Translation Module and other Commerce Modules.
|
||||
|
||||
## Summary
|
||||
|
||||
Medusa defines the following links between the Translation Module and other Commerce Modules:
|
||||
|
||||
<Table>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>
|
||||
First Data Model
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell>
|
||||
Second Data Model
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell>
|
||||
Type
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell>
|
||||
Description
|
||||
</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[Product](/references/product/models/Product) in [Product Module](../../product/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#product-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductVariant](/references/product/models/ProductVariant) in [Product Module](../../product/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#product-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductCategory](/references/product/models/ProductCategory) in [Product Module](../../product/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#product-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductCollection](/references/product/models/ProductCollection) in [Product Module](../../product/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#product-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductTag](/references/product/models/ProductTag) in [Product Module](../../product/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#product-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductType](/references/product/models/ProductType) in [Product Module](../../product/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#product-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductOption](/references/product/models/ProductOption) in [Product Module](../../product/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#product-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductOptionValue](/references/product/models/ProductOptionValue) in [Product Module](../../product/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - one-to-many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#product-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[StoreLocale](/references/store/models/StoreLocale) in [Store Module](../../store/page.mdx)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Locale](/references/translation/models/Locale)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Read-only - has many
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
[Learn more](#store-module)
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
|
||||
---
|
||||
|
||||
## Product Module
|
||||
|
||||
Medusa defines the following read-only links between the Translation and Product Modules:
|
||||
|
||||
<Table>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>
|
||||
Data Model
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell>
|
||||
Link Type
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell>
|
||||
Description
|
||||
</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[Product](/references/product/models/Product) \<-\> [Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
One-to-many (bidirectional)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Retrieve translations associated with a product and vice versa.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductVariant](/references/product/models/ProductVariant) -> [Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
One-to-many (read-only)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Retrieve translations of a product variant only.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductCategory](/references/product/models/ProductCategory) -> [Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
One-to-many (read-only)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Retrieve translations of a product category only.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductCollection](/references/product/models/ProductCollection) -> [Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
One-to-many (read-only)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Retrieve translations of a product collection only.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductTag](/references/product/models/ProductTag) -> [Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
One-to-many (read-only)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Retrieve translations of a product tag only.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductType](/references/product/models/ProductType) -> [Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
One-to-many (read-only)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Retrieve translations of a product type only.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductOption](/references/product/models/ProductOption) -> [Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
One-to-many (read-only)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Retrieve translations of a product option only.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
[ProductOptionValue](/references/product/models/ProductOptionValue) -> [Translation](/references/translation/models/Translation)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
One-to-many (read-only)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
Retrieve translations of a product option value only.
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
|
||||
### Retrieve with Query
|
||||
|
||||
To retrieve the translations of a product with [Query](!docs!/learn/fundamentals/module-links/query), pass `translations.*` in `fields`:
|
||||
|
||||
<Note>
|
||||
|
||||
You can pass the `translations.*` field when querying any of the above-mentioned data models to retrieve their associated translations.
|
||||
|
||||
</Note>
|
||||
|
||||
<CodeTabs group="relation-query">
|
||||
<CodeTab label="query.graph" value="method">
|
||||
|
||||
```ts
|
||||
const { data: products } = await query.graph({
|
||||
entity: "product",
|
||||
fields: [
|
||||
"translations.*",
|
||||
],
|
||||
})
|
||||
|
||||
// products[0].translations
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="useQueryGraphStep" value="step">
|
||||
|
||||
```ts
|
||||
import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
|
||||
|
||||
// ...
|
||||
|
||||
const { data: products } = useQueryGraphStep({
|
||||
entity: "product",
|
||||
fields: [
|
||||
"translations.*",
|
||||
],
|
||||
})
|
||||
|
||||
// products[0].translations
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
---
|
||||
|
||||
## Store Module
|
||||
|
||||
The [Store Module](../../store/page.mdx) has a `StoreLocale` data model that stores the supported locales of a store. However, these locales don't hold all the details of a locale, such as its name.
|
||||
|
||||
Instead, Medusa defines a read-only link from the Store Module's `StoreLocale` data model to the Translation Module's `Locale` data model. This means you can retrieve the details of a store's supported locales, but you don't manage the links in a pivot table in the database.
|
||||
|
||||
### Retrieve with Query
|
||||
|
||||
To retrieve the details of a store's locales with [Query](!docs!/learn/fundamentals/module-links/query), pass `supported_locales.locale.*` in `fields`:
|
||||
|
||||
<CodeTabs group="relation-query">
|
||||
<CodeTab label="query.graph" value="method">
|
||||
|
||||
```ts
|
||||
const { data: stores } = await query.graph({
|
||||
entity: "store",
|
||||
fields: [
|
||||
"supported_locales.locale.*",
|
||||
],
|
||||
})
|
||||
|
||||
// stores[0].supported_locales[0].locale
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="useQueryGraphStep" value="step">
|
||||
|
||||
```ts
|
||||
import { useQueryGraphStep } from "@medusajs/medusa/core-flows"
|
||||
|
||||
// ...
|
||||
|
||||
const { data: stores } = useQueryGraphStep({
|
||||
entity: "store",
|
||||
fields: [
|
||||
"supported_locales.locale.*",
|
||||
],
|
||||
})
|
||||
|
||||
// stores[0].supported_locales[0].locale
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
@@ -0,0 +1,222 @@
|
||||
---
|
||||
generate_toc: true
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab, ChildDocs, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Translation Module`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this section of the documentation, you will find resources to learn more about the Translation Module and how to use it in your application.
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Medusa v2.12.3 or later",
|
||||
link: "https://github.com/medusajs/medusa/releases/tag/v2.12.3"
|
||||
},
|
||||
{
|
||||
text: "Translation Feature Flag Enabled",
|
||||
link: "#"
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
<Note title="Looking for no-code docs?">
|
||||
|
||||
Refer to the [Medusa Admin User Guide](!user-guide!/settings/translations) to learn how to manage translations in the dashboard.
|
||||
|
||||
</Note>
|
||||
|
||||
Medusa has translation features available out-of-the-box through the Translation Module. A [module](!docs!/learn/fundamentals/modules) is a standalone package that provides features for a single domain. Each of Medusa's commerce features is provided in Commerce Modules, such as the Translation Module.
|
||||
|
||||
<Note>
|
||||
|
||||
Refer to the [Module Isolation](!docs!/learn/fundamentals/modules/isolation) guide to learn more about why modules are isolated.
|
||||
|
||||
</Note>
|
||||
|
||||
## Translation Features
|
||||
|
||||
- [Translation and Locale Management](./concepts/page.mdx): Manage locales and add translations for different resources in your store.
|
||||
- [Multi-Language Support](./storefront/page.mdx): Manage and serve resources like products in multiple languages to cater to a diverse customer base.
|
||||
|
||||
---
|
||||
|
||||
## Configure Translation Module
|
||||
|
||||
The Translation Module is currently behind a feature flag. To use it in your Medusa application, add it to the `modules` array and enable the `translation` feature flag.
|
||||
|
||||
In your `medusa-config.ts` file, add the Translation Module to the `modules` array and enable the `translation` feature flag:
|
||||
|
||||
```ts title="medusa-config.ts"
|
||||
module.exports = defineConfig({
|
||||
// ...
|
||||
modules: [
|
||||
// other modules...
|
||||
{
|
||||
resolve: "@medusajs/medusa/translation",
|
||||
},
|
||||
],
|
||||
featureFlags: {
|
||||
translation: true,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Then, run the following command to make the necessary database changes for the Translation Module:
|
||||
|
||||
```bash
|
||||
npx medusa db:migrate
|
||||
```
|
||||
|
||||
You can then use the Translation Module in your Medusa application.
|
||||
|
||||
---
|
||||
|
||||
## How to Use the Translation Module
|
||||
|
||||
In your Medusa application, you build flows around Commerce Modules. A flow is built as a [Workflow](!docs!/learn/fundamentals/workflows), which is a special function composed of a series of steps that guarantees data consistency and a reliable rollback mechanism.
|
||||
|
||||
You can build custom workflows and steps. You can also re-use Medusa's workflows and steps, which are provided by the `@medusajs/medusa/core-flows` package.
|
||||
|
||||
For example:
|
||||
|
||||
export const highlights = [
|
||||
["12", "Modules.TRANSLATION", "Resolve the module in a step."]
|
||||
]
|
||||
|
||||
```ts title="src/workflows/create-translation.ts" highlights={highlights}
|
||||
import {
|
||||
createWorkflow,
|
||||
WorkflowResponse,
|
||||
createStep,
|
||||
StepResponse,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
const createTranslationStep = createStep(
|
||||
"create-translation",
|
||||
async ({}, { container }) => {
|
||||
const translationModuleService = container.resolve(Modules.TRANSLATION)
|
||||
|
||||
const translation = await translationModuleService.createTranslations({
|
||||
reference_id: "product_123",
|
||||
reference: "product",
|
||||
locale_code: "fr-FR",
|
||||
translations: {
|
||||
title: "Produit Exemple",
|
||||
description: "Ceci est une description en français.",
|
||||
},
|
||||
})
|
||||
|
||||
return new StepResponse({ translation }, translation.id)
|
||||
},
|
||||
async (translationId, { container }) => {
|
||||
const translationModuleService = container.resolve(Modules.TRANSLATION)
|
||||
|
||||
await translationModuleService.deleteTranslations([translationId])
|
||||
}
|
||||
)
|
||||
|
||||
export const createTranslationWorkflow = createWorkflow(
|
||||
"create-translation",
|
||||
() => {
|
||||
const { translation } = createTranslationStep()
|
||||
|
||||
return new WorkflowResponse({
|
||||
translation,
|
||||
})
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
You can then execute the workflow in your custom API routes, scheduled jobs, or subscribers:
|
||||
|
||||
<CodeTabs group="resource-types">
|
||||
<CodeTab label="API Route" value="api-route">
|
||||
|
||||
```ts title="src/api/workflow/route.ts" highlights={[["11"], ["12"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports"
|
||||
import type {
|
||||
MedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "@medusajs/framework/http"
|
||||
import { createTranslationWorkflow } from "../../workflows/create-translation"
|
||||
|
||||
export async function GET(
|
||||
req: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
) {
|
||||
const { result } = await createTranslationWorkflow(req.scope)
|
||||
.run()
|
||||
|
||||
res.send(result)
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="Subscriber" value="subscriber">
|
||||
|
||||
```ts title="src/subscribers/user-created.ts" highlights={[["11"], ["12"]]} collapsibleLines="1-6" expandButtonLabel="Show Imports"
|
||||
import {
|
||||
type SubscriberConfig,
|
||||
type SubscriberArgs,
|
||||
} from "@medusajs/framework"
|
||||
import { createTranslationWorkflow } from "../workflows/create-translation"
|
||||
|
||||
export default async function handleUserCreated({
|
||||
event: { data },
|
||||
container,
|
||||
}: SubscriberArgs<{ id: string }>) {
|
||||
const { result } = await createTranslationWorkflow(container)
|
||||
.run()
|
||||
|
||||
console.log(result)
|
||||
}
|
||||
|
||||
export const config: SubscriberConfig = {
|
||||
event: "user.created",
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="Scheduled Job" value="scheduled-job">
|
||||
|
||||
```ts title="src/jobs/run-daily.ts" highlights={[["7"], ["8"]]}
|
||||
import { MedusaContainer } from "@medusajs/framework/types"
|
||||
import { createTranslationWorkflow } from "../workflows/create-translation"
|
||||
|
||||
export default async function myCustomJob(
|
||||
container: MedusaContainer
|
||||
) {
|
||||
const { result } = await createTranslationWorkflow(container)
|
||||
.run()
|
||||
|
||||
console.log(result)
|
||||
}
|
||||
|
||||
export const config = {
|
||||
name: "run-once-a-day",
|
||||
schedule: `0 0 * * *`,
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
Refer to the [Workflows](!docs!/learn/fundamentals/workflows) documentation to learn more.
|
||||
|
||||
---
|
||||
|
||||
## Supported Module Translations
|
||||
|
||||
The Translation Module currently supports translations for all data models in the [Product Module](../product/page.mdx), including products, product variants, and categories.
|
||||
|
||||
Future versions of the Translation Module will include support for all Commerce Modules, as well as custom modules.
|
||||
|
||||
---
|
||||
|
||||
<CommerceModuleSections />
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
products:
|
||||
- store
|
||||
- product
|
||||
- cart
|
||||
---
|
||||
|
||||
import { Prerequisites, CodeTabs } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Serve Translations in the Storefront`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this guide, you’ll learn how to use locales and serve translated content in your storefront application in your Medusa application.
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
## Fetch Store Locales
|
||||
|
||||
You can retrieve the list of locales available in your store using the [List Locales Store API route](!api!/store#locales_getlocales). You can display this list to customers, allowing them to select their preferred language.
|
||||
|
||||
For example, to fetch the list of locales, send a `GET` request to the following endpoint:
|
||||
|
||||
```bash
|
||||
curl "http://localhost:9000/store/locales" \
|
||||
-H 'x-publishable-api-key: {your_publishable_api_key}'
|
||||
```
|
||||
|
||||
Learn more in the [Localization](../../../storefront-development/localization/page.mdx) storefront guide.
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
You must pass a publishable API key in the request header to store API routes. Learn more in the [Store API reference](!api!/store#publishable-api-key).
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Translations for Resources
|
||||
|
||||
Currently, you can retrieve translations using the [Store API routes](!api!/store) for product-related resources, such as products, product variants, and categories. Future releases will expand translation support to additional resources.
|
||||
|
||||
Medusa determines the locale for the request in the following order of priority:
|
||||
|
||||
- The `locale` query parameter in the API request.
|
||||
- The `x-medusa-locale` header in the API request.
|
||||
|
||||
If translations aren't available for the selected locale, or no locale is selected, the original content stored in the resource's data model is returned.
|
||||
|
||||
For example:
|
||||
|
||||
```bash
|
||||
curl "http://localhost:9000/store/products?locale=fr-FR" \
|
||||
-H 'x-publishable-api-key: {your_publishable_api_key}'
|
||||
```
|
||||
|
||||
This returns the list of products with their French (France) translations if available:
|
||||
|
||||
```json
|
||||
{
|
||||
"products": [
|
||||
{
|
||||
"id": "prod_123",
|
||||
"title": "Produit Exemple",
|
||||
"description": "Ceci est une description en français.",
|
||||
// other product fields...
|
||||
},
|
||||
// other products...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Learn more in the [List Products](../../../storefront-development/products/list/page.mdx#retrieve-translations-for-products) storefront guide.
|
||||
|
||||
---
|
||||
|
||||
## Set a Cart's Locale
|
||||
|
||||
A cart can have a locale, which determines the language of the item contents. You can set the locale when creating the cart and update it if the user changes their language preference.
|
||||
|
||||
For example, when creating a cart, set the `locale` property in the request body:
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:9000/store/carts" \
|
||||
-H 'x-publishable-api-key: {your_publishable_api_key}' \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
// other cart properties...
|
||||
"locale": "fr-FR"
|
||||
}'
|
||||
```
|
||||
|
||||
This creates a cart with the French (France) locale. When you add items to the cart, their titles and descriptions are displayed in French if translations are available.
|
||||
|
||||
If you don't specify a locale when creating the cart, the original product content is used for the items in the cart.
|
||||
|
||||
Learn more in the [Create Cart](../../../storefront-development/cart/create/page.mdx) and [Update Cart](../../../storefront-development/cart/update/page.mdx) storefront guides.
|
||||
|
||||
---
|
||||
|
||||
## Locale of Placed Order
|
||||
|
||||
When a cart is completed and an order is placed, the locale of the cart is copied to the order. The content of items in the order is displayed in the locale that was set in the cart.
|
||||
|
||||
This ensures that customers see order details in their preferred language.
|
||||
@@ -0,0 +1,15 @@
|
||||
import { ChildDocs } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Translation Workflows`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
[Workflows](!docs!/learn/fundamentals/workflows) are a series of queries and actions, called steps, that complete a task. By using workflows, you benefit from features like data consistency and a reliable roll-back mechanism.
|
||||
|
||||
When building your customizations, it's highly recommended to re-use Medusa's existing workflows and steps where possible. The following workflows and steps allow you to manage Translations and use their features in your Medusa application. They are provided by the `@medusajs/medusa/core-flows` package.
|
||||
|
||||
The following links will take you to the reference documentation for [Medusa's Core Workflows](/medusa-workflows-reference).
|
||||
|
||||
<ChildDocs type="item" defaultItemsPerRow={2} />
|
||||
@@ -42,6 +42,12 @@ export const metadata = {
|
||||
|
||||
In this tutorial, you'll learn how to localize your Medusa store's data with Contentful.
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
[Translation Module](../../../commerce-modules/translation/page.mdx) is available since [Medusa v2.12.3](https://github.com/medusajs/medusa/releases/tag/v2.12.3). It allows you to manage translations for product-related resources through Medusa's Store API routes. For general localization needs, consider using the Translation Module instead of integrating a third-party CMS.
|
||||
|
||||
</Note>
|
||||
|
||||
When you install a Medusa application, you get a fully-fledged commerce platform with a Framework for customization. While Medusa provides features essential for internationalization, such as support for multiple [regions](../../../commerce-modules/region/page.mdx) and [currencies](../../../commerce-modules/currency/page.mdx), it doesn't provide content localization.
|
||||
|
||||
However, Medusa's architecture supports the integration of third-party services to provide additional features, such as data localization. One service you can integrate is [Contentful](https://www.contentful.com/), a headless content management system (CMS) that allows you to manage and deliver content across multiple channels.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CodeTabs, CodeTab, Table } from "docs-ui"
|
||||
import { CodeTabs, CodeTab, Table, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Medusa JS SDK`,
|
||||
@@ -651,6 +651,48 @@ The JS SDK appends request-specific headers to authentication headers and header
|
||||
|
||||
---
|
||||
|
||||
## Localization with JS SDK
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
If you support [localization](../storefront-development/localization/page.mdx) in your storefront, you can use the `setLocale` method of the JS SDK.
|
||||
|
||||
The `setLocale` method stores the locale in the JS SDK to pass the it as a `x-medusa-locale` header in all subsequent requests. Also, if your application supports `localStorage`, the method sets the locale in the `medusa_locale` key of the `localStorage`.
|
||||
|
||||
For example, to set the locale to French (France):
|
||||
|
||||
```ts
|
||||
sdk.setLocale("fr-FR")
|
||||
// products content is fetched in French
|
||||
const { products } = await sdk.store.product.list()
|
||||
```
|
||||
|
||||
The `setLocale` method accepts the locale string in the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). All subsequent requests sent using the JS SDK will include the specified locale in the `x-medusa-locale` header.
|
||||
|
||||
In the above example, the product content, such as title and description, is fetched in French and falls back to the original content if translations aren't available.
|
||||
|
||||
You can also retrieve the currently set locale using the `getLocale` method:
|
||||
|
||||
```ts
|
||||
const currentLocale = sdk.getLocale()
|
||||
console.log(currentLocale) // "fr-FR"
|
||||
```
|
||||
|
||||
<Note>
|
||||
|
||||
Learn more about localization and translations in the [Translation Module](../commerce-modules/translation/page.mdx) guide.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Medusa JS SDK Tips
|
||||
|
||||
### Use Tanstack (React) Query in Admin Customizations
|
||||
|
||||
@@ -145,21 +145,27 @@ A multi-regional setup lets merchants manage their inventory through Medusa acro
|
||||
|
||||
## Multi-Lingual Setup
|
||||
|
||||
By integrating a third-party Content Management Systems (CMS), you benefit from rich content features including managing your content in multiple languages. This allows you to cater to customers’ different languages in the regions you serve.
|
||||
Medusa's [Translation Module](../../commerce-modules/translation/page.mdx) allows merchants to manage translations for product-related resources through Medusa's Store API routes.
|
||||
|
||||
To integrate a third-party system, create a custom module whose main service connects to that third-party service. You can also follow the [Contentful integration guide](../../integrations/guides/contentful/page.mdx) to learn how to integrate Contentful and benefit from localization features.
|
||||
This enables merchants to provide a localized experience for customers in different regions by serving translated content in their storefront applications.
|
||||
|
||||
<Note>
|
||||
|
||||
Future versions of the Translation Module will expand translation support to additional resources beyond product-related ones.
|
||||
|
||||
</Note>
|
||||
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/learn/fundamentals/modules",
|
||||
title: "Create a Module",
|
||||
text: "Learn how to create a module in Medusa.",
|
||||
icon: AcademicCapSolid,
|
||||
href: "!user-guide!/settings/translations",
|
||||
title: "Manage Translations",
|
||||
text: "Learn how to manage translations in the Medusa Admin.",
|
||||
icon: UsersSolid,
|
||||
},
|
||||
{
|
||||
href: "/integrations/guides/contentful",
|
||||
title: "Integrate Contentful",
|
||||
text: "Integrate Contentful with Localization Features.",
|
||||
href: "/storefront-development/localization",
|
||||
title: "Localizing Storefronts",
|
||||
text: "Learn how to localize your storefront applications.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
]} />
|
||||
@@ -6,7 +6,7 @@ products:
|
||||
- cart
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
import { CodeTabs, CodeTab, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Create Cart in Storefront`,
|
||||
@@ -132,6 +132,39 @@ However, if the cart is created for a guest customer, then the customer logs in,
|
||||
|
||||
---
|
||||
|
||||
## Set Cart's Locale
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
By default, items in the cart will have their associated product's original content. If your storefront supports [localization](../../localization/page.mdx), you can set the cart's locale to ensure that the item contents are in the customer's preferred language.
|
||||
|
||||
You can set the cart's locale by passing the `locale` request body parameter to the [Create Cart API route](!api!/store#carts_postcarts). For example:
|
||||
|
||||
```ts
|
||||
sdk.store.cart.create({
|
||||
region_id: region.id,
|
||||
// you can also retrieve the locale from sdk.getLocale()
|
||||
locale: "fr-FR",
|
||||
})
|
||||
.then(({ cart }) => {
|
||||
// TODO use the cart...
|
||||
console.log(cart)
|
||||
})
|
||||
```
|
||||
|
||||
When the cart's locale is set, the cart's items will have their content in the specified locale if translations are available.
|
||||
|
||||
You can also [update the cart's locale](../update/page.mdx#set-cart-locale) later if the customer changes their language preference.
|
||||
|
||||
---
|
||||
|
||||
## Store Cart Details in React Context
|
||||
|
||||
If you're using React, it's then recommended to create a context that stores the cart details and make it available to all components in your application, as explained in the [Cart React Context in Storefront](../context/page.mdx) guide.
|
||||
@@ -7,7 +7,7 @@ products:
|
||||
- customer
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
import { CodeTabs, CodeTab, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Update Cart in Storefront`,
|
||||
@@ -86,3 +86,33 @@ Learn more about authenticating customers with the JS SDK in the [Login Customer
|
||||
When using the Fetch API to send the request, either use `credentials: include` if the customer is already authenticated with a cookie session, or pass the Authorization Bearer token in the request's header.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Set Cart's Locale
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
By default, items in the cart will have their associated product's original content. If your storefront supports [localization](../../localization/page.mdx), you can set the cart's locale to ensure that the item contents are in the customer's preferred language.
|
||||
|
||||
You can set the cart's locale by passing the `locale` request body parameter to the [Update Cart API route](!api!/store#carts_postcarts). For example:
|
||||
|
||||
```ts
|
||||
sdk.store.cart.update(cartId, {
|
||||
// you can also retrieve the locale from sdk.getLocale()
|
||||
locale: "fr-FR",
|
||||
})
|
||||
.then(({ cart }) => {
|
||||
// TODO use the cart...
|
||||
console.log(cart)
|
||||
})
|
||||
```
|
||||
|
||||
When the cart's locale is set, existing and new items in the cart will have their content in the specified locale if translations are available.
|
||||
@@ -10,7 +10,7 @@ products:
|
||||
- payment
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
import { CodeTabs, CodeTab, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Checkout Step 5: Complete Cart`,
|
||||
@@ -57,6 +57,23 @@ When the cart completion is successful, it's important to unset the cart ID from
|
||||
|
||||
---
|
||||
|
||||
## Order's Locale after Cart Completion
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
When you complete the cart, items in the order will be in the locale that was set for the cart. This ensures that the customer sees the order details in their preferred language.
|
||||
|
||||
If no locale was set for the cart, then the order's items will be in the original product content.
|
||||
|
||||
---
|
||||
|
||||
## React Example with Default System Payment Provider
|
||||
|
||||
For example, to complete the cart when the default system payment provider is used:
|
||||
|
||||
@@ -6,7 +6,7 @@ products:
|
||||
- order
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab, Table } from "docs-ui"
|
||||
import { CodeTabs, CodeTab, Table, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Order Confirmation in Storefront`,
|
||||
@@ -144,6 +144,21 @@ return (
|
||||
|
||||
In the above example, you show the order items in a list, displaying the item's title, quantity, and unit price formatted with the `formatPrice` function.
|
||||
|
||||
### Locale of Order Items
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
When you complete the cart, items in the order will be in the locale that was set for the cart. This ensures that the customer sees the order details in their preferred language.
|
||||
|
||||
If no locale was set for the cart, then the order's items will be in the original product content.
|
||||
|
||||
---
|
||||
|
||||
## Show Order Totals
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
---
|
||||
tags:
|
||||
- translation
|
||||
- storefront
|
||||
products:
|
||||
- translation
|
||||
---
|
||||
|
||||
import { Prerequisites, CodeTabs, CodeTab } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Storefront Localization`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this guide, you'll learn how to support multiple languages and locales in your storefront.
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
## Overview
|
||||
|
||||
Medusa provides localization features through the [Translation Module](../../commerce-modules/translation/page.mdx). The Translation Module allows you to manage locales and translations for various resources in your store, such as products and categories.
|
||||
|
||||
Admin users can [specify supported locales](!user-guide!/settings/store#manage-store-locales), and [add translations for different resources](!user-guide!/settings/translations) from the Medusa Admin. Then, you can allow customers to choose their locale and show them translated content in your storefront.
|
||||
|
||||
Refer to the [Translation Module documentation](../../commerce-modules/translation/page.mdx) to learn more about translation concepts and features. This guide focuses on how to serve localized content in your storefront.
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Supported Locales
|
||||
|
||||
You can retrieve the list of locales supported by your store using the [List Locales Store API route](!api!/store#locales_getlocales). You can display this list to customers, allowing them to select their preferred language.
|
||||
|
||||
For example:
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn how to install and configure the JS SDK in the [JS SDK documentation](../../js-sdk/page.mdx).
|
||||
|
||||
</Note>
|
||||
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
|
||||
export const highlights = [
|
||||
["18"], ["19"], ["20"], ["21"], ["22"]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { sdk } from "@/lib/sdk"
|
||||
|
||||
export default function Locales() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [locales, setLocales] = useState<
|
||||
HttpTypes.StoreLocale[]
|
||||
>([])
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading) {
|
||||
return
|
||||
}
|
||||
|
||||
sdk.store.locale.list()
|
||||
.then(({ locales: dataLocales }) => {
|
||||
setLocales(dataLocales)
|
||||
setLoading(false)
|
||||
})
|
||||
}, [loading])
|
||||
|
||||
return (
|
||||
<div>
|
||||
{loading && <span>Loading...</span>}
|
||||
{!loading && locales.length === 0 && <span>No locales found.</span>}
|
||||
{!loading && locales.length > 0 && (
|
||||
<ul>
|
||||
{locales.map((locale) => (
|
||||
<li key={locale.code}>{locale.name}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="JS SDK" value="js-sdk">
|
||||
|
||||
```ts
|
||||
sdk.store.locale.list()
|
||||
.then(({ locales: dataLocales }) => {
|
||||
// TODO use locales...
|
||||
console.log(dataLocales)
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
The response has a `locales` field, which is an array of [locales](!api!/store#locales_locale_schema).
|
||||
|
||||
Each locale has a `code` property that follows the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1). For example, `en-US` represents American English, while `fr-FR` represents French (France).
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Translations for Resources
|
||||
|
||||
Currently, you can retrieve translations using the [Store API routes](!api!/store) for product-related resources, such as products, product variants, and categories. Future releases will expand translation support to additional resources.
|
||||
|
||||
By default, Medusa serves the original content of a resource. You can override the locale for a request to get the translated content if available.
|
||||
|
||||
### Set Locale in JS SDK
|
||||
|
||||
The JS SDK has a `setLocale` method that you can use to set the locale for subsequent requests.
|
||||
|
||||
The JS SDK will automatically include the `x-medusa-locale` header in API requests. Also, if your application supports `localStorage`, the method sets the locale in the `medusa_locale` key of the `localStorage`.
|
||||
|
||||
For example, when a customer selects a locale in your storefront, you can set the locale in the JS SDK:
|
||||
|
||||
```ts
|
||||
sdk.setLocale("fr-FR")
|
||||
// products content is fetched in French
|
||||
const { products } = await sdk.store.product.list()
|
||||
```
|
||||
|
||||
In the above example, you set the locale to French using the `setLocale` method. It accepts the locale string in the [IETF BCP 47 standard](https://gist.github.com/typpo/b2b828a35e683b9bf8db91b5404f1bd1).
|
||||
|
||||
When you fetch the products, their content, such as title and description, is in French and falls back to the original content if translations aren't available.
|
||||
|
||||
You can also retrieve the currently set locale using the `getLocale` method:
|
||||
|
||||
```ts
|
||||
const currentLocale = sdk.getLocale()
|
||||
console.log(currentLocale) // "fr-FR"
|
||||
```
|
||||
|
||||
### Set Locale without JS SDK
|
||||
|
||||
If you're sending requests to the Store API without using the JS SDK, you can set the locale using either the `locale` query parameter or the `x-medusa-locale` header.
|
||||
|
||||
<CodeTabs group="set-locale">
|
||||
<CodeTab label="Using Query Parameter" value="query-param">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:9000/store/products?locale=fr-FR" \
|
||||
-H 'x-publishable-api-key: {your_publishable_api_key}'
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="Using Header" value="header">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:9000/store/products" \
|
||||
-H 'x-publishable-api-key: {your_publishable_api_key}' \
|
||||
-H "x-medusa-locale: fr-FR"
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
Learn more in the [Store API reference](!api!/store#localization).
|
||||
|
||||
### Set Locale in Server Environments
|
||||
|
||||
If you're making Store API requests from a server environment (such as server components or server actions in Next.js), you can use cookies to persist the selected locale across requests.
|
||||
|
||||
When a customer selects a locale in your storefront, set a cookie (for example, `_medusa_locale`) with the selected locale value:
|
||||
|
||||
```ts
|
||||
import { cookies } from "next/headers"
|
||||
|
||||
export const setLocale = async (locale: string) => {
|
||||
const cookies_ = await cookies()
|
||||
cookies_.set("_medusa_locale", locale, {
|
||||
maxAge: 60 * 60 * 24 * 7,
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
Then, create a utility that returns the locale from the cookie as a `x-medusa-locale` header:
|
||||
|
||||
```ts
|
||||
import { cookies } from "next/headers"
|
||||
|
||||
export const getLocaleHeader = async () => {
|
||||
try {
|
||||
const cookies_ = await cookies()
|
||||
const locale = cookies_.get("_medusa_locale")?.value
|
||||
|
||||
return { "x-medusa-locale": locale }
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Finally, use the utility to set the `x-medusa-locale` header in your Store API requests:
|
||||
|
||||
```ts
|
||||
import { getLocaleHeader } from "@/lib/locale"
|
||||
|
||||
export async function listProducts() {
|
||||
const headers = {
|
||||
...(await getLocaleHeader()),
|
||||
}
|
||||
|
||||
return sdk.store.product.list({}, { headers })
|
||||
}
|
||||
```
|
||||
|
||||
### Retrieve Translated Products
|
||||
|
||||
When you pass the locale while fetching products, their content will be in the specified locale if translations are available. Learn more in the [List Products](../products/list/page.mdx) guide.
|
||||
|
||||
### Set Cart's Locale
|
||||
|
||||
When creating a cart, you should set the cart's locale to ensure that item contents are in the correct language. You can also update the cart's locale later if the customer changes their language preference.
|
||||
|
||||
Learn more in the [Create Cart](../cart/create/page.mdx) and [Update Cart](../cart/update/page.mdx) guides.
|
||||
@@ -6,7 +6,7 @@ products:
|
||||
- product
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
import { CodeTabs, CodeTab, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Show Products in Storefront`,
|
||||
@@ -225,3 +225,82 @@ sdk.store.product.list({
|
||||
```
|
||||
|
||||
The result will be products sorted by title in descending order.
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Translations for Products
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
By default, Medusa returns the product's original content (such as title and description).
|
||||
|
||||
If you support [localization](../../localization/page.mdx) in your storefront, you can set the locale to retrieve product information with based on the customer's preferred language.
|
||||
|
||||
You can set the locale using one of the following methods:
|
||||
|
||||
- Use the JS SDK's `setLocale` method. The JS SDK will automatically include the locale in subsequent requests.
|
||||
- Pass the `locale` query parameter to the [List Products API route](!api!/store#products_getproducts).
|
||||
- Set the `x-medusa-locale` header in the API request to the [List Products API route](!api!/store#products_getproducts).
|
||||
|
||||
For example:
|
||||
|
||||
<CodeTabs group="localized-products">
|
||||
<CodeTab label="Using JS SDK" value="js-sdk">
|
||||
|
||||
```ts
|
||||
sdk.setLocale("fr-FR")
|
||||
sdk.store.product.list()
|
||||
.then(({ products: dataProducts, count }) => {
|
||||
// TODO set products...
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="Using Query Parameter" value="query-param">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:9000/store/products?locale=fr-FR" \
|
||||
-H 'x-publishable-api-key: {your_publishable_api_key}'
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="Using Header" value="header">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:9000/store/products" \
|
||||
-H 'x-publishable-api-key: {your_publishable_api_key}' \
|
||||
-H "x-medusa-locale: fr-FR"
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
The returned products will have the same structure as described in the [products schema](!api!/store#products_product_schema), but their fields like `title` and `description` will be in the specified locale:
|
||||
|
||||
```json
|
||||
{
|
||||
"products": [
|
||||
{
|
||||
"id": "prod_123",
|
||||
"title": "Chemise Exemple",
|
||||
"description": "Ceci est une description en français.",
|
||||
// other product fields...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
If translations aren't available for the selected locale, or no locale is selected, the product's original content is returned.
|
||||
|
||||
### Retrieve in Server-Side Environments
|
||||
|
||||
For server-side environments (such as server components or server actions in Next.js), you can set the locale using cookies to persist the selected locale across requests.
|
||||
|
||||
Learn more in the [Storefront Localization](../../localization/page.mdx#set-locale-in-server-environments) guide.
|
||||
@@ -6,7 +6,7 @@ products:
|
||||
- product
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
import { CodeTabs, CodeTab, Prerequisites } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Retrieve a Product in Storefront`,
|
||||
@@ -70,7 +70,7 @@ export const highlights = [
|
||||
setProduct(dataProduct)
|
||||
setLoading(false)
|
||||
})
|
||||
}, [loading])
|
||||
}, [loading, id])
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -93,7 +93,7 @@ export const highlights = [
|
||||
</ul>
|
||||
)}
|
||||
{product.images?.map((image) => (
|
||||
<img src={image.url} key={image.id} />
|
||||
<img src={image.url} alt={product.title} key={image.id} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
@@ -132,7 +132,7 @@ Refer to the [Features in Product Details Page](#features-in-product-details-pag
|
||||
|
||||
## Retrieve a Product by Handle
|
||||
|
||||
To retrieve a product by its handle, send a request to the [List Products API route](!api!/store#products_getproducts) passing it the `handle` query parameter:
|
||||
To retrieve a product by its handle, send a request to the [List Products API route](!api!/store#products_getproducts) passing the `handle` query parameter:
|
||||
|
||||
<CodeTabs group="store-request">
|
||||
<CodeTab label="React" value="react">
|
||||
@@ -174,7 +174,7 @@ export const handleHighlights = [
|
||||
}
|
||||
setLoading(false)
|
||||
})
|
||||
}, [loading])
|
||||
}, [loading, handle])
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -190,7 +190,7 @@ export const handleHighlights = [
|
||||
{option.title}
|
||||
<ul>
|
||||
{option.values?.map((optionValue) => (
|
||||
<li id={optionValue.id}>{optionValue.value}</li>
|
||||
<li key={optionValue.id}>{optionValue.value}</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
@@ -198,7 +198,7 @@ export const handleHighlights = [
|
||||
</ul>
|
||||
)}
|
||||
{product.images?.map((image) => (
|
||||
<img src={image.url} key={image.id} />
|
||||
<img src={image.url} alt={product.title} key={image.id} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
@@ -220,7 +220,7 @@ export const handleFetchHighlights = [
|
||||
})
|
||||
.then(({ products }) => {
|
||||
if (!products.length) {
|
||||
// product with the specified handle doesn't exist
|
||||
// Product not found with the specified handle
|
||||
return
|
||||
}
|
||||
// use the product...
|
||||
@@ -233,11 +233,87 @@ export const handleFetchHighlights = [
|
||||
|
||||
---
|
||||
|
||||
## Retrieve Translated Product
|
||||
|
||||
<Prerequisites
|
||||
items={[
|
||||
{
|
||||
text: "Translation Module Configured",
|
||||
link: "/commerce-modules/translation#configure-translation-module",
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
By default, Medusa returns the product's original content (such as title and description).
|
||||
|
||||
If you support [localization](../../localization/page.mdx) in your storefront, you can set the locale to retrieve product information based on the customer's preferred language.
|
||||
|
||||
You can set the locale using one of the following methods:
|
||||
|
||||
- Use the JS SDK's `setLocale` method. The JS SDK will automatically include the locale in subsequent requests.
|
||||
- Pass the `locale` query parameter to the [List Products API route](!api!/store#products_getproducts).
|
||||
- Set the `x-medusa-locale` header in the API request to the [List Products API route](!api!/store#products_getproducts).
|
||||
|
||||
For example:
|
||||
|
||||
<CodeTabs group="localized-products">
|
||||
<CodeTab label="Using JS SDK" value="js-sdk">
|
||||
|
||||
```ts
|
||||
sdk.setLocale("fr-FR")
|
||||
sdk.store.product.retrieve(id)
|
||||
.then(({ product }) => {
|
||||
// TODO use the product...
|
||||
console.log(product)
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="Using Query Parameter" value="query-param">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:9000/store/products/prod_123?locale=fr-FR" \
|
||||
-H 'x-publishable-api-key: {your_publishable_api_key}'
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="Using Header" value="header">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:9000/store/products/prod_123" \
|
||||
-H 'x-publishable-api-key: {your_publishable_api_key}' \
|
||||
-H "x-medusa-locale: fr-FR"
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
The returned product will have the same structure as described in the [products schema](!api!/store#products_product_schema), but fields such as `title` and `description` will be in the specified locale:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "prod_123",
|
||||
"title": "Chemise Exemple",
|
||||
"description": "Ceci est une description en français.",
|
||||
// other product fields...
|
||||
}
|
||||
```
|
||||
|
||||
If translations aren't available for the selected locale, or no locale is selected, the product's original content is returned.
|
||||
|
||||
### Retrieve in Server-Side Environments
|
||||
|
||||
For server-side environments (such as server components or server actions in Next.js), you can set the locale using cookies to persist the selected locale across requests.
|
||||
|
||||
Learn more in the [Storefront Localization](../../localization/page.mdx#set-locale-in-server-environments) guide.
|
||||
|
||||
---
|
||||
|
||||
## Features in Product Details Page
|
||||
|
||||
In a product's details page, you want to allow the customer to choose a variant, see its price, and add it to the cart.
|
||||
On a product details page, you typically want to allow customers to choose a variant, see its price, and add it to the cart.
|
||||
|
||||
The following guides will help you add these features into your storefront:
|
||||
The following guides will help you add these features to your storefront:
|
||||
|
||||
- [Select a variant](../variants/page.mdx)
|
||||
- [Show variant price](../price/page.mdx)
|
||||
|
||||
Reference in new issue
Block a user