96 lines
2.6 KiB
TypeScript
96 lines
2.6 KiB
TypeScript
import { usePage } from "@inertiajs/react";
|
|
import { type ReactNode } from "react";
|
|
|
|
import type { TranslationField } from "@/back/types/i18n";
|
|
import str from "@/hooks/use-string";
|
|
import useTrans from "@/hooks/use-translations";
|
|
|
|
/**
|
|
* Get a normalize preview of a target string.
|
|
*
|
|
* @param value - Translated value
|
|
* @return A string with limited length
|
|
*/
|
|
function normalizePreview(value: string): string {
|
|
return str(value).normalize().value().substring(0, 50);
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
* @return An object with the resolved value and optional fallback locale,
|
|
* or null if no translation is available
|
|
*/
|
|
function useGetTranslationValue(
|
|
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] };
|
|
}
|
|
|
|
function RenderValue({
|
|
value,
|
|
renderHtml,
|
|
}: {
|
|
value: string;
|
|
renderHtml: boolean;
|
|
}): ReactNode {
|
|
const preview = normalizePreview(value);
|
|
|
|
return renderHtml ? (
|
|
<p dangerouslySetInnerHTML={{ __html: preview }} />
|
|
) : (
|
|
preview
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
* @param renderHtml - Render a html value or not (optional)
|
|
* @return A ReactNode ready to be rendered inside a table cell
|
|
*/
|
|
export default function RenderTranslationCell({
|
|
value,
|
|
renderHtml = false,
|
|
}: {
|
|
value?: TranslationField;
|
|
renderHtml?: boolean;
|
|
}): ReactNode {
|
|
const result = useGetTranslationValue(value);
|
|
const notKnown = useTrans("uwil-i18n::trans.value_not_known");
|
|
|
|
if (!result) {
|
|
return <p className="text-muted-foreground italic m-0">{notKnown}</p>;
|
|
}
|
|
|
|
if (!result.locale) {
|
|
return <RenderValue value={result.value} renderHtml={renderHtml} />;
|
|
}
|
|
|
|
return (
|
|
<span className="italic text-xs">
|
|
<span className="text-muted-foreground mr-1">{result.locale}:</span>
|
|
<RenderValue value={result.value} renderHtml={renderHtml} />
|
|
</span>
|
|
);
|
|
}
|