feat(translation): Improve translation alert in empty languages state (#14464)

**What**
When there is no languages configured, the translation page will show a proper alert on the page that is more visible and actionable
This commit is contained in:
Adrien de Peretti
2026-01-06 16:04:23 +01:00
committed by GitHub
parent b300a93345
commit d54589751c
7 changed files with 71 additions and 38 deletions

View File

@@ -9444,9 +9444,17 @@
},
"noLocalesTip": {
"type": "string"
},
"noLocalesTipConfigureAction": {
"type": "string"
}
},
"required": ["heading", "subtitle", "noLocalesTip"]
"required": [
"heading",
"subtitle",
"noLocalesTip",
"noLocalesTipConfigureAction"
]
},
"completion": {
"type": "object",

View File

@@ -2540,7 +2540,8 @@
"activeLocales": {
"heading": "Languages",
"subtitle": "Activated translations",
"noLocalesTip": "Configure at least one locale to start translating your data"
"noLocalesTip": "Configure at least one language to start translating your data",
"noLocalesTipConfigureAction": "Configure"
},
"completion": {
"heading": "Translated fields",

View File

@@ -2480,7 +2480,8 @@
"activeLocales": {
"heading": "Idiomas",
"subtitle": "Traducciones activas",
"noLocalesTip": "Configura al menos un idioma para empezar a traducir tu información"
"noLocalesTip": "Configura al menos un lenguaje para empezar a traducir tu información",
"noLocalesTipConfigureAction": "Configurar"
},
"completion": {
"heading": "Textos traducidos",

View File

@@ -1,17 +1,10 @@
import { PencilSquare, Language } from "@medusajs/icons"
import {
Container,
Heading,
IconButton,
InlineTip,
Text,
Tooltip,
} from "@medusajs/ui"
import { Language } from "@medusajs/icons"
import { HttpTypes } from "@medusajs/types"
import { Container, Heading, Text, Tooltip } from "@medusajs/ui"
import { useCallback, useState } from "react"
import { useTranslation } from "react-i18next"
import { IconAvatar } from "../../../../../components/common/icon-avatar"
import { HttpTypes } from "@medusajs/types"
import { useCallback, useState } from "react"
import { useNavigate } from "react-router-dom"
import { LinkButton } from "../../../../../components/common/link-button"
type ActiveLocalesSectionProps = {
locales: HttpTypes.AdminLocale[]
@@ -21,13 +14,8 @@ export const ActiveLocalesSection = ({
locales,
}: ActiveLocalesSectionProps) => {
const { t } = useTranslation()
const navigate = useNavigate()
const [isHovered, setIsHovered] = useState(false)
const handleManageLocales = useCallback(() => {
navigate("/settings/translations/add-locales")
}, [navigate])
const renderLocales = useCallback(() => {
const maxLocalesToDetail = 2
if (locales.length <= maxLocalesToDetail) {
@@ -46,18 +34,26 @@ export const ActiveLocalesSection = ({
<Container className="flex flex-col p-0">
<div className="flex items-center justify-between px-6 py-4">
<Heading level="h2">{t("translations.activeLocales.heading")}</Heading>
<IconButton variant="transparent" onClick={handleManageLocales}>
<PencilSquare></PencilSquare>
</IconButton>
<LinkButton
variant="interactive"
className="text-ui-fg-subtle hover:text-ui-fg-subtle-hover"
to="/settings/translations/add-locales"
>
{t("translations.activeLocales.noLocalesTipConfigureAction")}
</LinkButton>
</div>
<div className="px-1 pb-1">
{hasLocales ? (
{hasLocales && (
<div className="px-1 pb-1">
<Tooltip
open={isHovered}
content={
<div className="flex flex-col gap-y-1 p-1">
{locales.map((locale) => (
<Text key={locale.code} size="small" weight="plus">
<Text
key={locale.code}
size="base"
className="text-ui-fg-subtle"
>
{locale.name}
</Text>
))}
@@ -82,12 +78,8 @@ export const ActiveLocalesSection = ({
</div>
</Container>
</Tooltip>
) : (
<InlineTip label="Tip">
{t("translations.activeLocales.noLocalesTip")}
</InlineTip>
)}
</div>
</div>
)}
</Container>
)
}

View File

@@ -1,6 +1,9 @@
import { Container, Heading, Text } from "@medusajs/ui"
import { TwoColumnPage } from "../../../components/layout/pages"
import { Alert, Button, Container, Heading, Text } from "@medusajs/ui"
import { useCallback, useMemo } from "react"
import { useTranslation } from "react-i18next"
import { useNavigate } from "react-router-dom"
import { TwoColumnPageSkeleton } from "../../../components/common/skeleton"
import { TwoColumnPage } from "../../../components/layout/pages"
import {
useStore,
useTranslationSettings,
@@ -9,8 +12,6 @@ import {
import { ActiveLocalesSection } from "./components/active-locales-section/active-locales-section"
import { TranslationListSection } from "./components/translation-list-section/translation-list-section"
import { TranslationsCompletionSection } from "./components/translations-completion-section/translations-completion-section"
import { TwoColumnPageSkeleton } from "../../../components/common/skeleton"
import { useMemo } from "react"
export type TranslatableEntity = {
label: string
@@ -22,6 +23,7 @@ export type TranslatableEntity = {
export const TranslationList = () => {
const { t } = useTranslation()
const navigate = useNavigate()
const { store, isPending, isError, error } = useStore()
const {
@@ -88,6 +90,10 @@ export const TranslationList = () => {
)
}, [translatable_fields, statistics])
const handleManageLocales = useCallback(() => {
navigate("/settings/translations/add-locales")
}, [navigate])
const isReady =
!!store &&
!isPending &&
@@ -115,6 +121,25 @@ export const TranslationList = () => {
{t("translations.subtitle")}
</Text>
</Container>
{!hasLocales && (
<Alert
variant="info"
className="bg-ui-bg-base flex items-center px-6 py-4"
>
<div className="flex items-center justify-between gap-x-2">
<p>{t("translations.activeLocales.noLocalesTip")}.</p>
<Button
onClick={handleManageLocales}
size="small"
variant="secondary"
>
{t("translations.activeLocales.noLocalesTipConfigureAction")}
</Button>
</div>
</Alert>
)}
<TranslationListSection
entities={translatableEntities}
hasLocales={hasLocales}

View File

@@ -60,7 +60,7 @@ export const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
<div
ref={ref}
className={clx(
"bg-ui-bg-subtle text-pretty txt-compact-small grid items-start gap-x-2 rounded-lg border p-3",
"bg-ui-bg-subtle txt-compact-small grid items-start gap-x-2 text-pretty rounded-lg border p-3",
{
"grid-cols-[20px_1fr]": !dismissible,
"grid-cols-[20px_1fr_20px]": dismissible,
@@ -77,7 +77,7 @@ export const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
"text-ui-tag-neutral-icon": variant === "info",
})}
/>
<div>{children}</div>
<div className="w-full">{children}</div>
{dismissible && (
<IconButton
size="2xsmall"