inline-i18n-multi-react 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React, { ReactNode } from 'react';
|
|
3
3
|
import { Locale, TranslationVars, DetectLocaleOptions, Translations } from 'inline-i18n-multi';
|
|
4
|
-
export { CustomFormatter, DetectLocaleOptions, DetectSource, Dictionaries, Dictionary, Locale, PluralRules, RichTextSegment, TranslationVars, Translations, clearDictionaries, clearFormatters, clearICUCache, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLocale, hasTranslation, isLoaded, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadAsync, loadDictionaries, loadDictionary, parseRichText, registerFormatter, resetConfig, restoreLocale, setLocale, t, zh_es } from 'inline-i18n-multi';
|
|
4
|
+
export { CustomFormatter, DetectLocaleOptions, DetectSource, Dictionaries, Dictionary, Locale, PluralRules, RichTextSegment, TranslationVars, Translations, clearDictionaries, clearFormatters, clearICUCache, clearMissingKeys, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLocale, getLocaleDisplayName, getMissingKeys, getTranslationKeys, hasTranslation, isLoaded, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadAsync, loadDictionaries, loadDictionary, parseRichText, registerFormatter, resetConfig, restoreLocale, setLocale, t, trackMissingKeys, zh_es } from 'inline-i18n-multi';
|
|
5
5
|
|
|
6
6
|
interface LocaleProviderProps {
|
|
7
7
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React, { ReactNode } from 'react';
|
|
3
3
|
import { Locale, TranslationVars, DetectLocaleOptions, Translations } from 'inline-i18n-multi';
|
|
4
|
-
export { CustomFormatter, DetectLocaleOptions, DetectSource, Dictionaries, Dictionary, Locale, PluralRules, RichTextSegment, TranslationVars, Translations, clearDictionaries, clearFormatters, clearICUCache, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLocale, hasTranslation, isLoaded, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadAsync, loadDictionaries, loadDictionary, parseRichText, registerFormatter, resetConfig, restoreLocale, setLocale, t, zh_es } from 'inline-i18n-multi';
|
|
4
|
+
export { CustomFormatter, DetectLocaleOptions, DetectSource, Dictionaries, Dictionary, Locale, PluralRules, RichTextSegment, TranslationVars, Translations, clearDictionaries, clearFormatters, clearICUCache, clearMissingKeys, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, getConfig, getDictionary, getLoadedLocales, getLocale, getLocaleDisplayName, getMissingKeys, getTranslationKeys, hasTranslation, isLoaded, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadAsync, loadDictionaries, loadDictionary, parseRichText, registerFormatter, resetConfig, restoreLocale, setLocale, t, trackMissingKeys, zh_es } from 'inline-i18n-multi';
|
|
5
5
|
|
|
6
6
|
interface LocaleProviderProps {
|
|
7
7
|
/**
|
package/dist/index.js
CHANGED
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
clearDictionaries: () => import_inline_i18n_multi5.clearDictionaries,
|
|
28
28
|
clearFormatters: () => import_inline_i18n_multi5.clearFormatters,
|
|
29
29
|
clearICUCache: () => import_inline_i18n_multi5.clearICUCache,
|
|
30
|
+
clearMissingKeys: () => import_inline_i18n_multi5.clearMissingKeys,
|
|
30
31
|
configure: () => import_inline_i18n_multi5.configure,
|
|
31
32
|
createScope: () => import_inline_i18n_multi5.createScope,
|
|
32
33
|
detectLocale: () => import_inline_i18n_multi5.detectLocale,
|
|
@@ -39,6 +40,9 @@ __export(index_exports, {
|
|
|
39
40
|
getDictionary: () => import_inline_i18n_multi5.getDictionary,
|
|
40
41
|
getLoadedLocales: () => import_inline_i18n_multi5.getLoadedLocales,
|
|
41
42
|
getLocale: () => import_inline_i18n_multi5.getLocale,
|
|
43
|
+
getLocaleDisplayName: () => import_inline_i18n_multi5.getLocaleDisplayName,
|
|
44
|
+
getMissingKeys: () => import_inline_i18n_multi5.getMissingKeys,
|
|
45
|
+
getTranslationKeys: () => import_inline_i18n_multi5.getTranslationKeys,
|
|
42
46
|
hasTranslation: () => import_inline_i18n_multi5.hasTranslation,
|
|
43
47
|
isLoaded: () => import_inline_i18n_multi5.isLoaded,
|
|
44
48
|
it: () => import_inline_i18n_multi5.it,
|
|
@@ -58,6 +62,7 @@ __export(index_exports, {
|
|
|
58
62
|
restoreLocale: () => import_inline_i18n_multi5.restoreLocale,
|
|
59
63
|
setLocale: () => import_inline_i18n_multi5.setLocale,
|
|
60
64
|
t: () => import_inline_i18n_multi5.t,
|
|
65
|
+
trackMissingKeys: () => import_inline_i18n_multi5.trackMissingKeys,
|
|
61
66
|
useDetectedLocale: () => useDetectedLocale,
|
|
62
67
|
useLoadDictionaries: () => useLoadDictionaries,
|
|
63
68
|
useLocale: () => useLocale,
|
|
@@ -227,6 +232,7 @@ var import_inline_i18n_multi5 = require("inline-i18n-multi");
|
|
|
227
232
|
clearDictionaries,
|
|
228
233
|
clearFormatters,
|
|
229
234
|
clearICUCache,
|
|
235
|
+
clearMissingKeys,
|
|
230
236
|
configure,
|
|
231
237
|
createScope,
|
|
232
238
|
detectLocale,
|
|
@@ -239,6 +245,9 @@ var import_inline_i18n_multi5 = require("inline-i18n-multi");
|
|
|
239
245
|
getDictionary,
|
|
240
246
|
getLoadedLocales,
|
|
241
247
|
getLocale,
|
|
248
|
+
getLocaleDisplayName,
|
|
249
|
+
getMissingKeys,
|
|
250
|
+
getTranslationKeys,
|
|
242
251
|
hasTranslation,
|
|
243
252
|
isLoaded,
|
|
244
253
|
it,
|
|
@@ -258,6 +267,7 @@ var import_inline_i18n_multi5 = require("inline-i18n-multi");
|
|
|
258
267
|
restoreLocale,
|
|
259
268
|
setLocale,
|
|
260
269
|
t,
|
|
270
|
+
trackMissingKeys,
|
|
261
271
|
useDetectedLocale,
|
|
262
272
|
useLoadDictionaries,
|
|
263
273
|
useLocale,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/context.tsx","../src/hooks.ts","../src/component.tsx","../src/richtext.tsx"],"sourcesContent":["export { LocaleProvider } from './provider'\nexport { useLocale, useT, useScopedT, useLoadDictionaries, useDetectedLocale } from './hooks'\nexport { T } from './component'\nexport { RichText, useRichText } from './richtext'\n\n// re-export from core for convenience\nexport {\n // inline translations\n it,\n it_ja,\n it_zh,\n it_es,\n it_fr,\n it_de,\n en_ja,\n en_zh,\n en_es,\n en_fr,\n en_de,\n ja_zh,\n ja_es,\n zh_es,\n getLocale,\n setLocale,\n // key-based translations (i18n compatible)\n t,\n loadDictionaries,\n loadDictionary,\n clearDictionaries,\n hasTranslation,\n getLoadedLocales,\n getDictionary,\n loadAsync,\n isLoaded,\n // configuration\n configure,\n getConfig,\n resetConfig,\n // rich text parsing\n parseRichText,\n type RichTextSegment,\n // custom formatters (v0.6.0) + ICU cache (v0.7.0)\n registerFormatter,\n clearFormatters,\n clearICUCache,\n type CustomFormatter,\n // locale persistence (v0.7.0)\n restoreLocale,\n // translation scope (v0.8.0)\n createScope,\n // locale detection (v0.6.0)\n detectLocale,\n type DetectLocaleOptions,\n type DetectSource,\n // types\n type Locale,\n type Translations,\n type TranslationVars,\n type Dictionary,\n type Dictionaries,\n type PluralRules,\n} from 'inline-i18n-multi'\n","import { useState, useCallback, useMemo, useEffect, type ReactNode } from 'react'\nimport { setLocale as setCoreLocale, type Locale } from 'inline-i18n-multi'\nimport { LocaleContext } from './context'\n\ninterface LocaleProviderProps {\n /**\n * Initial locale value\n */\n locale: Locale\n /**\n * Cookie name for persisting locale (default: NEXT_LOCALE)\n * Set to false to disable cookie sync\n */\n cookieName?: string | false\n /**\n * Callback when locale changes\n */\n onLocaleChange?: (locale: Locale) => void\n children: ReactNode\n}\n\nfunction setCookie(name: string, value: string, days = 365): void {\n if (typeof document === 'undefined') return\n const expires = new Date(Date.now() + days * 864e5).toUTCString()\n document.cookie = `${name}=${value}; expires=${expires}; path=/; SameSite=Lax`\n}\n\nexport function LocaleProvider({\n locale: initialLocale,\n cookieName = 'NEXT_LOCALE',\n onLocaleChange,\n children,\n}: LocaleProviderProps) {\n const [locale, setLocaleState] = useState<Locale>(initialLocale)\n\n // sync with core package on mount and locale change\n useEffect(() => {\n setCoreLocale(locale)\n }, [locale])\n\n const setLocale = useCallback(\n (newLocale: Locale) => {\n setLocaleState(newLocale)\n setCoreLocale(newLocale)\n\n // sync cookie for Next.js middleware\n if (cookieName) {\n setCookie(cookieName, newLocale)\n }\n\n // callback for custom handling\n onLocaleChange?.(newLocale)\n },\n [cookieName, onLocaleChange]\n )\n\n const value = useMemo(() => ({ locale, setLocale }), [locale, setLocale])\n\n return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>\n}\n","import { createContext, useContext } from 'react'\nimport type { Locale } from 'inline-i18n-multi'\n\ninterface LocaleContextValue {\n locale: Locale\n setLocale: (locale: Locale) => void\n}\n\nexport const LocaleContext = createContext<LocaleContextValue | null>(null)\n\nexport function useLocaleContext(): LocaleContextValue {\n const context = useContext(LocaleContext)\n\n if (!context) {\n throw new Error('useLocaleContext must be used within a LocaleProvider')\n }\n\n return context\n}\n","import { useCallback, useState, useEffect } from 'react'\nimport { useLocaleContext } from './context'\nimport { t as coreT, loadAsync, isLoaded, detectLocale, setLocale } from 'inline-i18n-multi'\nimport type { Locale, TranslationVars, DetectLocaleOptions } from 'inline-i18n-multi'\n\n/**\n * Get current locale and setter\n */\nexport function useLocale(): [Locale, (locale: Locale) => void] {\n const { locale, setLocale } = useLocaleContext()\n return [locale, setLocale]\n}\n\n/**\n * Get translation function bound to current locale\n * @example\n * const t = useT()\n * t('greeting.hello') // uses context locale\n * t('items.count', { count: 5 })\n */\nexport function useT(): (key: string, vars?: TranslationVars) => string {\n const { locale } = useLocaleContext()\n\n return useCallback(\n (key: string, vars?: TranslationVars) => coreT(key, vars, locale),\n [locale]\n )\n}\n\n/**\n * Hook for lazy loading dictionaries\n * Automatically loads dictionaries when locale or namespace changes\n *\n * @example\n * function Dashboard() {\n * const { isLoading, error } = useLoadDictionaries('ko', 'dashboard')\n * if (isLoading) return <Spinner />\n * if (error) return <Error message={error.message} />\n * return <Content />\n * }\n */\nexport function useLoadDictionaries(\n locale: Locale,\n namespace?: string\n): { isLoading: boolean; error: Error | null } {\n const [isLoading, setIsLoading] = useState(() => !isLoaded(locale, namespace))\n const [error, setError] = useState<Error | null>(null)\n\n useEffect(() => {\n if (isLoaded(locale, namespace)) {\n setIsLoading(false)\n setError(null)\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n loadAsync(locale, namespace)\n .then(() => setIsLoading(false))\n .catch((err) => {\n setError(err instanceof Error ? err : new Error(String(err)))\n setIsLoading(false)\n })\n }, [locale, namespace])\n\n return { isLoading, error }\n}\n\n/**\n * Hook that auto-detects and sets locale on mount\n *\n * @example\n * function App() {\n * useDetectedLocale({\n * supportedLocales: ['en', 'ko', 'ja'],\n * defaultLocale: 'en',\n * sources: ['cookie', 'navigator'],\n * })\n * return <Content />\n * }\n */\n/**\n * Get a scoped translation function bound to current locale and namespace\n * @param namespace - Namespace to scope to\n * @example\n * const tc = useScopedT('common')\n * tc('greeting') // equivalent to t('common:greeting')\n */\nexport function useScopedT(namespace: string): (key: string, vars?: TranslationVars) => string {\n const { locale } = useLocaleContext()\n\n return useCallback(\n (key: string, vars?: TranslationVars) => coreT(`${namespace}:${key}`, vars, locale),\n [locale, namespace]\n )\n}\n\nexport function useDetectedLocale(options: DetectLocaleOptions): void {\n const { setLocale: setContextLocale } = useLocaleContext()\n\n useEffect(() => {\n const detected = detectLocale(options)\n setLocale(detected)\n setContextLocale(detected)\n // Run once on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n}\n","import { it, type Translations, type TranslationVars } from 'inline-i18n-multi'\n\ninterface TPropsShorthand {\n /**\n * Korean text\n */\n ko: string\n /**\n * English text\n */\n en: string\n translations?: never\n}\n\ninterface TPropsObject {\n ko?: never\n en?: never\n /**\n * Translation map with locale keys\n */\n translations: Translations\n}\n\ntype TProps = (TPropsShorthand | TPropsObject) & TranslationVars\n\n/**\n * Translation component for JSX\n * @example <T ko=\"안녕\" en=\"Hello\" />\n * @example <T translations={{ ko: '안녕', en: 'Hello', ja: 'こんにちは' }} />\n * @example <T ko=\"안녕 {name}\" en=\"Hello {name}\" name=\"철수\" />\n */\nexport function T(props: TProps) {\n const { ko, en, translations, ...vars } = props\n\n if (translations) {\n return <>{it(translations, vars)}</>\n }\n\n if (ko !== undefined && en !== undefined) {\n return <>{it(ko, en, vars)}</>\n }\n\n throw new Error('T component requires either \"translations\" or both \"ko\" and \"en\" props')\n}\n","import React, { type ReactNode, useMemo, useCallback, Fragment } from 'react'\nimport { it, parseRichText, type Translations, type TranslationVars } from 'inline-i18n-multi'\n\ntype ComponentRenderer = (text: string) => ReactNode\n\ninterface RichTextProps {\n /**\n * Translation map with locale keys\n * Tags like <link>text</link> will be matched to component renderers\n */\n translations: Translations\n /**\n * Component renderers for each tag name\n * @example { link: (text) => <a href=\"/terms\">{text}</a> }\n */\n components: Record<string, ComponentRenderer>\n /**\n * Variables for interpolation (applied before rich text parsing)\n */\n vars?: TranslationVars\n}\n\n/**\n * Rich text translation component\n * Supports embedding React components within translations\n *\n * @example\n * <RichText\n * translations={{\n * en: 'Read <link>terms</link> and <bold>agree</bold>',\n * ko: '<link>약관</link>을 읽고 <bold>동의</bold>해주세요'\n * }}\n * components={{\n * link: (text) => <a href=\"/terms\">{text}</a>,\n * bold: (text) => <strong>{text}</strong>\n * }}\n * />\n */\nexport function RichText({ translations, components, vars }: RichTextProps): React.JSX.Element {\n const componentNames = useMemo(() => Object.keys(components), [components])\n\n // Resolve locale and interpolate variables ({curly} braces)\n // Rich text tags (<angle> brackets) don't conflict with variable interpolation\n const resolved = it(translations, vars)\n const segments = parseRichText(resolved, componentNames)\n\n return (\n <>\n {segments.map((segment, index) => {\n if (segment.type === 'text') {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n const renderer = components[segment.componentName!]\n if (!renderer) {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n return <Fragment key={index}>{renderer(segment.content)}</Fragment>\n })}\n </>\n )\n}\n\n/**\n * Hook for rich text translations\n * Returns a function that resolves translations with component interpolation\n *\n * @example\n * const richT = useRichText({\n * link: (text) => <a href=\"/terms\">{text}</a>,\n * bold: (text) => <strong>{text}</strong>,\n * })\n * return richT({ en: 'Click <link>here</link>', ko: '<link>여기</link> 클릭' })\n */\nexport function useRichText(\n components: Record<string, ComponentRenderer>\n): (translations: Translations, vars?: TranslationVars) => ReactNode {\n const componentNames = useMemo(() => Object.keys(components), [components])\n\n return useCallback(\n (translations: Translations, vars?: TranslationVars): ReactNode => {\n const resolved = it(translations, vars)\n const segments = parseRichText(resolved, componentNames)\n\n return (\n <>\n {segments.map((segment, index) => {\n if (segment.type === 'text') {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n const renderer = components[segment.componentName!]\n if (!renderer) {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n return <Fragment key={index}>{renderer(segment.content)}</Fragment>\n })}\n </>\n )\n },\n [components, componentNames]\n )\n}\n"],"mappings":"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","names":["import_react","setCoreLocale","setLocale","import_react","import_inline_i18n_multi","setLocale","coreT","import_inline_i18n_multi","import_jsx_runtime","import_react","import_inline_i18n_multi","import_jsx_runtime","import_inline_i18n_multi"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/context.tsx","../src/hooks.ts","../src/component.tsx","../src/richtext.tsx"],"sourcesContent":["export { LocaleProvider } from './provider'\nexport { useLocale, useT, useScopedT, useLoadDictionaries, useDetectedLocale } from './hooks'\nexport { T } from './component'\nexport { RichText, useRichText } from './richtext'\n\n// re-export from core for convenience\nexport {\n // inline translations\n it,\n it_ja,\n it_zh,\n it_es,\n it_fr,\n it_de,\n en_ja,\n en_zh,\n en_es,\n en_fr,\n en_de,\n ja_zh,\n ja_es,\n zh_es,\n getLocale,\n setLocale,\n // key-based translations (i18n compatible)\n t,\n loadDictionaries,\n loadDictionary,\n clearDictionaries,\n hasTranslation,\n getLoadedLocales,\n getDictionary,\n loadAsync,\n isLoaded,\n // configuration\n configure,\n getConfig,\n resetConfig,\n // rich text parsing\n parseRichText,\n type RichTextSegment,\n // custom formatters (v0.6.0) + ICU cache (v0.7.0)\n registerFormatter,\n clearFormatters,\n clearICUCache,\n type CustomFormatter,\n // locale persistence (v0.7.0)\n restoreLocale,\n // translation scope (v0.8.0)\n createScope,\n // locale detection (v0.6.0)\n detectLocale,\n // utils (v0.11.0)\n getLocaleDisplayName,\n getTranslationKeys,\n trackMissingKeys,\n getMissingKeys,\n clearMissingKeys,\n type DetectLocaleOptions,\n type DetectSource,\n // types\n type Locale,\n type Translations,\n type TranslationVars,\n type Dictionary,\n type Dictionaries,\n type PluralRules,\n} from 'inline-i18n-multi'\n","import { useState, useCallback, useMemo, useEffect, type ReactNode } from 'react'\nimport { setLocale as setCoreLocale, type Locale } from 'inline-i18n-multi'\nimport { LocaleContext } from './context'\n\ninterface LocaleProviderProps {\n /**\n * Initial locale value\n */\n locale: Locale\n /**\n * Cookie name for persisting locale (default: NEXT_LOCALE)\n * Set to false to disable cookie sync\n */\n cookieName?: string | false\n /**\n * Callback when locale changes\n */\n onLocaleChange?: (locale: Locale) => void\n children: ReactNode\n}\n\nfunction setCookie(name: string, value: string, days = 365): void {\n if (typeof document === 'undefined') return\n const expires = new Date(Date.now() + days * 864e5).toUTCString()\n document.cookie = `${name}=${value}; expires=${expires}; path=/; SameSite=Lax`\n}\n\nexport function LocaleProvider({\n locale: initialLocale,\n cookieName = 'NEXT_LOCALE',\n onLocaleChange,\n children,\n}: LocaleProviderProps) {\n const [locale, setLocaleState] = useState<Locale>(initialLocale)\n\n // sync with core package on mount and locale change\n useEffect(() => {\n setCoreLocale(locale)\n }, [locale])\n\n const setLocale = useCallback(\n (newLocale: Locale) => {\n setLocaleState(newLocale)\n setCoreLocale(newLocale)\n\n // sync cookie for Next.js middleware\n if (cookieName) {\n setCookie(cookieName, newLocale)\n }\n\n // callback for custom handling\n onLocaleChange?.(newLocale)\n },\n [cookieName, onLocaleChange]\n )\n\n const value = useMemo(() => ({ locale, setLocale }), [locale, setLocale])\n\n return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>\n}\n","import { createContext, useContext } from 'react'\nimport type { Locale } from 'inline-i18n-multi'\n\ninterface LocaleContextValue {\n locale: Locale\n setLocale: (locale: Locale) => void\n}\n\nexport const LocaleContext = createContext<LocaleContextValue | null>(null)\n\nexport function useLocaleContext(): LocaleContextValue {\n const context = useContext(LocaleContext)\n\n if (!context) {\n throw new Error('useLocaleContext must be used within a LocaleProvider')\n }\n\n return context\n}\n","import { useCallback, useState, useEffect } from 'react'\nimport { useLocaleContext } from './context'\nimport { t as coreT, loadAsync, isLoaded, detectLocale, setLocale } from 'inline-i18n-multi'\nimport type { Locale, TranslationVars, DetectLocaleOptions } from 'inline-i18n-multi'\n\n/**\n * Get current locale and setter\n */\nexport function useLocale(): [Locale, (locale: Locale) => void] {\n const { locale, setLocale } = useLocaleContext()\n return [locale, setLocale]\n}\n\n/**\n * Get translation function bound to current locale\n * @example\n * const t = useT()\n * t('greeting.hello') // uses context locale\n * t('items.count', { count: 5 })\n */\nexport function useT(): (key: string, vars?: TranslationVars) => string {\n const { locale } = useLocaleContext()\n\n return useCallback(\n (key: string, vars?: TranslationVars) => coreT(key, vars, locale),\n [locale]\n )\n}\n\n/**\n * Hook for lazy loading dictionaries\n * Automatically loads dictionaries when locale or namespace changes\n *\n * @example\n * function Dashboard() {\n * const { isLoading, error } = useLoadDictionaries('ko', 'dashboard')\n * if (isLoading) return <Spinner />\n * if (error) return <Error message={error.message} />\n * return <Content />\n * }\n */\nexport function useLoadDictionaries(\n locale: Locale,\n namespace?: string\n): { isLoading: boolean; error: Error | null } {\n const [isLoading, setIsLoading] = useState(() => !isLoaded(locale, namespace))\n const [error, setError] = useState<Error | null>(null)\n\n useEffect(() => {\n if (isLoaded(locale, namespace)) {\n setIsLoading(false)\n setError(null)\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n loadAsync(locale, namespace)\n .then(() => setIsLoading(false))\n .catch((err) => {\n setError(err instanceof Error ? err : new Error(String(err)))\n setIsLoading(false)\n })\n }, [locale, namespace])\n\n return { isLoading, error }\n}\n\n/**\n * Hook that auto-detects and sets locale on mount\n *\n * @example\n * function App() {\n * useDetectedLocale({\n * supportedLocales: ['en', 'ko', 'ja'],\n * defaultLocale: 'en',\n * sources: ['cookie', 'navigator'],\n * })\n * return <Content />\n * }\n */\n/**\n * Get a scoped translation function bound to current locale and namespace\n * @param namespace - Namespace to scope to\n * @example\n * const tc = useScopedT('common')\n * tc('greeting') // equivalent to t('common:greeting')\n */\nexport function useScopedT(namespace: string): (key: string, vars?: TranslationVars) => string {\n const { locale } = useLocaleContext()\n\n return useCallback(\n (key: string, vars?: TranslationVars) => coreT(`${namespace}:${key}`, vars, locale),\n [locale, namespace]\n )\n}\n\nexport function useDetectedLocale(options: DetectLocaleOptions): void {\n const { setLocale: setContextLocale } = useLocaleContext()\n\n useEffect(() => {\n const detected = detectLocale(options)\n setLocale(detected)\n setContextLocale(detected)\n // Run once on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n}\n","import { it, type Translations, type TranslationVars } from 'inline-i18n-multi'\n\ninterface TPropsShorthand {\n /**\n * Korean text\n */\n ko: string\n /**\n * English text\n */\n en: string\n translations?: never\n}\n\ninterface TPropsObject {\n ko?: never\n en?: never\n /**\n * Translation map with locale keys\n */\n translations: Translations\n}\n\ntype TProps = (TPropsShorthand | TPropsObject) & TranslationVars\n\n/**\n * Translation component for JSX\n * @example <T ko=\"안녕\" en=\"Hello\" />\n * @example <T translations={{ ko: '안녕', en: 'Hello', ja: 'こんにちは' }} />\n * @example <T ko=\"안녕 {name}\" en=\"Hello {name}\" name=\"철수\" />\n */\nexport function T(props: TProps) {\n const { ko, en, translations, ...vars } = props\n\n if (translations) {\n return <>{it(translations, vars)}</>\n }\n\n if (ko !== undefined && en !== undefined) {\n return <>{it(ko, en, vars)}</>\n }\n\n throw new Error('T component requires either \"translations\" or both \"ko\" and \"en\" props')\n}\n","import React, { type ReactNode, useMemo, useCallback, Fragment } from 'react'\nimport { it, parseRichText, type Translations, type TranslationVars } from 'inline-i18n-multi'\n\ntype ComponentRenderer = (text: string) => ReactNode\n\ninterface RichTextProps {\n /**\n * Translation map with locale keys\n * Tags like <link>text</link> will be matched to component renderers\n */\n translations: Translations\n /**\n * Component renderers for each tag name\n * @example { link: (text) => <a href=\"/terms\">{text}</a> }\n */\n components: Record<string, ComponentRenderer>\n /**\n * Variables for interpolation (applied before rich text parsing)\n */\n vars?: TranslationVars\n}\n\n/**\n * Rich text translation component\n * Supports embedding React components within translations\n *\n * @example\n * <RichText\n * translations={{\n * en: 'Read <link>terms</link> and <bold>agree</bold>',\n * ko: '<link>약관</link>을 읽고 <bold>동의</bold>해주세요'\n * }}\n * components={{\n * link: (text) => <a href=\"/terms\">{text}</a>,\n * bold: (text) => <strong>{text}</strong>\n * }}\n * />\n */\nexport function RichText({ translations, components, vars }: RichTextProps): React.JSX.Element {\n const componentNames = useMemo(() => Object.keys(components), [components])\n\n // Resolve locale and interpolate variables ({curly} braces)\n // Rich text tags (<angle> brackets) don't conflict with variable interpolation\n const resolved = it(translations, vars)\n const segments = parseRichText(resolved, componentNames)\n\n return (\n <>\n {segments.map((segment, index) => {\n if (segment.type === 'text') {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n const renderer = components[segment.componentName!]\n if (!renderer) {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n return <Fragment key={index}>{renderer(segment.content)}</Fragment>\n })}\n </>\n )\n}\n\n/**\n * Hook for rich text translations\n * Returns a function that resolves translations with component interpolation\n *\n * @example\n * const richT = useRichText({\n * link: (text) => <a href=\"/terms\">{text}</a>,\n * bold: (text) => <strong>{text}</strong>,\n * })\n * return richT({ en: 'Click <link>here</link>', ko: '<link>여기</link> 클릭' })\n */\nexport function useRichText(\n components: Record<string, ComponentRenderer>\n): (translations: Translations, vars?: TranslationVars) => ReactNode {\n const componentNames = useMemo(() => Object.keys(components), [components])\n\n return useCallback(\n (translations: Translations, vars?: TranslationVars): ReactNode => {\n const resolved = it(translations, vars)\n const segments = parseRichText(resolved, componentNames)\n\n return (\n <>\n {segments.map((segment, index) => {\n if (segment.type === 'text') {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n const renderer = components[segment.componentName!]\n if (!renderer) {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n return <Fragment key={index}>{renderer(segment.content)}</Fragment>\n })}\n </>\n )\n },\n [components, componentNames]\n )\n}\n"],"mappings":"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","names":["import_react","setCoreLocale","setLocale","import_react","import_inline_i18n_multi","setLocale","coreT","import_inline_i18n_multi","import_jsx_runtime","import_react","import_inline_i18n_multi","import_jsx_runtime","import_inline_i18n_multi"]}
|
package/dist/index.mjs
CHANGED
|
@@ -185,7 +185,12 @@ import {
|
|
|
185
185
|
clearICUCache,
|
|
186
186
|
restoreLocale,
|
|
187
187
|
createScope,
|
|
188
|
-
detectLocale as detectLocale2
|
|
188
|
+
detectLocale as detectLocale2,
|
|
189
|
+
getLocaleDisplayName,
|
|
190
|
+
getTranslationKeys,
|
|
191
|
+
trackMissingKeys,
|
|
192
|
+
getMissingKeys,
|
|
193
|
+
clearMissingKeys
|
|
189
194
|
} from "inline-i18n-multi";
|
|
190
195
|
export {
|
|
191
196
|
LocaleProvider,
|
|
@@ -194,6 +199,7 @@ export {
|
|
|
194
199
|
clearDictionaries,
|
|
195
200
|
clearFormatters,
|
|
196
201
|
clearICUCache,
|
|
202
|
+
clearMissingKeys,
|
|
197
203
|
configure,
|
|
198
204
|
createScope,
|
|
199
205
|
detectLocale2 as detectLocale,
|
|
@@ -206,6 +212,9 @@ export {
|
|
|
206
212
|
getDictionary,
|
|
207
213
|
getLoadedLocales,
|
|
208
214
|
getLocale,
|
|
215
|
+
getLocaleDisplayName,
|
|
216
|
+
getMissingKeys,
|
|
217
|
+
getTranslationKeys,
|
|
209
218
|
hasTranslation,
|
|
210
219
|
isLoaded2 as isLoaded,
|
|
211
220
|
it3 as it,
|
|
@@ -225,6 +234,7 @@ export {
|
|
|
225
234
|
restoreLocale,
|
|
226
235
|
setLocale2 as setLocale,
|
|
227
236
|
t,
|
|
237
|
+
trackMissingKeys,
|
|
228
238
|
useDetectedLocale,
|
|
229
239
|
useLoadDictionaries,
|
|
230
240
|
useLocale,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.tsx","../src/context.tsx","../src/hooks.ts","../src/component.tsx","../src/richtext.tsx","../src/index.ts"],"sourcesContent":["import { useState, useCallback, useMemo, useEffect, type ReactNode } from 'react'\nimport { setLocale as setCoreLocale, type Locale } from 'inline-i18n-multi'\nimport { LocaleContext } from './context'\n\ninterface LocaleProviderProps {\n /**\n * Initial locale value\n */\n locale: Locale\n /**\n * Cookie name for persisting locale (default: NEXT_LOCALE)\n * Set to false to disable cookie sync\n */\n cookieName?: string | false\n /**\n * Callback when locale changes\n */\n onLocaleChange?: (locale: Locale) => void\n children: ReactNode\n}\n\nfunction setCookie(name: string, value: string, days = 365): void {\n if (typeof document === 'undefined') return\n const expires = new Date(Date.now() + days * 864e5).toUTCString()\n document.cookie = `${name}=${value}; expires=${expires}; path=/; SameSite=Lax`\n}\n\nexport function LocaleProvider({\n locale: initialLocale,\n cookieName = 'NEXT_LOCALE',\n onLocaleChange,\n children,\n}: LocaleProviderProps) {\n const [locale, setLocaleState] = useState<Locale>(initialLocale)\n\n // sync with core package on mount and locale change\n useEffect(() => {\n setCoreLocale(locale)\n }, [locale])\n\n const setLocale = useCallback(\n (newLocale: Locale) => {\n setLocaleState(newLocale)\n setCoreLocale(newLocale)\n\n // sync cookie for Next.js middleware\n if (cookieName) {\n setCookie(cookieName, newLocale)\n }\n\n // callback for custom handling\n onLocaleChange?.(newLocale)\n },\n [cookieName, onLocaleChange]\n )\n\n const value = useMemo(() => ({ locale, setLocale }), [locale, setLocale])\n\n return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>\n}\n","import { createContext, useContext } from 'react'\nimport type { Locale } from 'inline-i18n-multi'\n\ninterface LocaleContextValue {\n locale: Locale\n setLocale: (locale: Locale) => void\n}\n\nexport const LocaleContext = createContext<LocaleContextValue | null>(null)\n\nexport function useLocaleContext(): LocaleContextValue {\n const context = useContext(LocaleContext)\n\n if (!context) {\n throw new Error('useLocaleContext must be used within a LocaleProvider')\n }\n\n return context\n}\n","import { useCallback, useState, useEffect } from 'react'\nimport { useLocaleContext } from './context'\nimport { t as coreT, loadAsync, isLoaded, detectLocale, setLocale } from 'inline-i18n-multi'\nimport type { Locale, TranslationVars, DetectLocaleOptions } from 'inline-i18n-multi'\n\n/**\n * Get current locale and setter\n */\nexport function useLocale(): [Locale, (locale: Locale) => void] {\n const { locale, setLocale } = useLocaleContext()\n return [locale, setLocale]\n}\n\n/**\n * Get translation function bound to current locale\n * @example\n * const t = useT()\n * t('greeting.hello') // uses context locale\n * t('items.count', { count: 5 })\n */\nexport function useT(): (key: string, vars?: TranslationVars) => string {\n const { locale } = useLocaleContext()\n\n return useCallback(\n (key: string, vars?: TranslationVars) => coreT(key, vars, locale),\n [locale]\n )\n}\n\n/**\n * Hook for lazy loading dictionaries\n * Automatically loads dictionaries when locale or namespace changes\n *\n * @example\n * function Dashboard() {\n * const { isLoading, error } = useLoadDictionaries('ko', 'dashboard')\n * if (isLoading) return <Spinner />\n * if (error) return <Error message={error.message} />\n * return <Content />\n * }\n */\nexport function useLoadDictionaries(\n locale: Locale,\n namespace?: string\n): { isLoading: boolean; error: Error | null } {\n const [isLoading, setIsLoading] = useState(() => !isLoaded(locale, namespace))\n const [error, setError] = useState<Error | null>(null)\n\n useEffect(() => {\n if (isLoaded(locale, namespace)) {\n setIsLoading(false)\n setError(null)\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n loadAsync(locale, namespace)\n .then(() => setIsLoading(false))\n .catch((err) => {\n setError(err instanceof Error ? err : new Error(String(err)))\n setIsLoading(false)\n })\n }, [locale, namespace])\n\n return { isLoading, error }\n}\n\n/**\n * Hook that auto-detects and sets locale on mount\n *\n * @example\n * function App() {\n * useDetectedLocale({\n * supportedLocales: ['en', 'ko', 'ja'],\n * defaultLocale: 'en',\n * sources: ['cookie', 'navigator'],\n * })\n * return <Content />\n * }\n */\n/**\n * Get a scoped translation function bound to current locale and namespace\n * @param namespace - Namespace to scope to\n * @example\n * const tc = useScopedT('common')\n * tc('greeting') // equivalent to t('common:greeting')\n */\nexport function useScopedT(namespace: string): (key: string, vars?: TranslationVars) => string {\n const { locale } = useLocaleContext()\n\n return useCallback(\n (key: string, vars?: TranslationVars) => coreT(`${namespace}:${key}`, vars, locale),\n [locale, namespace]\n )\n}\n\nexport function useDetectedLocale(options: DetectLocaleOptions): void {\n const { setLocale: setContextLocale } = useLocaleContext()\n\n useEffect(() => {\n const detected = detectLocale(options)\n setLocale(detected)\n setContextLocale(detected)\n // Run once on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n}\n","import { it, type Translations, type TranslationVars } from 'inline-i18n-multi'\n\ninterface TPropsShorthand {\n /**\n * Korean text\n */\n ko: string\n /**\n * English text\n */\n en: string\n translations?: never\n}\n\ninterface TPropsObject {\n ko?: never\n en?: never\n /**\n * Translation map with locale keys\n */\n translations: Translations\n}\n\ntype TProps = (TPropsShorthand | TPropsObject) & TranslationVars\n\n/**\n * Translation component for JSX\n * @example <T ko=\"안녕\" en=\"Hello\" />\n * @example <T translations={{ ko: '안녕', en: 'Hello', ja: 'こんにちは' }} />\n * @example <T ko=\"안녕 {name}\" en=\"Hello {name}\" name=\"철수\" />\n */\nexport function T(props: TProps) {\n const { ko, en, translations, ...vars } = props\n\n if (translations) {\n return <>{it(translations, vars)}</>\n }\n\n if (ko !== undefined && en !== undefined) {\n return <>{it(ko, en, vars)}</>\n }\n\n throw new Error('T component requires either \"translations\" or both \"ko\" and \"en\" props')\n}\n","import React, { type ReactNode, useMemo, useCallback, Fragment } from 'react'\nimport { it, parseRichText, type Translations, type TranslationVars } from 'inline-i18n-multi'\n\ntype ComponentRenderer = (text: string) => ReactNode\n\ninterface RichTextProps {\n /**\n * Translation map with locale keys\n * Tags like <link>text</link> will be matched to component renderers\n */\n translations: Translations\n /**\n * Component renderers for each tag name\n * @example { link: (text) => <a href=\"/terms\">{text}</a> }\n */\n components: Record<string, ComponentRenderer>\n /**\n * Variables for interpolation (applied before rich text parsing)\n */\n vars?: TranslationVars\n}\n\n/**\n * Rich text translation component\n * Supports embedding React components within translations\n *\n * @example\n * <RichText\n * translations={{\n * en: 'Read <link>terms</link> and <bold>agree</bold>',\n * ko: '<link>약관</link>을 읽고 <bold>동의</bold>해주세요'\n * }}\n * components={{\n * link: (text) => <a href=\"/terms\">{text}</a>,\n * bold: (text) => <strong>{text}</strong>\n * }}\n * />\n */\nexport function RichText({ translations, components, vars }: RichTextProps): React.JSX.Element {\n const componentNames = useMemo(() => Object.keys(components), [components])\n\n // Resolve locale and interpolate variables ({curly} braces)\n // Rich text tags (<angle> brackets) don't conflict with variable interpolation\n const resolved = it(translations, vars)\n const segments = parseRichText(resolved, componentNames)\n\n return (\n <>\n {segments.map((segment, index) => {\n if (segment.type === 'text') {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n const renderer = components[segment.componentName!]\n if (!renderer) {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n return <Fragment key={index}>{renderer(segment.content)}</Fragment>\n })}\n </>\n )\n}\n\n/**\n * Hook for rich text translations\n * Returns a function that resolves translations with component interpolation\n *\n * @example\n * const richT = useRichText({\n * link: (text) => <a href=\"/terms\">{text}</a>,\n * bold: (text) => <strong>{text}</strong>,\n * })\n * return richT({ en: 'Click <link>here</link>', ko: '<link>여기</link> 클릭' })\n */\nexport function useRichText(\n components: Record<string, ComponentRenderer>\n): (translations: Translations, vars?: TranslationVars) => ReactNode {\n const componentNames = useMemo(() => Object.keys(components), [components])\n\n return useCallback(\n (translations: Translations, vars?: TranslationVars): ReactNode => {\n const resolved = it(translations, vars)\n const segments = parseRichText(resolved, componentNames)\n\n return (\n <>\n {segments.map((segment, index) => {\n if (segment.type === 'text') {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n const renderer = components[segment.componentName!]\n if (!renderer) {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n return <Fragment key={index}>{renderer(segment.content)}</Fragment>\n })}\n </>\n )\n },\n [components, componentNames]\n )\n}\n","export { LocaleProvider } from './provider'\nexport { useLocale, useT, useScopedT, useLoadDictionaries, useDetectedLocale } from './hooks'\nexport { T } from './component'\nexport { RichText, useRichText } from './richtext'\n\n// re-export from core for convenience\nexport {\n // inline translations\n it,\n it_ja,\n it_zh,\n it_es,\n it_fr,\n it_de,\n en_ja,\n en_zh,\n en_es,\n en_fr,\n en_de,\n ja_zh,\n ja_es,\n zh_es,\n getLocale,\n setLocale,\n // key-based translations (i18n compatible)\n t,\n loadDictionaries,\n loadDictionary,\n clearDictionaries,\n hasTranslation,\n getLoadedLocales,\n getDictionary,\n loadAsync,\n isLoaded,\n // configuration\n configure,\n getConfig,\n resetConfig,\n // rich text parsing\n parseRichText,\n type RichTextSegment,\n // custom formatters (v0.6.0) + ICU cache (v0.7.0)\n registerFormatter,\n clearFormatters,\n clearICUCache,\n type CustomFormatter,\n // locale persistence (v0.7.0)\n restoreLocale,\n // translation scope (v0.8.0)\n createScope,\n // locale detection (v0.6.0)\n detectLocale,\n type DetectLocaleOptions,\n type DetectSource,\n // types\n type Locale,\n type Translations,\n type TranslationVars,\n type Dictionary,\n type Dictionaries,\n type PluralRules,\n} from 'inline-i18n-multi'\n"],"mappings":"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","names":["setLocale","useCallback","useState","useEffect","setLocale","useCallback","useState","useEffect","jsx","useMemo","useCallback","Fragment","it","jsx","it","setLocale","loadAsync","isLoaded","parseRichText","detectLocale"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/context.tsx","../src/hooks.ts","../src/component.tsx","../src/richtext.tsx","../src/index.ts"],"sourcesContent":["import { useState, useCallback, useMemo, useEffect, type ReactNode } from 'react'\nimport { setLocale as setCoreLocale, type Locale } from 'inline-i18n-multi'\nimport { LocaleContext } from './context'\n\ninterface LocaleProviderProps {\n /**\n * Initial locale value\n */\n locale: Locale\n /**\n * Cookie name for persisting locale (default: NEXT_LOCALE)\n * Set to false to disable cookie sync\n */\n cookieName?: string | false\n /**\n * Callback when locale changes\n */\n onLocaleChange?: (locale: Locale) => void\n children: ReactNode\n}\n\nfunction setCookie(name: string, value: string, days = 365): void {\n if (typeof document === 'undefined') return\n const expires = new Date(Date.now() + days * 864e5).toUTCString()\n document.cookie = `${name}=${value}; expires=${expires}; path=/; SameSite=Lax`\n}\n\nexport function LocaleProvider({\n locale: initialLocale,\n cookieName = 'NEXT_LOCALE',\n onLocaleChange,\n children,\n}: LocaleProviderProps) {\n const [locale, setLocaleState] = useState<Locale>(initialLocale)\n\n // sync with core package on mount and locale change\n useEffect(() => {\n setCoreLocale(locale)\n }, [locale])\n\n const setLocale = useCallback(\n (newLocale: Locale) => {\n setLocaleState(newLocale)\n setCoreLocale(newLocale)\n\n // sync cookie for Next.js middleware\n if (cookieName) {\n setCookie(cookieName, newLocale)\n }\n\n // callback for custom handling\n onLocaleChange?.(newLocale)\n },\n [cookieName, onLocaleChange]\n )\n\n const value = useMemo(() => ({ locale, setLocale }), [locale, setLocale])\n\n return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>\n}\n","import { createContext, useContext } from 'react'\nimport type { Locale } from 'inline-i18n-multi'\n\ninterface LocaleContextValue {\n locale: Locale\n setLocale: (locale: Locale) => void\n}\n\nexport const LocaleContext = createContext<LocaleContextValue | null>(null)\n\nexport function useLocaleContext(): LocaleContextValue {\n const context = useContext(LocaleContext)\n\n if (!context) {\n throw new Error('useLocaleContext must be used within a LocaleProvider')\n }\n\n return context\n}\n","import { useCallback, useState, useEffect } from 'react'\nimport { useLocaleContext } from './context'\nimport { t as coreT, loadAsync, isLoaded, detectLocale, setLocale } from 'inline-i18n-multi'\nimport type { Locale, TranslationVars, DetectLocaleOptions } from 'inline-i18n-multi'\n\n/**\n * Get current locale and setter\n */\nexport function useLocale(): [Locale, (locale: Locale) => void] {\n const { locale, setLocale } = useLocaleContext()\n return [locale, setLocale]\n}\n\n/**\n * Get translation function bound to current locale\n * @example\n * const t = useT()\n * t('greeting.hello') // uses context locale\n * t('items.count', { count: 5 })\n */\nexport function useT(): (key: string, vars?: TranslationVars) => string {\n const { locale } = useLocaleContext()\n\n return useCallback(\n (key: string, vars?: TranslationVars) => coreT(key, vars, locale),\n [locale]\n )\n}\n\n/**\n * Hook for lazy loading dictionaries\n * Automatically loads dictionaries when locale or namespace changes\n *\n * @example\n * function Dashboard() {\n * const { isLoading, error } = useLoadDictionaries('ko', 'dashboard')\n * if (isLoading) return <Spinner />\n * if (error) return <Error message={error.message} />\n * return <Content />\n * }\n */\nexport function useLoadDictionaries(\n locale: Locale,\n namespace?: string\n): { isLoading: boolean; error: Error | null } {\n const [isLoading, setIsLoading] = useState(() => !isLoaded(locale, namespace))\n const [error, setError] = useState<Error | null>(null)\n\n useEffect(() => {\n if (isLoaded(locale, namespace)) {\n setIsLoading(false)\n setError(null)\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n loadAsync(locale, namespace)\n .then(() => setIsLoading(false))\n .catch((err) => {\n setError(err instanceof Error ? err : new Error(String(err)))\n setIsLoading(false)\n })\n }, [locale, namespace])\n\n return { isLoading, error }\n}\n\n/**\n * Hook that auto-detects and sets locale on mount\n *\n * @example\n * function App() {\n * useDetectedLocale({\n * supportedLocales: ['en', 'ko', 'ja'],\n * defaultLocale: 'en',\n * sources: ['cookie', 'navigator'],\n * })\n * return <Content />\n * }\n */\n/**\n * Get a scoped translation function bound to current locale and namespace\n * @param namespace - Namespace to scope to\n * @example\n * const tc = useScopedT('common')\n * tc('greeting') // equivalent to t('common:greeting')\n */\nexport function useScopedT(namespace: string): (key: string, vars?: TranslationVars) => string {\n const { locale } = useLocaleContext()\n\n return useCallback(\n (key: string, vars?: TranslationVars) => coreT(`${namespace}:${key}`, vars, locale),\n [locale, namespace]\n )\n}\n\nexport function useDetectedLocale(options: DetectLocaleOptions): void {\n const { setLocale: setContextLocale } = useLocaleContext()\n\n useEffect(() => {\n const detected = detectLocale(options)\n setLocale(detected)\n setContextLocale(detected)\n // Run once on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n}\n","import { it, type Translations, type TranslationVars } from 'inline-i18n-multi'\n\ninterface TPropsShorthand {\n /**\n * Korean text\n */\n ko: string\n /**\n * English text\n */\n en: string\n translations?: never\n}\n\ninterface TPropsObject {\n ko?: never\n en?: never\n /**\n * Translation map with locale keys\n */\n translations: Translations\n}\n\ntype TProps = (TPropsShorthand | TPropsObject) & TranslationVars\n\n/**\n * Translation component for JSX\n * @example <T ko=\"안녕\" en=\"Hello\" />\n * @example <T translations={{ ko: '안녕', en: 'Hello', ja: 'こんにちは' }} />\n * @example <T ko=\"안녕 {name}\" en=\"Hello {name}\" name=\"철수\" />\n */\nexport function T(props: TProps) {\n const { ko, en, translations, ...vars } = props\n\n if (translations) {\n return <>{it(translations, vars)}</>\n }\n\n if (ko !== undefined && en !== undefined) {\n return <>{it(ko, en, vars)}</>\n }\n\n throw new Error('T component requires either \"translations\" or both \"ko\" and \"en\" props')\n}\n","import React, { type ReactNode, useMemo, useCallback, Fragment } from 'react'\nimport { it, parseRichText, type Translations, type TranslationVars } from 'inline-i18n-multi'\n\ntype ComponentRenderer = (text: string) => ReactNode\n\ninterface RichTextProps {\n /**\n * Translation map with locale keys\n * Tags like <link>text</link> will be matched to component renderers\n */\n translations: Translations\n /**\n * Component renderers for each tag name\n * @example { link: (text) => <a href=\"/terms\">{text}</a> }\n */\n components: Record<string, ComponentRenderer>\n /**\n * Variables for interpolation (applied before rich text parsing)\n */\n vars?: TranslationVars\n}\n\n/**\n * Rich text translation component\n * Supports embedding React components within translations\n *\n * @example\n * <RichText\n * translations={{\n * en: 'Read <link>terms</link> and <bold>agree</bold>',\n * ko: '<link>약관</link>을 읽고 <bold>동의</bold>해주세요'\n * }}\n * components={{\n * link: (text) => <a href=\"/terms\">{text}</a>,\n * bold: (text) => <strong>{text}</strong>\n * }}\n * />\n */\nexport function RichText({ translations, components, vars }: RichTextProps): React.JSX.Element {\n const componentNames = useMemo(() => Object.keys(components), [components])\n\n // Resolve locale and interpolate variables ({curly} braces)\n // Rich text tags (<angle> brackets) don't conflict with variable interpolation\n const resolved = it(translations, vars)\n const segments = parseRichText(resolved, componentNames)\n\n return (\n <>\n {segments.map((segment, index) => {\n if (segment.type === 'text') {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n const renderer = components[segment.componentName!]\n if (!renderer) {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n return <Fragment key={index}>{renderer(segment.content)}</Fragment>\n })}\n </>\n )\n}\n\n/**\n * Hook for rich text translations\n * Returns a function that resolves translations with component interpolation\n *\n * @example\n * const richT = useRichText({\n * link: (text) => <a href=\"/terms\">{text}</a>,\n * bold: (text) => <strong>{text}</strong>,\n * })\n * return richT({ en: 'Click <link>here</link>', ko: '<link>여기</link> 클릭' })\n */\nexport function useRichText(\n components: Record<string, ComponentRenderer>\n): (translations: Translations, vars?: TranslationVars) => ReactNode {\n const componentNames = useMemo(() => Object.keys(components), [components])\n\n return useCallback(\n (translations: Translations, vars?: TranslationVars): ReactNode => {\n const resolved = it(translations, vars)\n const segments = parseRichText(resolved, componentNames)\n\n return (\n <>\n {segments.map((segment, index) => {\n if (segment.type === 'text') {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n const renderer = components[segment.componentName!]\n if (!renderer) {\n return <Fragment key={index}>{segment.content}</Fragment>\n }\n return <Fragment key={index}>{renderer(segment.content)}</Fragment>\n })}\n </>\n )\n },\n [components, componentNames]\n )\n}\n","export { LocaleProvider } from './provider'\nexport { useLocale, useT, useScopedT, useLoadDictionaries, useDetectedLocale } from './hooks'\nexport { T } from './component'\nexport { RichText, useRichText } from './richtext'\n\n// re-export from core for convenience\nexport {\n // inline translations\n it,\n it_ja,\n it_zh,\n it_es,\n it_fr,\n it_de,\n en_ja,\n en_zh,\n en_es,\n en_fr,\n en_de,\n ja_zh,\n ja_es,\n zh_es,\n getLocale,\n setLocale,\n // key-based translations (i18n compatible)\n t,\n loadDictionaries,\n loadDictionary,\n clearDictionaries,\n hasTranslation,\n getLoadedLocales,\n getDictionary,\n loadAsync,\n isLoaded,\n // configuration\n configure,\n getConfig,\n resetConfig,\n // rich text parsing\n parseRichText,\n type RichTextSegment,\n // custom formatters (v0.6.0) + ICU cache (v0.7.0)\n registerFormatter,\n clearFormatters,\n clearICUCache,\n type CustomFormatter,\n // locale persistence (v0.7.0)\n restoreLocale,\n // translation scope (v0.8.0)\n createScope,\n // locale detection (v0.6.0)\n detectLocale,\n // utils (v0.11.0)\n getLocaleDisplayName,\n getTranslationKeys,\n trackMissingKeys,\n getMissingKeys,\n clearMissingKeys,\n type DetectLocaleOptions,\n type DetectSource,\n // types\n type Locale,\n type Translations,\n type TranslationVars,\n type Dictionary,\n type Dictionaries,\n type PluralRules,\n} from 'inline-i18n-multi'\n"],"mappings":";;;AAAA,SAAS,UAAU,aAAa,SAAS,iBAAiC;AAC1E,SAAS,aAAa,qBAAkC;;;ACDxD,SAAS,eAAe,kBAAkB;AAQnC,IAAM,gBAAgB,cAAyC,IAAI;AAEnE,SAAS,mBAAuC;AACrD,QAAM,UAAU,WAAW,aAAa;AAExC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEA,SAAO;AACT;;;ADwCS;AArCT,SAAS,UAAU,MAAc,OAAe,OAAO,KAAW;AAChE,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,UAAU,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,EAAE,YAAY;AAChE,WAAS,SAAS,GAAG,IAAI,IAAI,KAAK,aAAa,OAAO;AACxD;AAEO,SAAS,eAAe;AAAA,EAC7B,QAAQ;AAAA,EACR,aAAa;AAAA,EACb;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,CAAC,QAAQ,cAAc,IAAI,SAAiB,aAAa;AAG/D,YAAU,MAAM;AACd,kBAAc,MAAM;AAAA,EACtB,GAAG,CAAC,MAAM,CAAC;AAEX,QAAMA,aAAY;AAAA,IAChB,CAAC,cAAsB;AACrB,qBAAe,SAAS;AACxB,oBAAc,SAAS;AAGvB,UAAI,YAAY;AACd,kBAAU,YAAY,SAAS;AAAA,MACjC;AAGA,uBAAiB,SAAS;AAAA,IAC5B;AAAA,IACA,CAAC,YAAY,cAAc;AAAA,EAC7B;AAEA,QAAM,QAAQ,QAAQ,OAAO,EAAE,QAAQ,WAAAA,WAAU,IAAI,CAAC,QAAQA,UAAS,CAAC;AAExE,SAAO,oBAAC,cAAc,UAAd,EAAuB,OAAe,UAAS;AACzD;;;AE3DA,SAAS,eAAAC,cAAa,YAAAC,WAAU,aAAAC,kBAAiB;AAEjD,SAAS,KAAK,OAAO,WAAW,UAAU,cAAc,iBAAiB;AAMlE,SAAS,YAAgD;AAC9D,QAAM,EAAE,QAAQ,WAAAC,WAAU,IAAI,iBAAiB;AAC/C,SAAO,CAAC,QAAQA,UAAS;AAC3B;AASO,SAAS,OAAwD;AACtE,QAAM,EAAE,OAAO,IAAI,iBAAiB;AAEpC,SAAOC;AAAA,IACL,CAAC,KAAa,SAA2B,MAAM,KAAK,MAAM,MAAM;AAAA,IAChE,CAAC,MAAM;AAAA,EACT;AACF;AAcO,SAAS,oBACd,QACA,WAC6C;AAC7C,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAS,MAAM,CAAC,SAAS,QAAQ,SAAS,CAAC;AAC7E,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AAErD,EAAAC,WAAU,MAAM;AACd,QAAI,SAAS,QAAQ,SAAS,GAAG;AAC/B,mBAAa,KAAK;AAClB,eAAS,IAAI;AACb;AAAA,IACF;AAEA,iBAAa,IAAI;AACjB,aAAS,IAAI;AAEb,cAAU,QAAQ,SAAS,EACxB,KAAK,MAAM,aAAa,KAAK,CAAC,EAC9B,MAAM,CAAC,QAAQ;AACd,eAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAC5D,mBAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EACL,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,SAAO,EAAE,WAAW,MAAM;AAC5B;AAsBO,SAAS,WAAW,WAAoE;AAC7F,QAAM,EAAE,OAAO,IAAI,iBAAiB;AAEpC,SAAOF;AAAA,IACL,CAAC,KAAa,SAA2B,MAAM,GAAG,SAAS,IAAI,GAAG,IAAI,MAAM,MAAM;AAAA,IAClF,CAAC,QAAQ,SAAS;AAAA,EACpB;AACF;AAEO,SAAS,kBAAkB,SAAoC;AACpE,QAAM,EAAE,WAAW,iBAAiB,IAAI,iBAAiB;AAEzD,EAAAE,WAAU,MAAM;AACd,UAAM,WAAW,aAAa,OAAO;AACrC,cAAU,QAAQ;AAClB,qBAAiB,QAAQ;AAAA,EAG3B,GAAG,CAAC,CAAC;AACP;;;AC5GA,SAAS,UAAmD;AAmCjD,0BAAAC,YAAA;AAJJ,SAAS,EAAE,OAAe;AAC/B,QAAM,EAAE,IAAI,IAAI,cAAc,GAAG,KAAK,IAAI;AAE1C,MAAI,cAAc;AAChB,WAAO,gBAAAA,KAAA,YAAG,aAAG,cAAc,IAAI,GAAE;AAAA,EACnC;AAEA,MAAI,OAAO,UAAa,OAAO,QAAW;AACxC,WAAO,gBAAAA,KAAA,YAAG,aAAG,IAAI,IAAI,IAAI,GAAE;AAAA,EAC7B;AAEA,QAAM,IAAI,MAAM,wEAAwE;AAC1F;;;AC3CA,SAAgC,WAAAC,UAAS,eAAAC,cAAa,YAAAC,iBAAgB;AACtE,SAAS,MAAAC,KAAI,qBAA8D;AA8CvE,qBAAAD,WAGa,OAAAE,YAHb;AATG,SAAS,SAAS,EAAE,cAAc,YAAY,KAAK,GAAqC;AAC7F,QAAM,iBAAiBJ,SAAQ,MAAM,OAAO,KAAK,UAAU,GAAG,CAAC,UAAU,CAAC;AAI1E,QAAM,WAAWG,IAAG,cAAc,IAAI;AACtC,QAAM,WAAW,cAAc,UAAU,cAAc;AAEvD,SACE,gBAAAC,KAAAF,WAAA,EACG,mBAAS,IAAI,CAAC,SAAS,UAAU;AAChC,QAAI,QAAQ,SAAS,QAAQ;AAC3B,aAAO,gBAAAE,KAACF,WAAA,EAAsB,kBAAQ,WAAhB,KAAwB;AAAA,IAChD;AACA,UAAM,WAAW,WAAW,QAAQ,aAAc;AAClD,QAAI,CAAC,UAAU;AACb,aAAO,gBAAAE,KAACF,WAAA,EAAsB,kBAAQ,WAAhB,KAAwB;AAAA,IAChD;AACA,WAAO,gBAAAE,KAACF,WAAA,EAAsB,mBAAS,QAAQ,OAAO,KAAhC,KAAkC;AAAA,EAC1D,CAAC,GACH;AAEJ;AAaO,SAAS,YACd,YACmE;AACnE,QAAM,iBAAiBF,SAAQ,MAAM,OAAO,KAAK,UAAU,GAAG,CAAC,UAAU,CAAC;AAE1E,SAAOC;AAAA,IACL,CAAC,cAA4B,SAAsC;AACjE,YAAM,WAAWE,IAAG,cAAc,IAAI;AACtC,YAAM,WAAW,cAAc,UAAU,cAAc;AAEvD,aACE,gBAAAC,KAAAF,WAAA,EACG,mBAAS,IAAI,CAAC,SAAS,UAAU;AAChC,YAAI,QAAQ,SAAS,QAAQ;AAC3B,iBAAO,gBAAAE,KAACF,WAAA,EAAsB,kBAAQ,WAAhB,KAAwB;AAAA,QAChD;AACA,cAAM,WAAW,WAAW,QAAQ,aAAc;AAClD,YAAI,CAAC,UAAU;AACb,iBAAO,gBAAAE,KAACF,WAAA,EAAsB,kBAAQ,WAAhB,KAAwB;AAAA,QAChD;AACA,eAAO,gBAAAE,KAACF,WAAA,EAAsB,mBAAS,QAAQ,OAAO,KAAhC,KAAkC;AAAA,MAC1D,CAAC,GACH;AAAA,IAEJ;AAAA,IACA,CAAC,YAAY,cAAc;AAAA,EAC7B;AACF;;;AC9FA;AAAA,EAEE,MAAAG;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAAC;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAAC;AAAA,EACA,YAAAC;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,iBAAAC;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EAEA;AAAA,EAEA,gBAAAC;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAUK;","names":["setLocale","useCallback","useState","useEffect","setLocale","useCallback","useState","useEffect","jsx","useMemo","useCallback","Fragment","it","jsx","it","setLocale","loadAsync","isLoaded","parseRichText","detectLocale"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inline-i18n-multi-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "React integration for inline-i18n-multi",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"react": "^18.0.0 || ^19.0.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"inline-i18n-multi": "0.
|
|
37
|
+
"inline-i18n-multi": "0.11.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/react": "^19.0.2",
|