#What typing to use for i18next options

23 messages · Page 1 of 1 (latest)

slow mist
#

I need help with asigning the correct typing to use the option parameter for useTranslation of i18next.
this is i18next.ts file with the i18nReady function which is called from the main.ts on app startup

import i18next from "i18next";
import { initReactI18next } from "react-i18next";
import { resources } from "./resources";

export const defaultNS = "home";

export const i18nReady = (async () => {
  const cfg = await window.pbs.loadConfig();
  const lang = cfg.success ? cfg.content.language : "en";

  await i18next
    .use(initReactI18next)
    .init({
      resources,
      lng: lang,
      fallbackLng: 'en',
      ns: Object.keys(resources.en),
      defaultNS,
      interpolation: { escapeValue: false }
    });
  return i18next;
})

export default i18next;```
this is the resouces.ts where I defined all the namespaces I want to use in my application:
```typescript
import abilities from "./locales/en/abilities.json";
import berryplants from "./locales/en/berryplants.json";
import buttons from "./locales/en/buttons.json";
import common from "./locales/en/common.json";
import encounters from "./locales/en/encounters.json";
import footer from "./locales/en/footer.json";
import forms from "./locales/en/forms.json";
import home from "./locales/en/home.json";
import imports from "./locales/en/imports.json";
import items from "./locales/en/items.json";
import mapmetadata from "./locales/en/mapmetadata.json";
import modals from "./locales/en/modals.json";
import moves from "./locales/en/moves.json";
import nav from "./locales/en/nav.json";
import pokemon from "./locales/en/pokemon.json";
import settings from "./locales/en/settings.json";
import tabs from "./locales/en/tabs.json";
import toasts from "./locales/en/toasts.json";
import townmap from "./locales/en/townmap.json";
import trainers from "./locales/en/trainers.json";
import trainertypes from "./locales/en/trainertypes.json";
import types from "./locales/en/types.json";

export const resources = {
  en: {
    abilities,
    berryplants,
    buttons,
    common,
    encounters,
    footer,
    forms,
    home,
    imports,
    items,
    mapmetadata,
    modals,
    moves,
    nav,
    pokemon,
    settings,
    tabs,
    toasts,
    townmap,
    trainers,
    trainertypes,
    types
  }
} as const;

export type AvailableNamespaces = keyof typeof resources["en"];```
This is the NavItem interface i'm using for the navItem array.
```typescript
export type TranslationKey = string;

export interface NavItem {
  headerKey: TranslationKey;
  nameKey: TranslationKey;
  url: string;
  disabled?: boolean;
}```
then inside my sidebar component:
```typescript
  const navItems: NavItem[] = [
    {
      headerKey: t('home:header'),
      nameKey: t('nav:home'),
      url: "/"
    },
    {
      headerKey: t('common:header'),
      nameKey: t('nav:abilities', { name: t('abilities:header.plural')}),
      url: "/abilities-v2"
    }
  ];```
but for the nameKey value of the second element, VS code is showing the error shown in the screenshot. Can anyone help me fix this or tell me how to use the options parameter? Or should i not use the {{ name }} syntax and add extra lines for each that need it in the namespace files? Thank you in advance
sick idol
#

i'm not able to reproduce your error:

paper wingBOT
#
mkantor#0

Preview:```ts
import {t} from "i18next"

export type TranslationKey = string

export interface NavItem {
headerKey: TranslationKey
nameKey: TranslationKey
url: string
disabled?: boolean
}

