diff --git a/www/apps/book/app/learn/build/page.mdx b/www/apps/book/app/learn/build/page.mdx
index f335559aec..387035f362 100644
--- a/www/apps/book/app/learn/build/page.mdx
+++ b/www/apps/book/app/learn/build/page.mdx
@@ -86,8 +86,8 @@ module.exports = defineConfig({
cookieOptions: {
sameSite: "lax",
secure: false,
- }
- }
+ },
+ },
})
```
diff --git a/www/apps/book/app/learn/fundamentals/admin/translations/page.mdx b/www/apps/book/app/learn/fundamentals/admin/translations/page.mdx
new file mode 100644
index 0000000000..aba1424d4d
--- /dev/null
+++ b/www/apps/book/app/learn/fundamentals/admin/translations/page.mdx
@@ -0,0 +1,464 @@
+import { CodeTabs, CodeTab } from "docs-ui"
+
+export const metadata = {
+ title: `${pageNumber} Translate Admin Customizations`,
+}
+
+# {metadata.title}
+
+In this chapter, you'll learn how to add translations to your Medusa Admin widgets and UI routes.
+
+
+
+Translations for admin customizations are available from [Medusa v2.11.1](https://github.com/medusajs/medusa/releases/tag/v2.11.1).
+
+
+
+## Translations in the Medusa Admin
+
+The Medusa Admin dashboard supports [multiple languages](!user-guide!/tips/languages) for its interface. Medusa uses [react-i18next](https://react.i18next.com/) to manage translations in the admin dashboard.
+
+
+
+Medusa Admin translations apply to the interface only. Medusa doesn't support translating store content, such as product names or descriptions. To implement localization for store content, [integrate a CMS](!resources!/integrations#cms).
+
+
+
+When you create [Widgets](../widgets/page.mdx) or [UI Routes](../ui-routes/page.mdx) to customize the Medusa Admin, you can provide translations for the text content in your customizations, allowing users to view your customizations in their preferred language.
+
+You can add translations for your admin customizations within your Medusa project or as part of a plugin.
+
+---
+
+## How to Add Translations to Admin Customizations
+
+### Step 1: Create Translation Files
+
+Translation files are JSON files containing key-value pairs, where the key identifies a text string and the value is the translated text or a nested object of translations.
+
+For example, to add English translations, create the file `src/admin/i18n/json/en.json` with the following content:
+
+
+
+English is the default language for Medusa Admin, so it's recommended to always include an English translation file.
+
+
+
+
+
+```json title="src/admin/i18n/json/en.json"
+{
+ "brands": {
+ "title": "Brands",
+ "description": "Manage your product brands"
+ },
+ "done": "Done"
+}
+```
+
+You can create additional translation files for other languages by following the same structure. For example, for Spanish, create `src/admin/i18n/json/es.json`:
+
+
+
+```json title="src/admin/i18n/json/es.json"
+{
+ "brands": {
+ "title": "Marcas",
+ "description": "Gestiona las marcas de tus productos"
+ },
+ "done": "Hecho"
+}
+```
+
+### Step 2: Load Translation Files
+
+Next, to load the translation files, create the file `src/admin/i18n/index.ts` with the following content:
+
+
+
+```ts title="src/admin/i18n/index.ts"
+import en from "./json/en.json" with { type: "json" }
+import es from "./json/es.json" with { type: "json" }
+
+export default {
+ en: {
+ translation: en,
+ },
+ es: {
+ translation: es,
+ },
+}
+```
+
+The `src/admin/i18n/index.ts` file imports the JSON translation files. You must include the `with { type: "json" }` directive to ensure the JSON files load correctly.
+
+The file exports an object that maps two-character language codes (like `en` and `es`) to their respective translation data.
+
+### Step 3: Use Translations in Admin Customizations
+
+Finally, you can use the translations in your admin customizations by using the `useTranslation` hook from `react-i18next`.
+
+
+
+The `react-i18next` package is already included in the Medusa Admin's dependencies, so you don't need to install it separately. However, `pnpm` users may need to install it manually due to package resolution issues.
+
+
+
+For example, create the file `src/admin/widgets/product-brand.tsx` with the following content:
+
+export const translationHighlights = [
+ ["3", "useTranslation", "Import `useTranslation` hook."],
+ ["6", "t", "Access translation function."],
+ ["10", "t", "Get translated text using keys."]
+]
+
+```tsx title="src/admin/widgets/product-brand.tsx" highlights={translationHighlights}
+import { defineWidgetConfig } from "@medusajs/admin-sdk"
+import { Button, Container, Heading } from "@medusajs/ui"
+import { useTranslation } from "react-i18next"
+
+const ProductWidget = () => {
+ const { t } = useTranslation()
+ return (
+
+
+ {t("brands.title")}
+
{t("brands.description")}
+
+
+
+
+
+ )
+}
+
+export const config = defineWidgetConfig({
+ zone: "product.details.before",
+})
+
+export default ProductWidget
+```
+
+In the above example, you retrieve the `t` function from the `useTranslation` hook. You then use this function to get the translated text by providing the appropriate keys defined in your translation JSON files.
+
+Nested keys are joined using dot notation. For example, `brands.title` refers to the `title` key inside the `brands` object in the translation files.
+
+### Test Translations
+
+To test the translations, start the Medusa application with the following command:
+
+```bash npm2yarn
+npm run dev
+```
+
+Then, go to a product details page in the Medusa Admin dashboard. If your default language is set to English, you'll see the widget displaying text in English.
+
+Next, [change the admin language](!user-guide!/settings/profile#edit-profile-details) to Spanish. The widget will now display the text in Spanish.
+
+---
+
+## How Translations are Loaded
+
+When you load the translations with the `translation` key in `src/admin/i18n/index.ts`, your custom Medusa Admin translations are merged with the default Medusa Admin translations:
+
+- Translation keys in your custom translations override the default Medusa Admin translations.
+- The default Medusa Admin translations are used as a fallback when a key is not defined in your custom translations.
+
+For example, consider the following widget and translation file:
+
+
+
+
+```tsx title="src/admin/widgets/product-brand.tsx"
+import { defineWidgetConfig } from "@medusajs/admin-sdk"
+import { Button, Container, Heading } from "@medusajs/ui"
+import { useTranslation } from "react-i18next"
+
+const ProductWidget = () => {
+ const { t } = useTranslation()
+ return (
+
+
+
+ )
+}
+
+export const config = defineWidgetConfig({
+ zone: "product.details.before",
+})
+
+export default ProductWidget
+```
+
+
+
+
+```json title="src/admin/i18n/json/en.json"
+{
+ "brands": {
+ "title": "Custom Brands Title"
+ },
+ "actions": {
+ "save": "Custom Save"
+ }
+}
+```
+
+
+
+
+```ts title="src/admin/i18n/index.ts"
+import en from "./json/en.json" with { type: "json" }
+
+export default {
+ en: {
+ translation: en,
+ },
+ // other languages...
+}
+```
+
+
+
+
+The widget will render the following for each translation key:
+
+- `brands.title`: Defined in your custom translation file, so it outputs `Custom Brands Title`.
+- `brands.description`: Not defined in your custom translation file or the default Medusa Admin translations, so it outputs the key itself: `brands.description`.
+- `actions.save`: Defined in your custom translation file, so it outputs `Custom Save`.
+- `actions.delete`: Not defined in your custom translation file, so it falls back to the default Medusa Admin translation and outputs `Delete`.
+
+### Custom Translation Namespaces
+
+To avoid potential key conflicts between your custom translations and the default Medusa Admin translations, you can use custom namespaces. This is particularly useful when developing plugins that add admin customizations, as it prevents naming collisions with other plugins or the default Medusa Admin translations.
+
+To add translations under a custom namespace, change the `[language].translation` key in the `src/admin/i18n/index.ts` file to your desired namespace:
+
+export const namespacesHighlights = [
+ ["6", "brands", "Use `brands` as custom namespace."],
+ ["9", "brands", "Use `brands` as custom namespace."]
+]
+
+```ts title="src/admin/i18n/index.ts" highlights={namespacesHighlights}
+import en from "./json/en.json" with { type: "json" }
+import es from "./json/es.json" with { type: "json" }
+
+export default {
+ en: {
+ brands: en,
+ },
+ es: {
+ brands: es,
+ },
+}
+```
+
+The translation files will now be loaded under the `brands` namespace.
+
+Then, in your admin customizations, specify the namespace when using the `useTranslation` hook:
+
+```tsx title="src/admin/widgets/product-brand.tsx" highlights={[["7"]]}
+import { defineWidgetConfig } from "@medusajs/admin-sdk"
+import { Button, Container, Heading } from "@medusajs/ui"
+import { useTranslation } from "react-i18next"
+
+// The widget
+const ProductWidget = () => {
+ const { t } = useTranslation("brands")
+ return (
+
+