Merge branch 'add/translationCell' into 'develop'

feat: ✨ add translation cell for fallback value

See merge request ldc-web/projets/ldc!102
This commit is contained in:
karl.muller 2025-12-23 14:33:59 +00:00
commit ecdbb015d6
20 changed files with 197 additions and 94 deletions

View file

@ -6,6 +6,7 @@ import { AppEnv, DocumentModel, Resource, TranslationField } from "../types/glob
import { Row } from "@tanstack/react-table";
import { usePage } from "@inertiajs/react";
import { Views } from "@/lib/utils";
import { renderTranslationCell } from "@/lib/translationCellFallback";
interface Props {
documents: Resource
@ -25,9 +26,9 @@ const AssociatedDocumentList = (props: Props) => {
/>
),
cell: ({ row }: { row: Row<DocumentModel> }) => {
return (row.getValue("name") as TranslationField)[appEnv.locale] ? (
(row.getValue("name") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("name")
)
},
},
{

View file

@ -9,6 +9,7 @@ import { Views } from "@/lib/utils";
import { useFormatedDate } from "@/hooks/use-formated-value";
import { Badge } from "@/components/ui/badge";
import NewsStatusBadge from "./NewsStatusBadge";
import { renderTranslationCell } from "@/lib/translationCellFallback";
interface Props {
news: Resource
@ -29,9 +30,9 @@ const AssociatedNewsList = (props: Props) => {
/>
),
cell: ({ row }: { row: Row<NewsModel> }) => {
return (row.getValue("title") as TranslationField)[appEnv.locale] ? (
(row.getValue("title") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("title")
)
},
},
{

View file

@ -24,6 +24,7 @@ import {
} from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Index({
companyActivityModels,
@ -61,9 +62,9 @@ export default function Index({
/>
),
cell: ({ row }: { row: Row<CompanyActivityModel> }) => {
return (row.getValue("name") as TranslationField)[appEnv.locale] ? (
(row.getValue("name") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("name")
)
},
},
{
@ -98,9 +99,8 @@ export default function Index({
cell: ({ row }: { row: Row<CompanyActivityModel> }) => (
<Badge
variant="outline"
className={`border-0 ${
row.getValue("published") ? "bg-green-200 dark:bg-green-900" : "bg-red-200 dark:bg-red-900"
}`}
className={`border-0 ${row.getValue("published") ? "bg-green-200 dark:bg-green-900" : "bg-red-200 dark:bg-red-900"
}`}
>
{row.getValue("published") ? (
<CheckIcon size={15} className="mr-1" />
@ -114,7 +114,7 @@ export default function Index({
];
const transModel = useTrans(`models.classes.${str(modelName).singular().value()}`, { choice: 2 });
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel }})
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel } })
const transTitle = str(isArchiveRoute ? transArchiveTitle : transModel).ucFirst().value();
const beforeNode = () => {

View file

@ -20,11 +20,11 @@ import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { ArrowLeftIcon, CheckIcon, XIcon } from "lucide-react";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Show({ data, modelName }: { data: SingleResource, modelName: string }) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
};
const { viewAny } = auth.policies.companyActivities;
const companyActivityModel = data.data as CompanyActivityModel;
@ -41,9 +41,11 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
{
accessorKey: "name",
header: str(useTrans("validation.attributes.name")).ucFirst().value(),
cell: ({ value }: { value: TranslationField }) => value[appEnv.locale]
? value[appEnv.locale]
: (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>),
cell: ({ value }: { value: TranslationField }) => {
return renderTranslationCell(
value
)
}
},
{
accessorKey: "color",
@ -63,9 +65,8 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
cell: ({ value }: { value: boolean }) => (
<Badge
variant="outline"
className={`border-0 ${
value ? "bg-green-200 dark:bg-green-900" : "bg-red-200 dark:bg-red-900"
}`}
className={`border-0 ${value ? "bg-green-200 dark:bg-green-900" : "bg-red-200 dark:bg-red-900"
}`}
>
{value ? (
<CheckIcon size={15} className="mr-1" />
@ -107,7 +108,7 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
return (
<AuthenticatedLayout
title={useTrans("crud.helpers.visualization_model", {
params: { model: useTrans("models.classes.company-activity", { choice: 1 })},
params: { model: useTrans("models.classes.company-activity", { choice: 1 }) },
})}
beforeNode={beforeNode()}
>

View file

@ -23,6 +23,7 @@ import {
} from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Index({
companySectorModels,
@ -60,9 +61,9 @@ export default function Index({
/>
),
cell: ({ row }: { row: Row<CompanySectorModel> }) => {
return (row.getValue("name") as TranslationField)[appEnv.locale] ? (
(row.getValue("name") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("name")
)
},
},
{
@ -76,9 +77,8 @@ export default function Index({
cell: ({ row }: { row: Row<CompanySectorModel> }) => (
<Badge
variant="outline"
className={`border-0 ${
row.getValue("published") ? "bg-green-200 dark:bg-green-900" : "bg-red-200 dark:bg-red-900"
}`}
className={`border-0 ${row.getValue("published") ? "bg-green-200 dark:bg-green-900" : "bg-red-200 dark:bg-red-900"
}`}
>
{row.getValue("published") ? (
<CheckIcon size={15} className="mr-1" />
@ -92,7 +92,7 @@ export default function Index({
];
const transModel = useTrans(`models.classes.${str(modelName).singular().value()}`, { choice: 2 });
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel }})
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel } })
const transTitle = str(isArchiveRoute ? transArchiveTitle : transModel).ucFirst().value();
const beforeNode = () => {

View file

@ -12,7 +12,6 @@ import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithT
import { Views } from "@/lib/utils";
import { useFormatedDate } from "@/hooks/use-formated-value";
import {
AppEnv,
AuthProp,
CompanySectorModel,
SingleResource,
@ -20,11 +19,11 @@ import {
} from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Show({ data, modelName }: { data: SingleResource, modelName: string }) {
const { auth, appEnv } = usePage().props as unknown as {
const { auth } = usePage().props as unknown as {
auth: AuthProp;
appEnv: AppEnv;
};
const { viewAny } = auth.policies.companySectors;
const companySectorModel = data.data as CompanySectorModel;
@ -41,9 +40,11 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
{
accessorKey: "name",
header: str(useTrans("validation.attributes.name")).ucFirst().value(),
cell: ({ value }: { value: TranslationField }) => value[appEnv.locale]
? value[appEnv.locale]
: (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>),
cell: ({ value }: { value: TranslationField }) => {
return renderTranslationCell(
value
)
}
},
{
accessorKey: "published",
@ -51,9 +52,8 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
cell: ({ value }: { value: boolean }) => (
<Badge
variant="outline"
className={`border-0 ${
value ? "bg-green-200 dark:bg-green-900" : "bg-red-200 dark:bg-red-900"
}`}
className={`border-0 ${value ? "bg-green-200 dark:bg-green-900" : "bg-red-200 dark:bg-red-900"
}`}
>
{value ? (
<CheckIcon size={15} className="mr-1" />

View file

@ -22,6 +22,7 @@ import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { Row } from "@tanstack/react-table";
import { Plus } from "lucide-react";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Index({
documentCategoryModel,
@ -54,9 +55,9 @@ export default function Index({
/>
),
cell: ({ row }: { row: Row<DocumentCategoryModel> }) => {
return (row.getValue("name") as TranslationField)[appEnv.locale] ? (
(row.getValue("name") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("name")
)
},
},
{

View file

@ -22,6 +22,7 @@ import useTrans from "@/hooks/use-translations";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { ArrowLeft } from "lucide-react";
import AssociatedDocumentList from "@/back/Components/AssociatedDocumentList";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Show({ data, modelName, documents }: { data: SingleResource, modelName: string, documents: Resource }) {
@ -43,9 +44,11 @@ export default function Show({ data, modelName, documents }: { data: SingleResou
{
accessorKey: "name",
header: str(useTrans("validation.attributes.name")).ucFirst().value(),
cell: ({ value }: { value: TranslationField }) => value[appEnv.locale]
? value[appEnv.locale]
: (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>),
cell: ({ value }: { value: TranslationField }) => {
return renderTranslationCell(
value
)
}
},
{
accessorKey: "slug",

View file

@ -22,6 +22,7 @@ import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { Row } from "@tanstack/react-table";
import { Plus } from "lucide-react";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Index({
documentTagModel,
@ -54,9 +55,9 @@ export default function Index({
/>
),
cell: ({ row }: { row: Row<DocumentTagModel> }) => {
return (row.getValue("name") as TranslationField)[appEnv.locale] ? (
(row.getValue("name") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("name")
)
},
},
{

View file

@ -22,6 +22,7 @@ import useTrans from "@/hooks/use-translations";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { ArrowLeft } from "lucide-react";
import AssociatedDocumentList from "@/back/Components/AssociatedDocumentList";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Show({ data, modelName, documents }: { data: SingleResource, modelName: string, documents: Resource }) {
const { auth, appEnv } = usePage().props as unknown as {
@ -42,9 +43,11 @@ export default function Show({ data, modelName, documents }: { data: SingleResou
{
accessorKey: "name",
header: str(useTrans("validation.attributes.name")).ucFirst().value(),
cell: ({ value }: { value: TranslationField }) => value[appEnv.locale]
? value[appEnv.locale]
: (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>),
cell: ({ value }: { value: TranslationField }) => {
return renderTranslationCell(
value
)
}
},
{
accessorKey: "slug",

View file

@ -41,6 +41,8 @@ import {
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import DynamicStatusBadge from "@/back/Components/DynamicPages/DynamicStatusBadge";
import { ReactNode } from "react";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Index({
dynamicPageModels,
@ -68,6 +70,7 @@ export default function Index({
Views.DUPLICATION,
Views.ARCHIVATION,
];
const columns = [
{
accessorKey: "title",
@ -78,10 +81,11 @@ export default function Index({
/>
),
cell: ({ row }: { row: Row<DynamicPageModel> }) => {
return (row.getValue("title") as TranslationField)[appEnv.locale] ? (
(row.getValue("title") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("title") as TranslationField
);
}
},
{
accessorKey: "parent_page",
@ -139,10 +143,10 @@ export default function Index({
accessorKey: "config",
header: ({ column }: { column: { id: string } }) => (
<DataTableFilterButton
label={str(useTrans(`validation.custom.${column.id}`))
.ucFirst()
.value()}
field={column.id}
label={str(useTrans(`validation.custom.${column.id}`))
.ucFirst()
.value()}
field={column.id}
/>
),
cell: ({ row }: { row: Row<DynamicPageModel> }) => {
@ -181,9 +185,9 @@ export default function Index({
return value;
}
return (
<p className="text-muted-foreground italic m-0">
{useTrans("back.table_not_known")}
</p>
<p className="text-muted-foreground italic m-0">
{useTrans("back.table_not_known")}
</p>
);
},
},
@ -191,10 +195,10 @@ export default function Index({
accessorKey: "status",
header: ({ column }: { column: { id: string } }) => (
<DataTableFilterButton
label={str(useTrans(`validation.custom.${column.id}`))
.ucFirst()
.value()}
field={column.id}
label={str(useTrans(`validation.custom.${column.id}`))
.ucFirst()
.value()}
field={column.id}
/>
),
cell: ({ row }: { row: Row<DynamicPageModel> }) => (
@ -230,7 +234,7 @@ export default function Index({
];
const transModel = useTrans(`models.classes.${str(modelName).singular().value()}`, { choice: 2 });
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel }})
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel } })
const transTitle = str(isArchiveRoute ? transArchiveTitle : transModel).ucFirst().value();
const beforeNode = () => {

View file

@ -23,6 +23,7 @@ import {
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Show({ data, modelName }: { data: SingleResource, modelName: string }) {
const { auth, appEnv } = usePage().props as unknown as {
@ -41,7 +42,9 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
accessorKey: "title",
header: str(useTrans("validation.attributes.title")).ucFirst().value(),
cell: ({ value }: { value: TranslationField }) => (
<p>{value[appEnv.locale]}</p>
renderTranslationCell(
value
)
),
},
{
@ -128,7 +131,7 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
variant="outline"
className={`border-0 ${value ? "bg-green-200 dark:bg-green-900" : "bg-red-200 dark:bg-red-900"}`}
>
{ value ? <CheckIcon size={15} className="mr-1" /> : <XIcon size={15} className="mr-1" /> }
{value ? <CheckIcon size={15} className="mr-1" /> : <XIcon size={15} className="mr-1" />}
{str(useTrans(value ? "back.yes" : "back.no")).ucFirst().value()}
</Badge>
),

View file

@ -25,6 +25,7 @@ import useTrans from "@/hooks/use-translations";
import { Row } from "@tanstack/react-table";
import { AlertCircle, Archive, ArrowLeft, Plus } from "lucide-react";
import NewsStatusBadge from "@/back/Components/NewsStatusBadge";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Index({
newsModels,
@ -62,9 +63,9 @@ export default function Index({
/>
),
cell: ({ row }: { row: Row<NewsModel> }) => {
return (row.getValue("title") as TranslationField)[appEnv.locale] ? (
(row.getValue("title") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("title")
)
},
},
{

View file

@ -24,6 +24,7 @@ import { ArrowLeft } from "lucide-react";
import NewsStatusBadge from "@/back/Components/NewsStatusBadge";
import NewsCategoriesBadge from "@/back/Components/NewsCategoriesBadge";
import useLocale from "@/store/use-locale-store";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Show({ data, modelName }: { data: SingleResource, modelName: string }) {
const { auth, appEnv } = usePage().props as unknown as {
@ -58,9 +59,11 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
{
accessorKey: "title",
header: str(useTrans("validation.attributes.title")).ucFirst().value(),
cell: ({ value }: { value: TranslationField }) => value[appEnv.locale]
? value[appEnv.locale]
: (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>),
cell: ({ value }: { value: TranslationField }) => {
return renderTranslationCell(
value
)
}
},
{
accessorKey: "slug",
@ -87,7 +90,7 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
},
{
accessorKey: "categories",
header: str(useTrans("validation.custom.category", {choice:2})).ucFirst().value(),
header: str(useTrans("validation.custom.category", { choice: 2 })).ucFirst().value(),
cell: ({ value }: { value?: NewsCategoryModel[] }) => {
if (!value || value.length === 0) return null;
return (

View file

@ -25,6 +25,7 @@ import {
} from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Index({
newsCategoryModels,
@ -62,9 +63,9 @@ export default function Index({
/>
),
cell: ({ row }: { row: Row<NewsCategoryModel> }) => {
return (row.getValue("name") as TranslationField)[appEnv.locale] ? (
(row.getValue("name") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("name")
)
},
},
{
@ -115,7 +116,7 @@ export default function Index({
},
];
const transModel = useTrans(`models.classes.${str(modelName).singular().value()}`, { choice: 2 });
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel }})
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel } })
const transTitle = str(isArchiveRoute ? transArchiveTitle : transModel).ucFirst().value();
const beforeNode = () => {

View file

@ -23,6 +23,7 @@ import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithT
import { ArrowLeft } from "lucide-react";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import AssociatedNewsList from "@/back/Components/AssociatedNewsList";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Show({ data, modelName, news }: { data: SingleResource, modelName: string, news: Resource }) {
@ -44,9 +45,11 @@ export default function Show({ data, modelName, news }: { data: SingleResource,
{
accessorKey: "name",
header: str(useTrans("validation.attributes.name")).ucFirst().value(),
cell: ({ value }: { value: TranslationField }) => value[appEnv.locale]
? value[appEnv.locale]
: (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>),
cell: ({ value }: { value: TranslationField }) => {
return renderTranslationCell(
value
)
}
},
{
accessorKey: "slug",

View file

@ -24,6 +24,7 @@ import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import { Row } from "@tanstack/react-table";
import { AlertCircleIcon, ArchiveIcon, ArrowLeftIcon, PlusIcon } from "lucide-react";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Index({
pageConfigModels,
@ -61,9 +62,9 @@ export default function Index({
/>
),
cell: ({ row }: { row: Row<PageConfigModel> }) => {
return (row.getValue("label") as TranslationField)[appEnv.locale] ? (
(row.getValue("label") as TranslationField)[appEnv.locale]
) : (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>);
return renderTranslationCell(
row.getValue("label") as TranslationField
)
},
},
{
@ -97,7 +98,7 @@ export default function Index({
];
const transModel = useTrans(`models.classes.${str(modelName).singular().value()}`, { choice: 2 });
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel }})
const transArchiveTitle = useTrans("crud.helpers.archives_model", { params: { model: transModel } })
const transTitle = str(isArchiveRoute ? transArchiveTitle : transModel).ucFirst().value();
const beforeNode = () => {

View file

@ -22,6 +22,7 @@ import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
import { ArrowLeftIcon } from "lucide-react";
import { renderTranslationCell } from "@/lib/translationCellFallback";
export default function Show({ data, modelName }: { data: SingleResource, modelName: string }) {
const { auth, appEnv } = usePage().props as unknown as {
@ -43,9 +44,11 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
{
accessorKey: "label",
header: str(useTrans("validation.custom.label")).ucFirst().value(),
cell: ({ value }: { value: TranslationField }) => value[appEnv.locale]
? value[appEnv.locale]
: (<p className="text-muted-foreground italic m-0">{useTrans('back.table_not_known')}</p>),
cell: ({ value }: { value: TranslationField }) => {
return renderTranslationCell(
value
)
}
},
{
accessorKey: "view",
@ -80,7 +83,7 @@ export default function Show({ data, modelName }: { data: SingleResource, modelN
),
},
];
const beforeNode = () => {
return viewAny && (
<div className="flex justify-end items-center gap-x-1.5">

View file

@ -0,0 +1,73 @@
import { AppEnv, TranslationField } from "@/back/types/global";
import useTrans from "@/hooks/use-translations";
import { usePage } from "@inertiajs/react";
import { ReactNode } from "react";
/**
* Resolves the best translation value for the current locale.
*
* Priority:
* 1. Value for the current app locale
* 2. First non-empty available translation (fallback)
*
* @param value - Translation field containing localized values
* @returns An object with the resolved value and optional fallback locale,
* or null if no translation is available
*/
const getTranslationValue = (
value?: TranslationField
):
| { value: string; locale?: string }
| null => {
const { appEnv } = usePage().props as unknown as {
appEnv: AppEnv;
};
if (!value) return null;
const local = value[appEnv.locale];
if (local) return { value: local };
const fallback = Object.entries(value).find(([, v]) => v?.trim());
if (!fallback) return null;
return { value: fallback[1], locale: fallback[0] };
};
/**
* Renders a table cell displaying a translated value.
*
* - Displays the value directly if it matches the current locale
* - Displays "locale: value" when a fallback translation is used
* - Displays a "not known" message when no translation is available
*
* @param value - Translation field containing localized values
* @returns A ReactNode ready to be rendered inside a table cell
*/
export const renderTranslationCell = (
value?: TranslationField
): ReactNode => {
const result = getTranslationValue(value);
if (!result) {
return (
<p className="text-muted-foreground italic m-0">
{useTrans("back.table_not_known")}
</p>
);
}
if (!result.locale) {
return result.value;
}
return (
<span className="italic text-xs">
<span className="text-muted-foreground mr-1">
{result.locale}:
</span>
{result.value}
</span>
);
};

View file

@ -322,13 +322,13 @@ Breadcrumbs::for('back.document-categories.create', function (Generator $trail)
Breadcrumbs::for('back.document-categories.edit', function (Generator $trail) {
$trail->parent('back.document-categories.index');
$trail->push(Str::ucfirst(trans('crud.actions.edit')), route('back.document-categories.edit', [
'document_tag' => request()->document_tag
'document_category' => request()->document_category
]));
});
Breadcrumbs::for('back.document-categories.show', function (Generator $trail) {
$trail->parent('back.document-categories.index');
$trail->push(Str::ucfirst(trans('crud.actions.visualize')), route('back.document-categories.show', [
'document_tag' => request()->document_tag
'document_category' => request()->document_category
]));
});
@ -347,12 +347,12 @@ Breadcrumbs::for('back.document-tags.create', function (Generator $trail) {
Breadcrumbs::for('back.document-tags.edit', function (Generator $trail) {
$trail->parent('back.document-tags.index');
$trail->push(Str::ucfirst(trans('crud.actions.edit')), route('back.document-tags.edit', [
'document_exercice' => request()->document_exercice
'document_tag' => request()->document_tag
]));
});
Breadcrumbs::for('back.document-tags.show', function (Generator $trail) {
$trail->parent('back.document-tags.index');
$trail->push(Str::ucfirst(trans('crud.actions.visualize')), route('back.document-tags.show', [
'document_exercice' => request()->document_exercice
'document_tag' => request()->document_tag
]));
});
});