const navItems: NavItem[] = [
{
headerKey: t("home:header"),
nameKey:
...```

sick idol
#

could you edit that playground to try and make the error appear, then send me back the updated URL?

#

the playground will use types for the latest versions of npm packages, so if you can't repro then check what version of i18next you're using

slow mist
sick idol
#

does this library use declaration merging to augment its types or something? nothing you shared would cause the type checking to change, so if you think that's what's going on please add the relevant code to a playground

slow mist
#

i'm not familiar with playground so i'm not sure how this works and can generate errors or not

#

the error is gone if i remove the resources parameter here:

import 'i18next';
import { resources } from '@/renderer/i18n/resources';
import { defaultNS } from '@/renderer/i18n/i18next';

declare module "i18next" {
  interface CustomTypeOptions {
    defaultNs: typeof defaultNS;
    resources: typeof resources["en"];
  }
}```
#

What i think i would need to do is to define those options as well that a namespace uses but that i don't know how to do

import abilities from "./locales/en/abilities.json";
import berryplants from "./locales/en/berryplants.json";
import buttons from "./locales/en/buttons.json";
import common from "./locales/en/common.json";
import encounters from "./locales/en/encounters.json";
import footer from "./locales/en/footer.json";
import forms from "./locales/en/forms.json";
import home from "./locales/en/home.json";
import imports from "./locales/en/imports.json";
import items from "./locales/en/items.json";
import mapmetadata from "./locales/en/mapmetadata.json";
import modals from "./locales/en/modals.json";
import moves from "./locales/en/moves.json";
import nav from "./locales/en/nav.json";
import pokemon from "./locales/en/pokemon.json";
import settings from "./locales/en/settings.json";
import tabs from "./locales/en/tabs.json";
import toasts from "./locales/en/toasts.json";
import townmap from "./locales/en/townmap.json";
import trainers from "./locales/en/trainers.json";
import trainertypes from "./locales/en/trainertypes.json";
import types from "./locales/en/types.json";

export const resources = {
  en: {
    abilities,
    berryplants,
    buttons,
    common,
    encounters,
    footer,
    forms,
    home,
    imports,
    items,
    mapmetadata,
    modals,
    moves,
    nav,
    pokemon,
    settings,
    tabs,
    toasts,
    townmap,
    trainers,
    trainertypes,
    types
  }
} as const;

export type AvailableNamespaces = keyof typeof resources["en"];```
sick idol
#

ah yeah that declare module "i18next" with the CustomTypeOptions is probably the thing that affects type checking

#

in order to understand the issue i'd need to see a complete definition of typeof resources["en"] (or whatever minimum subset of it that's necessary to reproduce the error). i think you've shared the rest. you can try copy/pasting the values from those imports to inline them into a playground

#

here's a start:

paper wingBOT
#
mkantor#0

Preview:```ts
import {t} from "i18next"

const defaultNS = "home"

const resources = {
en: {
abilities: {
/* TODO /
},
berryplants: {
/
TODO /
},
buttons: {
/
TODO /
},
common: {
/
TODO /
},
encounters: {
/
TODO /
},
footer: {
/
TODO /
},
forms: {
/
TODO /
},
home: {
/
TODO /
},
imports: {
/
TODO /
},
items: {
/
TODO */
},
mapmeta
...```

slow mist
#

Or would it work that I send you my project? I don't have much yet anyway

sick idol
#

eh i'm not really interested in getting that set up locally, sorry. maybe if you can't make the playground work for some reason (but it should; the only limitation is that it's a single file)

slow mist
#

I'll try to add it tomorrow then

sick idol
#

ideally you'd share a minimal example anyway to keep things focused rather than just dumping your entire project

slow mist
#

I understand

slow mist
#

https://youtu.be/GLIas4DH3Ww?is=GBMdCGR9OF2E4DDl this video might have the solution to my problem, I'll give it a try tomorrow when I can and tell here if I got it to work for my usecase.

In this video you will see how to introduce type-safe translations within your TypeScript projects thanks to i18next.

Blog Post: https://locize.com/blog/i18next-typescript/
Code: https://github.com/locize/i18next-typescript-examples
Website & Docs: https://www.i18next.com/overview/typescript

▶ Play video
#

This interface command is probably what I have to do to make typescript understand the interpolation I want to use

slow mist
#

I got it to work after try and error for another 2 hours:
I changed i18next.d.ts to this:

import { defaultNS } from '@/renderer/i18n/i18next';
import Resources from './resources';

declare module "i18next" {
  interface CustomTypeOptions {
    defaultNs: typeof defaultNS;
    resources: Resources;
  }
}```
with Resources being generated from that interface command `"interface": "i18next-resources-for-ts interface -i ./src/renderer/i18n/locales/en -o ./src/renderer/types/resources.d.ts"` in my case it's like this
I had to update my tsconfig.json based on this:
```json
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}```
mine has a few extra parameters but that's inrelivant with the error
then the one thing that did it for me was importing the namespaces like this
```typescript
  const { t } = useTranslation(['common', 'home', 'nav', 'abilities']);

  const navItems: NavItem[] = [
    {
      header: t('home:header'),
      name: t('nav:home'),
      url: "/"
    },
    {
      header: t('common:header', { name: t('abilities:header.plural')}),
      name: t('nav:abilities'),
      url: "/abilities-v2",
      disabled: disabledMap['abilities']
    }
  ];```
in useTranslation, without these the error is still there. This gives me as result that the interpolutions are type safe so if i type "names" instead of "name" typescript will tell me that's wrong
#

and it gives me the exact result i need in my app including typesafety