i18next icon indicating copy to clipboard operation
i18next copied to clipboard

i18n.exists reports false even if the translation exists.

Open sbaechler opened this issue 5 months ago • 5 comments

🐛 Bug Report

I noticed that i18n.exists can report false even if the key exists and the t function correctly translates the value. This breaks the rare use case where a React component can accept either a translation key or a string.

To Reproduce

Code Sandbox https://codesandbox.io/p/devbox/pedantic-haibt-f843tj

Check the console. I noticed that this only happens if the key is in a translation file that is loaded async.

  console.log({
    exists: i18n.exists("select.classification.BAR"),
    value: t("select.classification.BAR"),
  });

-> {exists: false, value: 'Bar'}

Expected behavior

The return value of the exists function should also resolve if the t function resolves to a valid key.

{exists: true, value: 'Bar'}

Your Environment

  • runtime version: node 22, CodeSandbox as well.
  • i18next version: 25.4.2, react-18next: 15.7.3
  • os: Mac

sbaechler avatar Sep 01 '25 07:09 sbaechler

const { t, i18n } = useTranslation("form"); binds the t function to the namespace form

i18n.exists is a function on i18next - it does not know about the namespace (not bound)

either use i18n.exists("form:select.classification.BAR") or i18n.exists("select.classification.BAR", { ns: 'form' })

jamuhl avatar Sep 01 '25 08:09 jamuhl

Thank you for the quick reply.

What is the reason that i18n is not bound in this case? This is not intuitive since the i18n object is returned from the useTranslation function that has a namespace as its first agument. As a developer I would expect that it was at least considering this namespace.

sbaechler avatar Sep 01 '25 08:09 sbaechler

because it's the one singleton raw unmutated i18n instance you passed in...you can't bind that to a namespace

jamuhl avatar Sep 01 '25 09:09 jamuhl

Could you add a note to the docs to clarify that only the t function is bound to the namespace but not the i18n object?

Alternatively it should be possible bind the exists function of the returned i18n object of useTranslation to the namespace (e.g. with a proxy).

sbaechler avatar Sep 01 '25 11:09 sbaechler

Could you add a note to the docs to clarify that only the t function is bound to the namespace but not the i18n object?

I updated the react-i18next docs to add the note clarifying that only the returned t is namespace-bound: https://react.i18next.com/latest/usetranslation-hook#usetranslation-params

Image

So far no one else has requested exists() to be bound.

Alternatively it should be possible bind the exists function of the returned i18n object of useTranslation to the namespace (e.g. with a proxy).

You could implement a proxy that wraps i18n and auto-injects ns for selected methods, but it’s not recommended as a library-level change. i18n exposes many methods with different argument shapes and side-effects, so a proxy risks surprising/fragile behavior and subtle bugs.

adrai avatar Sep 01 '25 13:09 adrai