From 7aeee650b62e30d29aa93efb5aa6bd045ab49b95 Mon Sep 17 00:00:00 2001 From: Lukas Heizmann <49527534+lkwr@users.noreply.github.com> Date: Wed, 4 Mar 2026 13:13:51 +0100 Subject: [PATCH 1/2] feat: make Trans component typesafe --- example/i18next.d.ts | 14 ++++++++++++++ src/trans.tsx | 34 ++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 example/i18next.d.ts diff --git a/example/i18next.d.ts b/example/i18next.d.ts new file mode 100644 index 0000000..73e8c82 --- /dev/null +++ b/example/i18next.d.ts @@ -0,0 +1,14 @@ +// import "i18next"; + +// import type lang from "./locale/en/lang.json"; +// import type translation from "./locale/en/translation.json"; + +// declare module "i18next" { +// interface CustomTypeOptions { +// defaultNS: "translation"; +// resources: { +// lang: typeof lang; +// translation: typeof translation; +// }; +// } +// } diff --git a/src/trans.tsx b/src/trans.tsx index d24eeb1..ca695d0 100644 --- a/src/trans.tsx +++ b/src/trans.tsx @@ -1,27 +1,41 @@ -import type { TFunction, TOptions } from "i18next"; +import type { + EffectiveKPrefix, + Namespace, + ParseKeys, + TFunction, + TOptions, +} from "i18next"; import { type Component, createMemo, type JSX } from "solid-js"; import { useTranslation } from "./use-translation.ts"; export type TransEmbeddedComponent = Component<{ children?: string }>; -export type TransProps = { - key: string; +export type TransProps< + Ns extends Namespace, + KPrefix = undefined, + TOpt extends TOptions = TOptions, +> = { + key: ParseKeys>; fallback?: string; components?: Record; - replace?: TOptions["replace"]; + replace?: TOpt["replace"]; - t?: TFunction; - options?: TOptions; + t?: TFunction; + options?: TOpt; }; -export const Trans: Component = (props) => { +export const Trans = < + Ns extends Namespace, + KPrefix = undefined, + TOpt extends TOptions = TOptions, +>( + props: TransProps, +): JSX.Element => { const [contextT] = useTranslation(() => props.options?.ns); const t = ((...args: Parameters) => - props.t - ? props.t(...(args as Parameters)) - : contextT(...(args as Parameters))) as TFunction; + props.t ? props.t(...args) : contextT(...args)) as TFunction; const mergedOptions = createMemo( (): TOptions => ({ From 3304df531cbd268ee169959ee20d12fb6c0a96c6 Mon Sep 17 00:00:00 2001 From: Lukas Heizmann <49527534+lkwr@users.noreply.github.com> Date: Thu, 5 Mar 2026 21:47:50 +0100 Subject: [PATCH 2/2] align more with react-i18next --- example/app.tsx | 2 +- example/locale/de/translation.json | 4 +++- example/locale/en/translation.json | 4 +++- src/trans.tsx | 14 +++++--------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/example/app.tsx b/example/app.tsx index 6937c7d..4865e51 100644 --- a/example/app.tsx +++ b/example/app.tsx @@ -41,7 +41,7 @@ export const App = () => {

{{name}}!" + "nested": { + "welcome": "Willkommen, {{name}}!" + } } diff --git a/example/locale/en/translation.json b/example/locale/en/translation.json index 0e347ae..11204cb 100644 --- a/example/locale/en/translation.json +++ b/example/locale/en/translation.json @@ -1,3 +1,5 @@ { - "welcome": "Welcome, {{name}}!" + "nested": { + "welcome": "Welcome, {{name}}!" + } } diff --git a/src/trans.tsx b/src/trans.tsx index ca695d0..5833a52 100644 --- a/src/trans.tsx +++ b/src/trans.tsx @@ -1,21 +1,16 @@ -import type { - EffectiveKPrefix, - Namespace, - ParseKeys, - TFunction, - TOptions, -} from "i18next"; +import type { Namespace, ParseKeys, TFunction, TOptions } from "i18next"; import { type Component, createMemo, type JSX } from "solid-js"; import { useTranslation } from "./use-translation.ts"; export type TransEmbeddedComponent = Component<{ children?: string }>; export type TransProps< + Key extends ParseKeys, Ns extends Namespace, KPrefix = undefined, TOpt extends TOptions = TOptions, > = { - key: ParseKeys>; + key: Key | Key[]; fallback?: string; components?: Record; @@ -26,11 +21,12 @@ export type TransProps< }; export const Trans = < + Key extends ParseKeys, Ns extends Namespace, KPrefix = undefined, TOpt extends TOptions = TOptions, >( - props: TransProps, + props: TransProps, ): JSX.Element => { const [contextT] = useTranslation(() => props.options?.ns);