React-i18next: Dynamically update translations using addResources at runtime?

Created on 13 Oct 2018  路  7Comments  路  Source: i18next/react-i18next

Overview
Using react-i18next for existing translations needs. Came across a case to update the translation's values by key at runtime.

Issue
I've tried using https://www.i18next.com/overview/api#addresource addResource in this instance but it _adds_ a new key / value pair to the translations, rather than updates the existing value by key.

Example:

const runTimeTranslationUpdates = {"api.translations.engineTemp":  44.5}
i18next.addResources('en', 'translations', runTimeTranslationUpdates)

Outcome
In this case the translation expected to update by that given key, isn't changed in the render after addResources has been called.

Expected Outcome

addResources updates the existing translation's values by the given key api.translations.engineTemp in runTimeTranslationUpdates object.

Question

Is there an i18next api method to update translation on the fly by key?

I couldn't find an issue similar to this, hence why I've opened a new issue.
This issue is similar but is aimed at adding rather than updating the translations:
https://github.com/i18next/react-i18next/issues/356

Most helpful comment

Turned out the i18nextConfig.ns value is being interpreted
as an array when passed to addResources.

So giving i18next.addResources(lng, i18nextConfig.ns, runTimeData); doesn't work
as i18nextConfig.ns - ["translation"] is an array.

The transformOptions function
does this transform.

Before:

export const i18nextConfig: any = {
  lng: "de",
  ns: "translation",
  resources: {
    de: {
      translation: {...{data: apiDataDeJson}}
    },
    en: {
      translation: {...{data: apiDataEnJson}}
    }
  }
};
export const runTimeTranslations = (runTimeData: any, lng: string) => {
  i18next.addResources(lng, i18nextConfig.ns, runTimeData);
};
export const i18n: i18next.i18n = i18next.init(i18nextConfig);

After:
Fixed this by passing i18nextConfig.ns[0] as inputOption to i18next.addResources:
Maybe it should be called out in the docs, that ns option is mutated to an array type in init?

export const i18nextConfig: any = {
  lng: "de",
  ns: ["translation"],
  resources: {
    de: {
      translation: {...{data: apiDataDeJson}}
    },
    en: {
      translation: {...{data: apiDataEnJson}}
    }
  }
};
export const runTimeTranslations = (runTimeData: any, lng: string) => {
  i18next.addResources(lng, i18nextConfig.ns[0], runTimeData);
};
export const i18n: i18next.i18n = i18next.init(i18nextConfig);

All 7 comments

https://www.i18next.com/overview/api#addresource -> API is like:

i18next.addResource('en', 'translations', 'api.translations.engineTemp', '44.5')

ah you're using the addResources: https://github.com/i18next/i18next/blob/master/src/ResourceStore.js#L61 should work...but the value needs to be a string.

@jamuhl this is the API function I'm using addResources. But it isn't refreshing the translations.

Should addResources do that or is there another method call needed to trigger the translates again?

I see this line emits the added event after addResources is called:

https://github.com/i18next/i18next/blob/0de7e5683565bcda8654aed5e9a59bf1ba916eaa/src/ResourceStore.js#L90

yes emits the added event on resourceStore -> if bind store has added: https://react.i18next.com/components/withnamespaces#set-defaults-for-all-used-withnamespaces

it should rerender...at least if not set option silent on adding

Turned out the i18nextConfig.ns value is being interpreted
as an array when passed to addResources.

So giving i18next.addResources(lng, i18nextConfig.ns, runTimeData); doesn't work
as i18nextConfig.ns - ["translation"] is an array.

The transformOptions function
does this transform.

Before:

export const i18nextConfig: any = {
  lng: "de",
  ns: "translation",
  resources: {
    de: {
      translation: {...{data: apiDataDeJson}}
    },
    en: {
      translation: {...{data: apiDataEnJson}}
    }
  }
};
export const runTimeTranslations = (runTimeData: any, lng: string) => {
  i18next.addResources(lng, i18nextConfig.ns, runTimeData);
};
export const i18n: i18next.i18n = i18next.init(i18nextConfig);

After:
Fixed this by passing i18nextConfig.ns[0] as inputOption to i18next.addResources:
Maybe it should be called out in the docs, that ns option is mutated to an array type in init?

export const i18nextConfig: any = {
  lng: "de",
  ns: ["translation"],
  resources: {
    de: {
      translation: {...{data: apiDataDeJson}}
    },
    en: {
      translation: {...{data: apiDataEnJson}}
    }
  }
};
export const runTimeTranslations = (runTimeData: any, lng: string) => {
  i18next.addResources(lng, i18nextConfig.ns[0], runTimeData);
};
export const i18n: i18next.i18n = i18next.init(i18nextConfig);

screen shot 2018-10-15 at 15 46 40

could this be closed?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

martinlaregina picture martinlaregina  路  3Comments

Flo-Slv picture Flo-Slv  路  4Comments

MohammedAl-Mahdawi picture MohammedAl-Mahdawi  路  4Comments

simoami picture simoami  路  3Comments

ok2ju picture ok2ju  路  3Comments