@tolgee/react 5.33.2 → 5.33.3-prerelease.2efc0e6b.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.
Files changed (45) hide show
  1. package/dist/TolgeeProvider.d.ts +2 -2
  2. package/dist/createServerInstance.d.ts +3 -2
  3. package/dist/tolgee-react-server.cjs.js +10 -1
  4. package/dist/tolgee-react-server.cjs.js.map +1 -1
  5. package/dist/tolgee-react-server.cjs.min.js +1 -1
  6. package/dist/tolgee-react-server.cjs.min.js.map +1 -1
  7. package/dist/tolgee-react-server.esm.js +10 -1
  8. package/dist/tolgee-react-server.esm.js.map +1 -1
  9. package/dist/tolgee-react-server.esm.min.js +1 -1
  10. package/dist/tolgee-react-server.esm.min.js.map +1 -1
  11. package/dist/tolgee-react-server.esm.min.mjs +1 -1
  12. package/dist/tolgee-react-server.esm.min.mjs.map +1 -1
  13. package/dist/tolgee-react-server.esm.mjs +10 -1
  14. package/dist/tolgee-react-server.esm.mjs.map +1 -1
  15. package/dist/tolgee-react-server.umd.js +10 -1
  16. package/dist/tolgee-react-server.umd.js.map +1 -1
  17. package/dist/tolgee-react-server.umd.min.js +1 -1
  18. package/dist/tolgee-react-server.umd.min.js.map +1 -1
  19. package/dist/tolgee-react.cjs.js +9 -20
  20. package/dist/tolgee-react.cjs.js.map +1 -1
  21. package/dist/tolgee-react.cjs.min.js +1 -1
  22. package/dist/tolgee-react.cjs.min.js.map +1 -1
  23. package/dist/tolgee-react.esm.js +9 -20
  24. package/dist/tolgee-react.esm.js.map +1 -1
  25. package/dist/tolgee-react.esm.min.js +1 -1
  26. package/dist/tolgee-react.esm.min.js.map +1 -1
  27. package/dist/tolgee-react.esm.min.mjs +1 -1
  28. package/dist/tolgee-react.esm.min.mjs.map +1 -1
  29. package/dist/tolgee-react.esm.mjs +9 -20
  30. package/dist/tolgee-react.esm.mjs.map +1 -1
  31. package/dist/tolgee-react.umd.js +9 -20
  32. package/dist/tolgee-react.umd.js.map +1 -1
  33. package/dist/tolgee-react.umd.min.js +1 -1
  34. package/dist/tolgee-react.umd.min.js.map +1 -1
  35. package/dist/useTolgeeSSR.d.ts +2 -2
  36. package/lib/TolgeeProvider.d.ts +2 -2
  37. package/lib/createServerInstance.d.ts +3 -2
  38. package/lib/useTolgeeSSR.d.ts +2 -2
  39. package/package.json +5 -5
  40. package/src/TolgeeProvider.tsx +3 -3
  41. package/src/__integration/namespaces.spec.tsx +7 -9
  42. package/src/__integration/useTolgee.spec.tsx +5 -0
  43. package/src/createServerInstance.tsx +21 -8
  44. package/src/useTolgeeSSR.ts +8 -6
  45. package/src/useTranslateInternal.ts +1 -15
