@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
125 lines (121 loc) • 4.03 kB
JavaScript
"use client";
import { useUpdateEffect } from "../../utils/effect.js";
import { utils_exports } from "../../utils/index.js";
import { DEFAULT_DIRECTION, DEFAULT_LOCALE } from "../../core/constant.js";
import intl_default from "./intl/index.js";
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import { jsx } from "react/jsx-runtime";
import IntlMessageFormat from "intl-messageformat";
//#region src/providers/i18n-provider/i18n-provider.tsx
const DEFAULT_LANGUAGE = {
dir: DEFAULT_DIRECTION,
locale: DEFAULT_LOCALE
};
const LOCALES = Object.keys(intl_default);
function getLanguage(locale, dir) {
locale ??= (0, utils_exports.createdDom)() ? navigator.language : DEFAULT_LOCALE;
try {
Intl.DateTimeFormat.supportedLocalesOf([locale]);
} catch (_err) {
locale = DEFAULT_LOCALE;
}
dir ??= (0, utils_exports.isRtl)(locale) ? "rtl" : "ltr";
return {
dir,
locale
};
}
const I18nContext = createContext({
...DEFAULT_LANGUAGE,
changeLanguage: utils_exports.noop,
getTranslation: () => () => "",
t: () => ""
});
const I18nProvider = ({ children, dir: forcedDir, formats, intl = intl_default, intlMessageFormatOptions, locale: forcedLocale }) => {
const [language, setLanguage] = useState(getLanguage(forcedLocale, forcedDir));
const controlled = !(0, utils_exports.isUndefined)(forcedLocale);
const { locale } = language;
const messages = useMemo(() => intl[locale], [intl, locale]);
const changeSystemLanguage = useCallback(() => {
setLanguage(getLanguage());
}, []);
const changeLanguage = useCallback((locale$1, dir) => {
setLanguage(getLanguage(locale$1, dir));
}, []);
const getValue = useCallback((path) => {
const value$1 = (0, utils_exports.getMemoizedObject)(messages, path);
if (!(0, utils_exports.isUndefined)(value$1)) return value$1;
else {
path = path.toString().replace(/^[^.]+\./g, "");
return (0, utils_exports.getMemoizedObject)(messages, path);
}
}, [messages]);
const getTranslation = useCallback((key) => (path, replaceValues) => {
const value$1 = getValue(key ? `${key}.${path}` : path) ?? path;
if ((0, utils_exports.isUndefined)(replaceValues)) return value$1;
try {
const resolvedReplaceValues = Object.entries(replaceValues).reduce((prev, [key$1, pathOrValue]) => {
if ((0, utils_exports.isString)(pathOrValue)) {
const resolvedPathOrValue = String(pathOrValue);
prev[key$1] = getValue(key$1 ? `${key$1}.${resolvedPathOrValue}` : resolvedPathOrValue) ?? resolvedPathOrValue;
} else prev[key$1] = pathOrValue;
return prev;
}, {});
return new IntlMessageFormat(value$1, locale, formats, intlMessageFormatOptions).format(resolvedReplaceValues);
} catch (e) {
if (e instanceof Error) console.warn(e.message);
return value$1;
}
}, [
getValue,
locale,
formats,
intlMessageFormatOptions
]);
const value = useMemo(() => {
const rest = {
changeLanguage,
getTranslation,
t: getTranslation()
};
return {
...language,
...rest
};
}, [
changeLanguage,
getTranslation,
language
]);
useEffect(() => {
if (controlled) return;
window.addEventListener("languagechange", changeSystemLanguage);
return () => {
window.removeEventListener("languagechange", changeSystemLanguage);
};
}, [controlled, changeSystemLanguage]);
useUpdateEffect(() => {
setLanguage(getLanguage(forcedLocale, forcedDir));
}, [forcedLocale, forcedDir]);
return /* @__PURE__ */ jsx(I18nContext, {
value,
children
});
};
function useI18n(key) {
const context = useContext(I18nContext);
const translation = useCallback((path, replaceValues) => context.getTranslation(key)(path, replaceValues), [key, context]);
if ((0, utils_exports.isEmptyObject)(context)) return {
...DEFAULT_LANGUAGE,
changeLanguage: utils_exports.noop,
t: () => ""
};
if (key) return {
...context,
t: translation
};
else return context;
}
//#endregion
export { I18nContext, I18nProvider, LOCALES, getLanguage, useI18n };
//# sourceMappingURL=i18n-provider.js.map