import "./style.pcss"; import { getMergedObj } from "@web3r/flowerkit/obj"; import type { FC, ReactNode, ReactElement, PropsWithChildren, } from "react"; import { Children, cloneElement, isValidElement, useMemo, } from "react"; import { Translation } from "react-i18next"; import type { ILocale, TTranslation } from "./config/types"; import { useMessage, getIsAttr, getUserAttrs } from "./lib"; import { constants } from "../../constants"; import type { IComponentBaseProps } from "../../types/components"; import { useCN } from "../../utils/react/useCN"; import { useLocalisationPlugin } from "../../utils/react/useLocalisationPlugin"; import { useSSGRender } from "../../utils/react/useSSGRender"; /** * Вывод данных локализации * @returns {ReactNode} */ const Message: FC> = ({ fn, code, options, instance, attr, children, }): ReactNode => { const { message } = useMessage({ fn, code, instance, options, }); const isAttr = getIsAttr(attr); if (isAttr && !!children) { // перевод только указанного атрибута для единственного дочернего элемента return Children .toArray(children) .filter((child) => isValidElement(child)) .map((child, index) => { const userAttrs = typeof attr === "string" ? getUserAttrs({ [attr]: message, }) : getUserAttrs(Object.fromEntries((attr as string[]).map((str) => [ str, message ]))); const currentProps: PropsWithChildren = { ...(child?.props ?? {}), key: index, }; const computedProps = getMergedObj(currentProps, userAttrs); return cloneElement(child, computedProps, currentProps.children); }); } else { // возвращение перевода как дочернего текста return message; } }; /** * Компонент вывода локали * @returns {ReactElement} */ const Locale: FC = (props): ReactElement => { const { baseClass = "locale", extraClasses = {}, extraAttrs = {}, children, code, attr, options = {}, ns, } = props; const { getCN } = useCN(baseClass); const { isLoading, isError, isReady } = useLocalisationPlugin(code); const utilClasses = useMemo(() => { switch (true) { case isReady: { return [ constants.stateClasses.translated ]; } case isError: { return [ constants.stateClasses.translationError ]; } case isLoading: default: { return [ constants.stateClasses.translationLoading ]; } } }, [ isLoading, isError, isReady ]); const metaAttr = useMemo(() => { return JSON.stringify({ code, options, attr, }); }, [ code, options, attr ]); const SSGComponent = useSSGRender("data-js-locale", props, "ins", baseClass); if (SSGComponent) { return SSGComponent; } return ( {isLoading && children} {isReady && ( {(t, instance) => ( {children} )} )} ); }; export type { ILocale }; export { Locale };