@@ -1 +1 @@
1
- {"version":3,"file":"tolgee-react.umd.min.js","sources":["../src/useTolgeeSSR.ts","../src/TolgeeProvider.tsx","../src/GlobalContextPlugin.tsx","../src/useTolgeeContext.ts","../src/hooks.ts","../src/useTranslateInternal.ts","../src/tagsTools.tsx","../src/TBase.tsx","../src/T.tsx","../src/useTolgee.ts","../src/useTranslate.ts"],"sourcesContent":["import {\n getTranslateProps,\n TolgeeInstance,\n TolgeeStaticData,\n} from '@tolgee/web';\nimport { useEffect, useMemo, useState } from 'react';\n\nfunction getTolgeeWithDeactivatedWrapper(\n tolgee: TolgeeInstance\n): TolgeeInstance {\n return {\n ...tolgee,\n t(...args) {\n // @ts-ignore\n const props = getTranslateProps(...args);\n return tolgee.t({ ...props, noWrap: true });\n },\n };\n}\n\n/**\n * Updates tolgee static data and language, to be ready right away for the first render\n * and therefore compatible with SSR.\n *\n * It also ensures that the first render is done without wrapping and so it avoids\n * \"client different than server\" issues.\n * *\n * @param tolgeeInstance initialized Tolgee instance\n * @param language language that is obtained outside of Tolgee on the server and client\n * @param staticData static data for the language\n * @param enabled if set to false, no action is taken\n */\nexport function useTolgeeSSR(\n tolgeeInstance: TolgeeInstance,\n language?: string,\n staticData?: TolgeeStaticData | undefined,\n enabled = true\n) {\n const [noWrappingTolgee] = useState(() =>\n getTolgeeWithDeactivatedWrapper(tolgeeInstance)\n );\n\n const [initialRender, setInitialRender] = useState(enabled);\n\n useEffect(() => {\n setInitialRender(false);\n }, []);\n\n useMemo(() => {\n if (enabled) {\n // we have to prepare tolgee before rendering children\n // so translations are available right away\n // events emitting must be off, to not trigger re-render while rendering\n tolgeeInstance.setEmitterActive(false);\n tolgeeInstance.addStaticData(staticData);\n tolgeeInstance.changeLanguage(language!);\n tolgeeInstance.setEmitterActive(true);\n }\n }, [language, staticData, tolgeeInstance]);\n\n useState(() => {\n // running this function only on first render\n if (!tolgeeInstance.isLoaded() && enabled) {\n // warning user, that static data provided are not sufficient\n // for proper SSR render\n const missingRecords = tolgeeInstance\n .getRequiredRecords(language)\n .map(({ namespace, language }) =>\n namespace ? `${namespace}:${language}` : language\n )\n .filter((key) => !staticData?.[key]);\n\n // eslint-disable-next-line no-console\n console.warn(\n `Tolgee: Missing records in \"staticData\" for proper SSR functionality: ${missingRecords.map((key) => `\"${key}\"`).join(', ')}`\n );\n }\n });\n\n return initialRender ? noWrappingTolgee : tolgeeInstance;\n}\n","import React, { Suspense, useEffect, useState } from 'react';\nimport { TolgeeInstance, TolgeeStaticData } from '@tolgee/web';\nimport { ReactOptions, TolgeeReactContext } from './types';\nimport { useTolgeeSSR } from './useTolgeeSSR';\n\nexport const DEFAULT_REACT_OPTIONS: ReactOptions = {\n useSuspense: true,\n};\n\nlet ProviderInstance: React.Context<TolgeeReactContext | undefined>;\n\nexport const getProviderInstance = () => {\n if (!ProviderInstance) {\n ProviderInstance = React.createContext<TolgeeReactContext | undefined>(\n undefined\n );\n }\n\n return ProviderInstance;\n};\n\nlet LAST_TOLGEE_INSTANCE: TolgeeInstance | undefined = undefined;\n\nexport type SSROptions = {\n /**\n * Hard set language to this value, use together with `staticData`\n */\n language?: string;\n /**\n * If provided, static data will be hard set to Tolgee cache for initial render\n */\n staticData?: TolgeeStaticData;\n};\n\nexport interface TolgeeProviderProps {\n children?: React.ReactNode;\n tolgee: TolgeeInstance;\n options?: ReactOptions;\n fallback?: React.ReactNode;\n /**\n * use this option if you use SSR\n *\n * You can pass staticData and language\n * which will be set to tolgee instance for the initial render\n *\n * Don't switch between ssr and non-ssr dynamically\n */\n ssr?: SSROptions | boolean;\n}\n\nexport const TolgeeProvider: React.FC<TolgeeProviderProps> = ({\n tolgee,\n options,\n children,\n fallback,\n ssr,\n}) => {\n // prevent restarting tolgee unnecesarly\n // however if the instance change on hot-reloading\n // we want to restart\n useEffect(() => {\n if (LAST_TOLGEE_INSTANCE?.run !== tolgee.run) {\n if (LAST_TOLGEE_INSTANCE) {\n LAST_TOLGEE_INSTANCE.stop();\n }\n LAST_TOLGEE_INSTANCE = tolgee;\n tolgee\n .run()\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n })\n .finally(() => {\n setLoading(false);\n });\n }\n }, [tolgee]);\n\n let tolgeeSSR = tolgee;\n\n const { language, staticData } = (\n typeof ssr !== 'object' ? {} : ssr\n ) as SSROptions;\n tolgeeSSR = useTolgeeSSR(tolgee, language, staticData, Boolean(ssr));\n\n const [loading, setLoading] = useState(!tolgeeSSR.isLoaded());\n\n const optionsWithDefault = { ...DEFAULT_REACT_OPTIONS, ...options };\n\n const TolgeeProviderContext = getProviderInstance();\n\n if (optionsWithDefault.useSuspense) {\n return (\n <TolgeeProviderContext.Provider\n value={{ tolgee: tolgeeSSR, options: optionsWithDefault }}\n >\n {loading ? (\n fallback\n ) : (\n <Suspense fallback={fallback || null}>{children}</Suspense>\n )}\n </TolgeeProviderContext.Provider>\n );\n }\n\n return (\n <TolgeeProviderContext.Provider\n value={{ tolgee: tolgeeSSR, options: optionsWithDefault }}\n >\n {loading ? fallback : children}\n </TolgeeProviderContext.Provider>\n );\n};\n","import type { TolgeePlugin } from '@tolgee/web';\nimport { DEFAULT_REACT_OPTIONS } from './TolgeeProvider';\nimport type { ReactOptions, TolgeeReactContext } from './types';\n\nlet globalContext: TolgeeReactContext | undefined;\n\nexport const GlobalContextPlugin =\n (options?: Partial<ReactOptions>): TolgeePlugin =>\n (tolgee) => {\n globalContext = {\n tolgee,\n options: { ...DEFAULT_REACT_OPTIONS, ...options },\n };\n return tolgee;\n };\n\nexport function getGlobalContext() {\n return globalContext;\n}\n","import { useContext } from 'react';\nimport { getGlobalContext } from './GlobalContextPlugin';\nimport { getProviderInstance } from './TolgeeProvider';\n\nexport const useTolgeeContext = () => {\n const TolgeeProviderContext = getProviderInstance();\n const context = useContext(TolgeeProviderContext) || getGlobalContext();\n if (!context) {\n throw new Error(\n \"Couldn't find tolgee instance, did you forgot to use `TolgeeProvider`?\"\n );\n }\n return context;\n};\n","import { useCallback, useState } from 'react';\n\nexport const useRerender = () => {\n const [instance, setCounter] = useState(0);\n\n const rerender = useCallback(() => {\n setCounter((num) => num + 1);\n }, [setCounter]);\n return { instance, rerender };\n};\n","import { useCallback, useEffect, useRef } from 'react';\nimport {\n SubscriptionSelective,\n TranslateProps,\n NsFallback,\n getFallbackArray,\n getFallback,\n} from '@tolgee/web';\n\nimport { useTolgeeContext } from './useTolgeeContext';\nimport { ReactOptions } from './types';\nimport { useRerender } from './hooks';\n\nexport const useTranslateInternal = (\n ns?: NsFallback,\n options?: ReactOptions\n) => {\n const { tolgee, options: defaultOptions } = useTolgeeContext();\n const namespaces = getFallback(ns);\n const namespacesJoined = getFallbackArray(namespaces).join(':');\n\n const currentOptions = {\n ...defaultOptions,\n ...options,\n };\n\n // dummy state to enable re-rendering\n const { rerender, instance } = useRerender();\n\n const subscriptionRef = useRef<SubscriptionSelective>();\n\n const subscriptionQueue = useRef([] as NsFallback[]);\n subscriptionQueue.current = [];\n\n const subscribeToNs = (ns: NsFallback) => {\n subscriptionQueue.current.push(ns);\n subscriptionRef.current?.subscribeNs(ns);\n };\n\n const isLoaded = tolgee.isLoaded(namespaces);\n\n useEffect(() => {\n const subscription = tolgee.onNsUpdate(rerender);\n subscriptionRef.current = subscription;\n subscription.subscribeNs(namespaces);\n subscriptionQueue.current.forEach((ns) => {\n subscription!.subscribeNs(ns);\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [namespacesJoined, tolgee]);\n\n useEffect(() => {\n tolgee.addActiveNs(namespaces);\n return () => tolgee.removeActiveNs(namespaces);\n }, [namespacesJoined, tolgee]);\n\n const t = useCallback(\n (props: TranslateProps<any>) => {\n const fallbackNs = props.ns ?? namespaces?.[0];\n subscribeToNs(fallbackNs);\n return tolgee.t({ ...props, ns: fallbackNs }) as any;\n },\n [tolgee, instance]\n );\n\n if (currentOptions.useSuspense && !isLoaded) {\n throw tolgee.addActiveNs(namespaces, true);\n }\n\n return { t, isLoading: !isLoaded };\n};\n","import { TranslateParams } from '@tolgee/web';\nimport React from 'react';\n\nimport { ParamsTags } from './types';\n\nfunction unwrapSingleElementArray(value: any) {\n if (Array.isArray(value) && value.length === 1) {\n return value[0];\n } else {\n return value;\n }\n}\n\nexport const wrapTagHandlers = (\n params: TranslateParams<ParamsTags> | undefined\n) => {\n if (!params) {\n return undefined;\n }\n\n const result: any = {};\n\n Object.entries(params || {}).forEach(([key, value]) => {\n if (typeof value === 'function') {\n result[key] = (chunk: any) => {\n return value(addReactKeys(chunk));\n };\n } else if (React.isValidElement(value as any)) {\n const el = value as React.ReactElement;\n result[key] = (chunk: any) => {\n return el.props.children === undefined && chunk?.length\n ? React.cloneElement(el, {}, addReactKeys(chunk))\n : React.cloneElement(el);\n };\n } else {\n result[key] = value;\n }\n });\n\n return result;\n};\n\nexport const addReactKeys = (\n children: React.ReactNode | React.ReactNode[] | undefined\n) => {\n const val = unwrapSingleElementArray(children);\n if (Array.isArray(val)) {\n return val.map((item, i) => (\n <React.Fragment key={i}>{item}</React.Fragment>\n ));\n } else {\n return val;\n }\n};\n","import React from 'react';\nimport { addReactKeys, wrapTagHandlers } from './tagsTools';\nimport type { PropsWithKeyName, TBaseInterface } from './types';\n\nexport const TBase: TBaseInterface = (props) => {\n const key = (props as PropsWithKeyName).keyName || props.children;\n if (key === undefined) {\n // eslint-disable-next-line no-console\n console.error('T component: keyName not defined');\n }\n const defaultValue =\n props.defaultValue ||\n ((props as PropsWithKeyName).keyName ? props.children : undefined);\n\n const translation = addReactKeys(\n props.t({\n key: key!,\n params: wrapTagHandlers(props.params),\n defaultValue,\n noWrap: props.noWrap,\n ns: props.ns,\n language: props.language,\n })\n );\n\n return <>{translation}</>;\n};\n","import React from 'react';\nimport { ParamsTags, TProps } from './types';\n\nimport { useTranslateInternal } from './useTranslateInternal';\nimport { TFnType } from '@tolgee/web';\nimport { TBase } from './TBase';\n\ninterface TInterface {\n (props: TProps): JSX.Element;\n}\n\nexport const T: TInterface = (props) => {\n const { t } = useTranslateInternal();\n\n return <TBase t={t as TFnType<ParamsTags>} {...props} />;\n};\n","import { TolgeeEvent, TolgeeInstance } from '@tolgee/web';\nimport { useEffect } from 'react';\nimport { useRerender } from './hooks';\nimport { useTolgeeContext } from './useTolgeeContext';\n\nexport const useTolgee = (events?: TolgeeEvent[]): TolgeeInstance => {\n const { tolgee } = useTolgeeContext();\n\n const { rerender } = useRerender();\n\n useEffect(() => {\n const listeners = events?.map((e) => tolgee.on(e, rerender));\n return () => {\n listeners?.forEach((listener) => listener.unsubscribe());\n };\n }, [events?.join(':')]);\n\n return tolgee;\n};\n","import { useCallback } from 'react';\nimport {\n TFnType,\n getTranslateProps,\n DefaultParamType,\n TranslationKey,\n} from '@tolgee/web';\n\nimport { useTranslateInternal } from './useTranslateInternal';\nimport { ReactOptions } from './types';\n\nexport interface UseTranslateResult {\n t: TFnType<DefaultParamType, string, TranslationKey>;\n isLoading: boolean;\n}\n\nexport const useTranslate = (\n ns?: string[] | string,\n options?: ReactOptions\n): UseTranslateResult => {\n const { t: tInternal, isLoading } = useTranslateInternal(ns, options);\n\n const t = useCallback(\n (...params: any) => {\n // @ts-ignore\n const props = getTranslateProps(...params);\n return tInternal(props);\n },\n [tInternal]\n );\n\n return { t, isLoading };\n};\n"],"names":["useTolgeeSSR","tolgeeInstance","language","staticData","enabled","noWrappingTolgee","useState","getTolgeeWithDeactivatedWrapper","tolgee","Object","assign","t","args","props","getTranslateProps","noWrap","initialRender","setInitialRender","useEffect","useMemo","setEmitterActive","addStaticData","changeLanguage","isLoaded","missingRecords","getRequiredRecords","map","namespace","filter","key","console","warn","join","DEFAULT_REACT_OPTIONS","useSuspense","ProviderInstance","getProviderInstance","React","createContext","undefined","LAST_TOLGEE_INSTANCE","globalContext","useTolgeeContext","TolgeeProviderContext","context","useContext","Error","useRerender","instance","setCounter","rerender","useCallback","num","useTranslateInternal","ns","options","defaultOptions","namespaces","getFallback","namespacesJoined","getFallbackArray","currentOptions","subscriptionRef","useRef","subscriptionQueue","current","subscription","onNsUpdate","subscribeNs","forEach","unsubscribe","addActiveNs","removeActiveNs","fallbackNs","_a","push","subscribeToNs","isLoading","wrapTagHandlers","params","result","entries","value","chunk","addReactKeys","isValidElement","el","children","length","cloneElement","val","Array","isArray","item","i","Fragment","TBase","keyName","error","defaultValue","translation","createElement","fallback","ssr","run","stop","catch","e","finally","setLoading","tolgeeSSR","Boolean","loading","optionsWithDefault","Provider","Suspense","events","listeners","on","listener","tInternal"],"mappings":"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"}
1
+ {"version":3,"file":"tolgee-react.umd.min.js","sources":["../src/useTolgeeSSR.ts","../src/TolgeeProvider.tsx","../src/GlobalContextPlugin.tsx","../src/useTolgeeContext.ts","../src/hooks.ts","../src/useTranslateInternal.ts","../src/tagsTools.tsx","../src/TBase.tsx","../src/T.tsx","../src/useTolgee.ts","../src/useTranslate.ts"],"sourcesContent":["import {\n CachePublicRecord,\n getTranslateProps,\n TolgeeInstance,\n TolgeeStaticData,\n} from '@tolgee/web';\nimport { useEffect, useMemo, useState } from 'react';\n\nfunction getTolgeeWithDeactivatedWrapper(\n tolgee: TolgeeInstance\n): TolgeeInstance {\n return {\n ...tolgee,\n t(...args) {\n // @ts-ignore\n const props = getTranslateProps(...args);\n return tolgee.t({ ...props, noWrap: true });\n },\n };\n}\n\n/**\n * Updates tolgee static data and language, to be ready right away for the first render\n * and therefore compatible with SSR.\n *\n * It also ensures that the first render is done without wrapping and so it avoids\n * \"client different than server\" issues.\n * *\n * @param tolgeeInstance initialized Tolgee instance\n * @param language language that is obtained outside of Tolgee on the server and client\n * @param staticData static data for the language\n * @param enabled if set to false, no action is taken\n */\nexport function useTolgeeSSR(\n tolgeeInstance: TolgeeInstance,\n language?: string,\n data?: TolgeeStaticData | CachePublicRecord[] | undefined,\n enabled = true\n) {\n const [noWrappingTolgee] = useState(() =>\n getTolgeeWithDeactivatedWrapper(tolgeeInstance)\n );\n\n const [initialRender, setInitialRender] = useState(enabled);\n\n useEffect(() => {\n setInitialRender(false);\n }, []);\n\n useMemo(() => {\n if (enabled) {\n // we have to prepare tolgee before rendering children\n // so translations are available right away\n // events emitting must be off, to not trigger re-render while rendering\n tolgeeInstance.setEmitterActive(false);\n tolgeeInstance.addStaticData(data);\n tolgeeInstance.changeLanguage(language!);\n tolgeeInstance.setEmitterActive(true);\n }\n }, [language, data, tolgeeInstance]);\n\n useState(() => {\n // running this function only on first render\n if (!tolgeeInstance.isLoaded() && enabled) {\n // warning user, that static data provided are not sufficient\n // for proper SSR render\n const requiredRecords = tolgeeInstance.getRequiredDescriptors(language);\n const providedRecords = tolgeeInstance.getAllRecords();\n const missingRecords = requiredRecords\n .map(({ namespace, language }) =>\n namespace ? `${namespace}:${language}` : language\n )\n .filter((key) => !providedRecords.find((r) => r?.cacheKey === key));\n\n // eslint-disable-next-line no-console\n console.warn(\n `Tolgee: Missing records in \"staticData\" for proper SSR functionality: ${missingRecords.map((key) => `\"${key}\"`).join(', ')}`\n );\n }\n });\n\n return initialRender ? noWrappingTolgee : tolgeeInstance;\n}\n","import React, { Suspense, useEffect, useState } from 'react';\nimport { TolgeeInstance, TolgeeStaticDataProp } from '@tolgee/web';\nimport { ReactOptions, TolgeeReactContext } from './types';\nimport { useTolgeeSSR } from './useTolgeeSSR';\n\nexport const DEFAULT_REACT_OPTIONS: ReactOptions = {\n useSuspense: false,\n};\n\nlet ProviderInstance: React.Context<TolgeeReactContext | undefined>;\n\nexport const getProviderInstance = () => {\n if (!ProviderInstance) {\n ProviderInstance = React.createContext<TolgeeReactContext | undefined>(\n undefined\n );\n }\n\n return ProviderInstance;\n};\n\nlet LAST_TOLGEE_INSTANCE: TolgeeInstance | undefined = undefined;\n\nexport type SSROptions = {\n /**\n * Hard set language to this value, use together with `staticData`\n */\n language?: string;\n /**\n * If provided, static data will be hard set to Tolgee cache for initial render\n */\n staticData?: TolgeeStaticDataProp;\n};\n\nexport interface TolgeeProviderProps {\n children?: React.ReactNode;\n tolgee: TolgeeInstance;\n options?: ReactOptions;\n fallback?: React.ReactNode;\n /**\n * use this option if you use SSR\n *\n * You can pass staticData and language\n * which will be set to tolgee instance for the initial render\n *\n * Don't switch between ssr and non-ssr dynamically\n */\n ssr?: SSROptions | boolean;\n}\n\nexport const TolgeeProvider: React.FC<TolgeeProviderProps> = ({\n tolgee,\n options,\n children,\n fallback,\n ssr,\n}) => {\n // prevent restarting tolgee unnecesarly\n // however if the instance change on hot-reloading\n // we want to restart\n useEffect(() => {\n if (LAST_TOLGEE_INSTANCE?.run !== tolgee.run) {\n if (LAST_TOLGEE_INSTANCE) {\n LAST_TOLGEE_INSTANCE.stop();\n }\n LAST_TOLGEE_INSTANCE = tolgee;\n tolgee\n .run()\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n })\n .finally(() => {\n setLoading(false);\n });\n }\n }, [tolgee]);\n\n let tolgeeSSR = tolgee;\n\n const { language, staticData } = (\n typeof ssr !== 'object' ? {} : ssr\n ) as SSROptions;\n tolgeeSSR = useTolgeeSSR(tolgee, language, staticData, Boolean(ssr));\n\n const [loading, setLoading] = useState(!tolgeeSSR.isLoaded());\n\n const optionsWithDefault = { ...DEFAULT_REACT_OPTIONS, ...options };\n\n const TolgeeProviderContext = getProviderInstance();\n\n if (optionsWithDefault.useSuspense) {\n return (\n <TolgeeProviderContext.Provider\n value={{ tolgee: tolgeeSSR, options: optionsWithDefault }}\n >\n {loading ? (\n fallback\n ) : (\n <Suspense fallback={fallback || null}>{children}</Suspense>\n )}\n </TolgeeProviderContext.Provider>\n );\n }\n\n return (\n <TolgeeProviderContext.Provider\n value={{ tolgee: tolgeeSSR, options: optionsWithDefault }}\n >\n {loading ? fallback : children}\n </TolgeeProviderContext.Provider>\n );\n};\n","import type { TolgeePlugin } from '@tolgee/web';\nimport { DEFAULT_REACT_OPTIONS } from './TolgeeProvider';\nimport type { ReactOptions, TolgeeReactContext } from './types';\n\nlet globalContext: TolgeeReactContext | undefined;\n\nexport const GlobalContextPlugin =\n (options?: Partial<ReactOptions>): TolgeePlugin =>\n (tolgee) => {\n globalContext = {\n tolgee,\n options: { ...DEFAULT_REACT_OPTIONS, ...options },\n };\n return tolgee;\n };\n\nexport function getGlobalContext() {\n return globalContext;\n}\n","import { useContext } from 'react';\nimport { getGlobalContext } from './GlobalContextPlugin';\nimport { getProviderInstance } from './TolgeeProvider';\n\nexport const useTolgeeContext = () => {\n const TolgeeProviderContext = getProviderInstance();\n const context = useContext(TolgeeProviderContext) || getGlobalContext();\n if (!context) {\n throw new Error(\n \"Couldn't find tolgee instance, did you forgot to use `TolgeeProvider`?\"\n );\n }\n return context;\n};\n","import { useCallback, useState } from 'react';\n\nexport const useRerender = () => {\n const [instance, setCounter] = useState(0);\n\n const rerender = useCallback(() => {\n setCounter((num) => num + 1);\n }, [setCounter]);\n return { instance, rerender };\n};\n","import { useCallback, useEffect, useRef } from 'react';\nimport {\n TranslateProps,\n NsFallback,\n getFallbackArray,\n getFallback,\n} from '@tolgee/web';\n\nimport { useTolgeeContext } from './useTolgeeContext';\nimport { ReactOptions } from './types';\nimport { useRerender } from './hooks';\n\nexport const useTranslateInternal = (\n ns?: NsFallback,\n options?: ReactOptions\n) => {\n const { tolgee, options: defaultOptions } = useTolgeeContext();\n const namespaces = getFallback(ns);\n const namespacesJoined = getFallbackArray(namespaces).join(':');\n\n const currentOptions = {\n ...defaultOptions,\n ...options,\n };\n\n // dummy state to enable re-rendering\n const { rerender, instance } = useRerender();\n\n const subscriptionQueue = useRef([] as NsFallback[]);\n subscriptionQueue.current = [];\n\n const isLoaded = tolgee.isLoaded(namespaces);\n\n useEffect(() => {\n const subscription = tolgee.on('update', rerender);\n\n return () => {\n subscription.unsubscribe();\n };\n }, [namespacesJoined, tolgee]);\n\n useEffect(() => {\n tolgee.addActiveNs(namespaces);\n return () => tolgee.removeActiveNs(namespaces);\n }, [namespacesJoined, tolgee]);\n\n const t = useCallback(\n (props: TranslateProps<any>) => {\n const fallbackNs = props.ns ?? namespaces?.[0];\n return tolgee.t({ ...props, ns: fallbackNs }) as any;\n },\n [tolgee, instance]\n );\n\n if (currentOptions.useSuspense && !isLoaded) {\n throw tolgee.addActiveNs(namespaces, true);\n }\n\n return { t, isLoading: !isLoaded };\n};\n","import { TranslateParams } from '@tolgee/web';\nimport React from 'react';\n\nimport { ParamsTags } from './types';\n\nfunction unwrapSingleElementArray(value: any) {\n if (Array.isArray(value) && value.length === 1) {\n return value[0];\n } else {\n return value;\n }\n}\n\nexport const wrapTagHandlers = (\n params: TranslateParams<ParamsTags> | undefined\n) => {\n if (!params) {\n return undefined;\n }\n\n const result: any = {};\n\n Object.entries(params || {}).forEach(([key, value]) => {\n if (typeof value === 'function') {\n result[key] = (chunk: any) => {\n return value(addReactKeys(chunk));\n };\n } else if (React.isValidElement(value as any)) {\n const el = value as React.ReactElement;\n result[key] = (chunk: any) => {\n return el.props.children === undefined && chunk?.length\n ? React.cloneElement(el, {}, addReactKeys(chunk))\n : React.cloneElement(el);\n };\n } else {\n result[key] = value;\n }\n });\n\n return result;\n};\n\nexport const addReactKeys = (\n children: React.ReactNode | React.ReactNode[] | undefined\n) => {\n const val = unwrapSingleElementArray(children);\n if (Array.isArray(val)) {\n return val.map((item, i) => (\n <React.Fragment key={i}>{item}</React.Fragment>\n ));\n } else {\n return val;\n }\n};\n","import React from 'react';\nimport { addReactKeys, wrapTagHandlers } from './tagsTools';\nimport type { PropsWithKeyName, TBaseInterface } from './types';\n\nexport const TBase: TBaseInterface = (props) => {\n const key = (props as PropsWithKeyName).keyName || props.children;\n if (key === undefined) {\n // eslint-disable-next-line no-console\n console.error('T component: keyName not defined');\n }\n const defaultValue =\n props.defaultValue ||\n ((props as PropsWithKeyName).keyName ? props.children : undefined);\n\n const translation = addReactKeys(\n props.t({\n key: key!,\n params: wrapTagHandlers(props.params),\n defaultValue,\n noWrap: props.noWrap,\n ns: props.ns,\n language: props.language,\n })\n );\n\n return <>{translation}</>;\n};\n","import React from 'react';\nimport { ParamsTags, TProps } from './types';\n\nimport { useTranslateInternal } from './useTranslateInternal';\nimport { TFnType } from '@tolgee/web';\nimport { TBase } from './TBase';\n\ninterface TInterface {\n (props: TProps): JSX.Element;\n}\n\nexport const T: TInterface = (props) => {\n const { t } = useTranslateInternal();\n\n return <TBase t={t as TFnType<ParamsTags>} {...props} />;\n};\n","import { TolgeeEvent, TolgeeInstance } from '@tolgee/web';\nimport { useEffect } from 'react';\nimport { useRerender } from './hooks';\nimport { useTolgeeContext } from './useTolgeeContext';\n\nexport const useTolgee = (events?: TolgeeEvent[]): TolgeeInstance => {\n const { tolgee } = useTolgeeContext();\n\n const { rerender } = useRerender();\n\n useEffect(() => {\n const listeners = events?.map((e) => tolgee.on(e, rerender));\n return () => {\n listeners?.forEach((listener) => listener.unsubscribe());\n };\n }, [events?.join(':')]);\n\n return tolgee;\n};\n","import { useCallback } from 'react';\nimport {\n TFnType,\n getTranslateProps,\n DefaultParamType,\n TranslationKey,\n} from '@tolgee/web';\n\nimport { useTranslateInternal } from './useTranslateInternal';\nimport { ReactOptions } from './types';\n\nexport interface UseTranslateResult {\n t: TFnType<DefaultParamType, string, TranslationKey>;\n isLoading: boolean;\n}\n\nexport const useTranslate = (\n ns?: string[] | string,\n options?: ReactOptions\n): UseTranslateResult => {\n const { t: tInternal, isLoading } = useTranslateInternal(ns, options);\n\n const t = useCallback(\n (...params: any) => {\n // @ts-ignore\n const props = getTranslateProps(...params);\n return tInternal(props);\n },\n [tInternal]\n );\n\n return { t, isLoading };\n};\n"],"names":["useTolgeeSSR","tolgeeInstance","language","data","enabled","noWrappingTolgee","useState","getTolgeeWithDeactivatedWrapper","tolgee","Object","assign","t","args","props","getTranslateProps","noWrap","initialRender","setInitialRender","useEffect","useMemo","setEmitterActive","addStaticData","changeLanguage","isLoaded","requiredRecords","getRequiredDescriptors","providedRecords","getAllRecords","missingRecords","map","namespace","filter","key","find","r","cacheKey","console","warn","join","DEFAULT_REACT_OPTIONS","useSuspense","ProviderInstance","getProviderInstance","React","createContext","undefined","LAST_TOLGEE_INSTANCE","globalContext","useTolgeeContext","TolgeeProviderContext","context","useContext","Error","useRerender","instance","setCounter","rerender","useCallback","num","useTranslateInternal","ns","options","defaultOptions","namespaces","getFallback","namespacesJoined","getFallbackArray","currentOptions","useRef","current","subscription","on","unsubscribe","addActiveNs","removeActiveNs","fallbackNs","_a","isLoading","wrapTagHandlers","params","result","entries","forEach","value","chunk","addReactKeys","isValidElement","el","children","length","cloneElement","val","Array","isArray","item","i","Fragment","TBase","keyName","error","defaultValue","translation","createElement","fallback","ssr","run","stop","catch","e","finally","setLoading","tolgeeSSR","staticData","Boolean","loading","optionsWithDefault","Provider","Suspense","events","listeners","listener","tInternal"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { TolgeeInstance, TolgeeStaticData } from '@tolgee/web';
1
+ import { CachePublicRecord, TolgeeInstance, TolgeeStaticData } from '@tolgee/web';
2
2
  /**
3
3
  * Updates tolgee static data and language, to be ready right away for the first render
4
4
  * and therefore compatible with SSR.
@@ -11,4 +11,4 @@ import { TolgeeInstance, TolgeeStaticData } from '@tolgee/web';
11
11
  * @param staticData static data for the language
12
12
  * @param enabled if set to false, no action is taken
13
13
  */
14
- export declare function useTolgeeSSR(tolgeeInstance: TolgeeInstance, language?: string, staticData?: TolgeeStaticData | undefined, enabled?: boolean): TolgeeInstance;
14
+ export declare function useTolgeeSSR(tolgeeInstance: TolgeeInstance, language?: string, data?: TolgeeStaticData | CachePublicRecord[] | undefined, enabled?: boolean): TolgeeInstance;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { TolgeeInstance, TolgeeStaticData } from '@tolgee/web';
2
+ import { TolgeeInstance, TolgeeStaticDataProp } from '@tolgee/web';
3
3
  import { ReactOptions, TolgeeReactContext } from './types';
4
4
  export declare const DEFAULT_REACT_OPTIONS: ReactOptions;
5
5
  export declare const getProviderInstance: () => React.Context<TolgeeReactContext | undefined>;
@@ -11,7 +11,7 @@ export type SSROptions = {
11
11
  /**
12
12
  * If provided, static data will be hard set to Tolgee cache for initial render
13
13
  */
14
- staticData?: TolgeeStaticData;
14
+ staticData?: TolgeeStaticDataProp;
15
15
  };
16
16
  export interface TolgeeProviderProps {
17
17
  children?: React.ReactNode;
@@ -1,13 +1,14 @@
1
- import { TFnType } from '@tolgee/web';
2
- import { TProps } from './types';
3
1
  import React from 'react';
2
+ import { TFnType } from '@tolgee/web';
4
3
  import { TolgeeInstance } from '@tolgee/web';
4
+ import { TProps } from './types';
5
5
  export type CreateServerInstanceOptions = {
6
6
  createTolgee: (locale: string) => Promise<TolgeeInstance>;
7
7
  getLocale: () => Promise<string>;
8
8
  };
9
9
  export declare const createServerInstance: ({ createTolgee, getLocale, }: CreateServerInstanceOptions) => {
10
10
  getTolgeeInstance: (locale: string) => Promise<TolgeeInstance>;
11
+ getTolgeeStaticInstance: (locale: string) => Promise<TolgeeInstance>;
11
12
  getTolgee: () => Promise<TolgeeInstance>;
12
13
  getTranslate: () => Promise<TFnType<import("@tolgee/web").DefaultParamType, string, import("@tolgee/web").TranslationKey>>;
13
14
  T: (props: TProps) => Promise<React.JSX.Element>;
@@ -1,4 +1,4 @@
1
- import { TolgeeInstance, TolgeeStaticData } from '@tolgee/web';
1
+ import { CachePublicRecord, TolgeeInstance, TolgeeStaticData } from '@tolgee/web';
2
2
  /**
3
3
  * Updates tolgee static data and language, to be ready right away for the first render
4
4
  * and therefore compatible with SSR.
@@ -11,4 +11,4 @@ import { TolgeeInstance, TolgeeStaticData } from '@tolgee/web';
11
11
  * @param staticData static data for the language
12
12
  * @param enabled if set to false, no action is taken
13
13
  */
14
- export declare function useTolgeeSSR(tolgeeInstance: TolgeeInstance, language?: string, staticData?: TolgeeStaticData | undefined, enabled?: boolean): TolgeeInstance;
14
+ export declare function useTolgeeSSR(tolgeeInstance: TolgeeInstance, language?: string, data?: TolgeeStaticData | CachePublicRecord[] | undefined, enabled?: boolean): TolgeeInstance;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tolgee/react",
3
- "version": "5.33.2",
3
+ "version": "5.33.3-prerelease.2efc0e6b.0",
4
4
  "description": "React implementation for Tolgee localization framework",
5
5
  "main": "./dist/tolgee-react.cjs.js",
6
6
  "module": "./dist/tolgee-react.esm.js",
@@ -38,7 +38,7 @@
38
38
  "react": "^16.14.0 || ^17.0.1 || ^18.1.0 || ^19"
39
39
  },
40
40
  "dependencies": {
41
- "@tolgee/web": "5.33.2"
41
+ "@tolgee/web": "5.33.3-prerelease.2efc0e6b.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@rollup/plugin-node-resolve": "^14.1.0",
@@ -46,8 +46,8 @@
46
46
  "@testing-library/dom": "^8.7.2",
47
47
  "@testing-library/jest-dom": "^5.11.4",
48
48
  "@testing-library/react": "^14.3.1",
49
- "@tolgee/format-icu": "5.33.2",
50
- "@tolgee/testing": "5.33.2",
49
+ "@tolgee/format-icu": "5.33.3-prerelease.2efc0e6b.0",
50
+ "@tolgee/testing": "5.33.3-prerelease.2efc0e6b.0",
51
51
  "@types/jest": "^27.0.2",
52
52
  "@types/node": "^17.0.8",
53
53
  "@types/react": "^18.3.16",
@@ -88,5 +88,5 @@
88
88
  "access": "public"
89
89
  },
90
90
  "sideEffects": false,
91
- "gitHead": "73467e06c29511cafab7e7162cef8ac4a36ff507"
91
+ "gitHead": "799332abc27675f19c1b722ac063cbe2451f500e"
92
92
  }
@@ -1,10 +1,10 @@
1
1
  import React, { Suspense, useEffect, useState } from 'react';
2
- import { TolgeeInstance, TolgeeStaticData } from '@tolgee/web';
2
+ import { TolgeeInstance, TolgeeStaticDataProp } from '@tolgee/web';
3
3
  import { ReactOptions, TolgeeReactContext } from './types';
4
4
  import { useTolgeeSSR } from './useTolgeeSSR';
5
5
 
6
6
  export const DEFAULT_REACT_OPTIONS: ReactOptions = {
7
- useSuspense: true,
7
+ useSuspense: false,
8
8
  };
9
9
 
10
10
  let ProviderInstance: React.Context<TolgeeReactContext | undefined>;
@@ -29,7 +29,7 @@ export type SSROptions = {
29
29
  /**
30
30
  * If provided, static data will be hard set to Tolgee cache for initial render
31
31
  */
32
- staticData?: TolgeeStaticData;
32
+ staticData?: TolgeeStaticDataProp;
33
33
  };
34
34
 
35
35
  export interface TolgeeProviderProps {
@@ -36,7 +36,7 @@ describe('useTranslations namespaces', () => {
36
36
  beforeEach(async () => {
37
37
  staticDataMock = mockStaticDataAsync();
38
38
  tolgee = Tolgee()
39
- .use(GlobalContextPlugin({ useSuspense: false }))
39
+ .use(GlobalContextPlugin())
40
40
  .use(DevTools())
41
41
  .use(FormatIcu())
42
42
  .init({
@@ -49,9 +49,7 @@ describe('useTranslations namespaces', () => {
49
49
 
50
50
  await act(async () => {
51
51
  const runPromise = tolgee.run();
52
- staticDataMock.resolvablePromises.cs.resolve();
53
- staticDataMock.resolvablePromises.en.resolve();
54
- staticDataMock.resolvablePromises['en:fallback'].resolve();
52
+ staticDataMock.resolvePending();
55
53
  await runPromise;
56
54
  render(<TestComponent />);
57
55
  });
@@ -63,7 +61,7 @@ describe('useTranslations namespaces', () => {
63
61
 
64
62
  it('loads namespace after render', async () => {
65
63
  expect(screen.queryByTestId('loading')).toContainHTML('Loading...');
66
- staticDataMock.resolveAll();
64
+ staticDataMock.resolvePending();
67
65
  await waitFor(() => {
68
66
  expect(screen.queryByTestId('loading')).toBeFalsy();
69
67
  expect(screen.queryByTestId('test')).toContainHTML('Český test');
@@ -72,7 +70,7 @@ describe('useTranslations namespaces', () => {
72
70
  });
73
71
 
74
72
  it('works with english fallback', async () => {
75
- staticDataMock.resolveAll();
73
+ staticDataMock.resolvePending();
76
74
  await waitFor(() => {
77
75
  expect(screen.queryByTestId('test_english_fallback')).toContainHTML(
78
76
  'Test english fallback'
@@ -85,7 +83,7 @@ describe('useTranslations namespaces', () => {
85
83
 
86
84
  it('works with ns fallback', async () => {
87
85
  expect(screen.queryByTestId('ns_fallback')).toContainHTML('fallback');
88
- staticDataMock.resolveAll();
86
+ staticDataMock.resolvePending();
89
87
  await waitFor(() => {
90
88
  expect(screen.queryByTestId('ns_fallback')).toContainHTML('Fallback');
91
89
  expect(screen.queryByTestId('ns_fallback')).toHaveAttribute('_tolgee');
@@ -98,7 +96,7 @@ describe('useTranslations namespaces', () => {
98
96
  );
99
97
  await act(async () => {
100
98
  const changePromise = tolgee.changeLanguage('en');
101
- staticDataMock.resolveAll();
99
+ staticDataMock.resolvePending();
102
100
  await changePromise;
103
101
  });
104
102
  expect(screen.queryByTestId('ns_fallback')).toContainHTML(
@@ -107,7 +105,7 @@ describe('useTranslations namespaces', () => {
107
105
  });
108
106
 
109
107
  it('works with default value', async () => {
110
- staticDataMock.resolveAll();
108
+ staticDataMock.resolvePending();
111
109
  await waitFor(() => {
112
110
  expect(screen.queryByTestId('non_existant')).toContainHTML(
113
111
  'Non existant'
@@ -5,6 +5,7 @@ import { render, screen, waitFor } from '@testing-library/react';
5
5
  import { Tolgee, TolgeeEvent, TolgeeInstance } from '@tolgee/web';
6
6
  import { FormatIcu } from '@tolgee/format-icu';
7
7
  import { mockStaticDataAsync } from '@tolgee/testing/mockStaticData';
8
+ import { wait } from '@tolgee/testing/wait';
8
9
 
9
10
  const API_URL = 'http://localhost';
10
11
 
@@ -66,6 +67,7 @@ describe('useTranslation hook integration', () => {
66
67
  checkState({ initialLoad: 'true' });
67
68
 
68
69
  await act(async () => {
70
+ await wait(0);
69
71
  staticDataMock.resolvablePromises.cs.resolve();
70
72
  await runPromise;
71
73
  });
@@ -74,6 +76,7 @@ describe('useTranslation hook integration', () => {
74
76
  });
75
77
  await act(async () => {
76
78
  tolgee.changeLanguage('en');
79
+ await wait(0);
77
80
  staticDataMock.resolvablePromises.en.resolve();
78
81
  });
79
82
  await waitFor(() => {
@@ -90,6 +93,7 @@ describe('useTranslation hook integration', () => {
90
93
  checkState({ language: 'cs' });
91
94
  await act(async () => {
92
95
  tolgee.changeLanguage('en');
96
+ await wait(0);
93
97
  staticDataMock.resolvablePromises.en.resolve();
94
98
  });
95
99
  checkState({ language: 'en' });
@@ -104,6 +108,7 @@ describe('useTranslation hook integration', () => {
104
108
  checkState({ language: 'cs', pendingLanguage: 'cs' });
105
109
  await act(async () => {
106
110
  tolgee.changeLanguage('en');
111
+ await wait(0);
107
112
  staticDataMock.resolvablePromises.en.resolve();
108
113
  });
109
114
  await waitFor(async () => {
@@ -1,11 +1,11 @@
1
1
  // @ts-ignore
2
2
  import { cache } from 'react';
3
+ import React from 'react';
3
4
  import { TFnType } from '@tolgee/web';
5
+ import { TolgeeInstance } from '@tolgee/web';
4
6
 
5
7
  import { TBase } from './TBase';
6
8
  import { TProps, ParamsTags } from './types';
7
- import React from 'react';
8
- import { TolgeeInstance } from '@tolgee/web';
9
9
 
10
10
  export type CreateServerInstanceOptions = {
11
11
  createTolgee: (locale: string) => Promise<TolgeeInstance>;
@@ -16,11 +16,18 @@ export const createServerInstance = ({
16
16
  createTolgee,
17
17
  getLocale,
18
18
  }: CreateServerInstanceOptions) => {
19
- const getTolgeeInstance = cache(async (locale: string) => {
20
- const tolgee = await createTolgee(locale);
21
- await tolgee.run();
22
- return tolgee;
23
- }) as (locale: string) => Promise<TolgeeInstance>;
19
+ const getTolgeeInstance: (locale: string) => Promise<TolgeeInstance> = cache(
20
+ async (locale: string) => {
21
+ const tolgee = await createTolgee(locale);
22
+ await tolgee.run();
23
+ return tolgee;
24
+ }
25
+ );
26
+
27
+ const getTolgeeStaticInstance: (locale: string) => Promise<TolgeeInstance> =
28
+ cache(async (locale: string): Promise<TolgeeInstance> => {
29
+ return createTolgee(locale);
30
+ });
24
31
 
25
32
  const getTolgee = async () => {
26
33
  const locale = await getLocale();
@@ -38,5 +45,11 @@ export const createServerInstance = ({
38
45
  return <TBase t={t as TFnType<ParamsTags>} {...props} />;
39
46
  }
40
47
 
41
- return { getTolgeeInstance, getTolgee, getTranslate, T };
48
+ return {
49
+ getTolgeeInstance,
50
+ getTolgeeStaticInstance,
51
+ getTolgee,
52
+ getTranslate,
53
+ T,
54
+ };
42
55
  };
@@ -1,4 +1,5 @@
1
1
  import {
2
+ CachePublicRecord,
2
3
  getTranslateProps,
3
4
  TolgeeInstance,
4
5
  TolgeeStaticData,
@@ -33,7 +34,7 @@ function getTolgeeWithDeactivatedWrapper(
33
34
  export function useTolgeeSSR(
34
35
  tolgeeInstance: TolgeeInstance,
35
36
  language?: string,
36
- staticData?: TolgeeStaticData | undefined,
37
+ data?: TolgeeStaticData | CachePublicRecord[] | undefined,
37
38
  enabled = true
38
39
  ) {
39
40
  const [noWrappingTolgee] = useState(() =>
@@ -52,23 +53,24 @@ export function useTolgeeSSR(
52
53
  // so translations are available right away
53
54
  // events emitting must be off, to not trigger re-render while rendering
54
55
  tolgeeInstance.setEmitterActive(false);
55
- tolgeeInstance.addStaticData(staticData);
56
+ tolgeeInstance.addStaticData(data);
56
57
  tolgeeInstance.changeLanguage(language!);
57
58
  tolgeeInstance.setEmitterActive(true);
58
59
  }
59
- }, [language, staticData, tolgeeInstance]);
60
+ }, [language, data, tolgeeInstance]);
60
61
 
61
62
  useState(() => {
62
63
  // running this function only on first render
63
64
  if (!tolgeeInstance.isLoaded() && enabled) {
64
65
  // warning user, that static data provided are not sufficient
65
66
  // for proper SSR render
66
- const missingRecords = tolgeeInstance
67
- .getRequiredRecords(language)
67
+ const requiredRecords = tolgeeInstance.getRequiredDescriptors(language);
68
+ const providedRecords = tolgeeInstance.getAllRecords();
69
+ const missingRecords = requiredRecords
68
70
  .map(({ namespace, language }) =>
69
71
  namespace ? `${namespace}:${language}` : language
70
72
  )
71
- .filter((key) => !staticData?.[key]);
73
+ .filter((key) => !providedRecords.find((r) => r?.cacheKey === key));
72
74
 
73
75
  // eslint-disable-next-line no-console
74
76
  console.warn(
@@ -1,6 +1,5 @@
1
1
  import { useCallback, useEffect, useRef } from 'react';
2
2
  import {
3
- SubscriptionSelective,
4
3
  TranslateProps,
5
4
  NsFallback,
6
5
  getFallbackArray,
@@ -27,25 +26,13 @@ export const useTranslateInternal = (
27
26
  // dummy state to enable re-rendering
28
27
  const { rerender, instance } = useRerender();
29
28
 
30
- const subscriptionRef = useRef<SubscriptionSelective>();
31
-
32
29
  const subscriptionQueue = useRef([] as NsFallback[]);
33
30
  subscriptionQueue.current = [];
34
31
 
35
- const subscribeToNs = (ns: NsFallback) => {
36
- subscriptionQueue.current.push(ns);
37
- subscriptionRef.current?.subscribeNs(ns);
38
- };
39
-
40
32
  const isLoaded = tolgee.isLoaded(namespaces);
41
33
 
42
34
  useEffect(() => {
43
- const subscription = tolgee.onNsUpdate(rerender);
44
- subscriptionRef.current = subscription;
45
- subscription.subscribeNs(namespaces);
46
- subscriptionQueue.current.forEach((ns) => {
47
- subscription!.subscribeNs(ns);
48
- });
35
+ const subscription = tolgee.on('update', rerender);
49
36
 
50
37
  return () => {
51
38
  subscription.unsubscribe();
@@ -60,7 +47,6 @@ export const useTranslateInternal = (
60
47
  const t = useCallback(
61
48
  (props: TranslateProps<any>) => {
62
49
  const fallbackNs = props.ns ?? namespaces?.[0];
63
- subscribeToNs(fallbackNs);
64
50
  return tolgee.t({ ...props, ns: fallbackNs }) as any;
65
51
  },
66
52
  [tolgee, instance]