inline-i18n-multi-react 0.11.0 → 0.13.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 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, 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';
4
+ export { CustomFormatter, DetectLocaleOptions, DetectSource, Dictionaries, Dictionary, Locale, PluralRules, RichTextSegment, TranslationVars, Translations, clearDictionaries, clearFormatters, clearICUCache, clearLocaleListeners, clearMissingKeys, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, formatDate, formatList, formatNumber, 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, onLocaleChange, 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, 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';
4
+ export { CustomFormatter, DetectLocaleOptions, DetectSource, Dictionaries, Dictionary, Locale, PluralRules, RichTextSegment, TranslationVars, Translations, clearDictionaries, clearFormatters, clearICUCache, clearLocaleListeners, clearMissingKeys, configure, createScope, detectLocale, en_de, en_es, en_fr, en_ja, en_zh, formatDate, formatList, formatNumber, 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, onLocaleChange, 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
+ clearLocaleListeners: () => import_inline_i18n_multi5.clearLocaleListeners,
30
31
  clearMissingKeys: () => import_inline_i18n_multi5.clearMissingKeys,
31
32
  configure: () => import_inline_i18n_multi5.configure,
32
33
  createScope: () => import_inline_i18n_multi5.createScope,
@@ -36,6 +37,9 @@ __export(index_exports, {
36
37
  en_fr: () => import_inline_i18n_multi5.en_fr,
37
38
  en_ja: () => import_inline_i18n_multi5.en_ja,
38
39
  en_zh: () => import_inline_i18n_multi5.en_zh,
40
+ formatDate: () => import_inline_i18n_multi5.formatDate,
41
+ formatList: () => import_inline_i18n_multi5.formatList,
42
+ formatNumber: () => import_inline_i18n_multi5.formatNumber,
39
43
  getConfig: () => import_inline_i18n_multi5.getConfig,
40
44
  getDictionary: () => import_inline_i18n_multi5.getDictionary,
41
45
  getLoadedLocales: () => import_inline_i18n_multi5.getLoadedLocales,
@@ -56,6 +60,7 @@ __export(index_exports, {
56
60
  loadAsync: () => import_inline_i18n_multi5.loadAsync,
57
61
  loadDictionaries: () => import_inline_i18n_multi5.loadDictionaries,
58
62
  loadDictionary: () => import_inline_i18n_multi5.loadDictionary,
63
+ onLocaleChange: () => import_inline_i18n_multi5.onLocaleChange,
59
64
  parseRichText: () => import_inline_i18n_multi5.parseRichText,
60
65
  registerFormatter: () => import_inline_i18n_multi5.registerFormatter,
61
66
  resetConfig: () => import_inline_i18n_multi5.resetConfig,
@@ -98,7 +103,7 @@ function setCookie(name, value, days = 365) {
98
103
  function LocaleProvider({
99
104
  locale: initialLocale,
100
105
  cookieName = "NEXT_LOCALE",
101
- onLocaleChange,
106
+ onLocaleChange: onLocaleChange2,
102
107
  children
103
108
  }) {
104
109
  const [locale, setLocaleState] = (0, import_react2.useState)(initialLocale);
@@ -112,9 +117,9 @@ function LocaleProvider({
112
117
  if (cookieName) {
113
118
  setCookie(cookieName, newLocale);
114
119
  }
115
- onLocaleChange?.(newLocale);
120
+ onLocaleChange2?.(newLocale);
116
121
  },
117
- [cookieName, onLocaleChange]
122
+ [cookieName, onLocaleChange2]
118
123
  );
119
124
  const value = (0, import_react2.useMemo)(() => ({ locale, setLocale: setLocale3 }), [locale, setLocale3]);
120
125
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LocaleContext.Provider, { value, children });
@@ -232,6 +237,7 @@ var import_inline_i18n_multi5 = require("inline-i18n-multi");
232
237
  clearDictionaries,
233
238
  clearFormatters,
234
239
  clearICUCache,
240
+ clearLocaleListeners,
235
241
  clearMissingKeys,
236
242
  configure,
237
243
  createScope,
@@ -241,6 +247,9 @@ var import_inline_i18n_multi5 = require("inline-i18n-multi");
241
247
  en_fr,
242
248
  en_ja,
243
249
  en_zh,
250
+ formatDate,
251
+ formatList,
252
+ formatNumber,
244
253
  getConfig,
245
254
  getDictionary,
246
255
  getLoadedLocales,
@@ -261,6 +270,7 @@ var import_inline_i18n_multi5 = require("inline-i18n-multi");
261
270
  loadAsync,
262
271
  loadDictionaries,
263
272
  loadDictionary,
273
+ onLocaleChange,
264
274
  parseRichText,
265
275
  registerFormatter,
266
276
  resetConfig,
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 // 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"]}
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 // locale change event (v0.12.0)\n onLocaleChange,\n clearLocaleListeners,\n // utils (v0.11.0)\n getLocaleDisplayName,\n getTranslationKeys,\n trackMissingKeys,\n getMissingKeys,\n clearMissingKeys,\n // formatting utilities (v0.13.0)\n formatNumber,\n formatDate,\n formatList,\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","onLocaleChange","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
@@ -25,7 +25,7 @@ function setCookie(name, value, days = 365) {
25
25
  function LocaleProvider({
26
26
  locale: initialLocale,
27
27
  cookieName = "NEXT_LOCALE",
28
- onLocaleChange,
28
+ onLocaleChange: onLocaleChange2,
29
29
  children
30
30
  }) {
31
31
  const [locale, setLocaleState] = useState(initialLocale);
@@ -39,9 +39,9 @@ function LocaleProvider({
39
39
  if (cookieName) {
40
40
  setCookie(cookieName, newLocale);
41
41
  }
42
- onLocaleChange?.(newLocale);
42
+ onLocaleChange2?.(newLocale);
43
43
  },
44
- [cookieName, onLocaleChange]
44
+ [cookieName, onLocaleChange2]
45
45
  );
46
46
  const value = useMemo(() => ({ locale, setLocale: setLocale3 }), [locale, setLocale3]);
47
47
  return /* @__PURE__ */ jsx(LocaleContext.Provider, { value, children });
@@ -186,11 +186,16 @@ import {
186
186
  restoreLocale,
187
187
  createScope,
188
188
  detectLocale as detectLocale2,
189
+ onLocaleChange,
190
+ clearLocaleListeners,
189
191
  getLocaleDisplayName,
190
192
  getTranslationKeys,
191
193
  trackMissingKeys,
192
194
  getMissingKeys,
193
- clearMissingKeys
195
+ clearMissingKeys,
196
+ formatNumber,
197
+ formatDate,
198
+ formatList
194
199
  } from "inline-i18n-multi";
195
200
  export {
196
201
  LocaleProvider,
@@ -199,6 +204,7 @@ export {
199
204
  clearDictionaries,
200
205
  clearFormatters,
201
206
  clearICUCache,
207
+ clearLocaleListeners,
202
208
  clearMissingKeys,
203
209
  configure,
204
210
  createScope,
@@ -208,6 +214,9 @@ export {
208
214
  en_fr,
209
215
  en_ja,
210
216
  en_zh,
217
+ formatDate,
218
+ formatList,
219
+ formatNumber,
211
220
  getConfig,
212
221
  getDictionary,
213
222
  getLoadedLocales,
@@ -228,6 +237,7 @@ export {
228
237
  loadAsync2 as loadAsync,
229
238
  loadDictionaries,
230
239
  loadDictionary,
240
+ onLocaleChange,
231
241
  parseRichText2 as parseRichText,
232
242
  registerFormatter,
233
243
  resetConfig,
@@ -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 // 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":"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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 // locale change event (v0.12.0)\n onLocaleChange,\n clearLocaleListeners,\n // utils (v0.11.0)\n getLocaleDisplayName,\n getTranslationKeys,\n trackMissingKeys,\n getMissingKeys,\n clearMissingKeys,\n // formatting utilities (v0.13.0)\n formatNumber,\n formatDate,\n formatList,\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":["onLocaleChange","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.11.0",
3
+ "version": "0.13.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.11.0"
37
+ "inline-i18n-multi": "0.13.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/react": "^19.0.2",