Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions examples/tanstack-start/src/client.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { setupI18n } from "@lingui/core"
import { hydrateRoot } from "react-dom/client"
import { StartClient } from "@tanstack/react-start"
import { dynamicActivate } from "./modules/lingui/i18n"

import { createRouter } from "./router"
import { startTransition, StrictMode } from "react"

// The lang should be set by the server
const i18n = setupI18n({})
await dynamicActivate(i18n, document.documentElement.lang)

const router = createRouter({ i18n })

Expand Down
5 changes: 5 additions & 0 deletions examples/tanstack-start/src/locales/en/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"

#. js-lingui-explicit-id
#: src/routes/deferred.tsx:10
msgid "Hello deferred!"
msgstr "Hello deferred!"

#: src/routes/posts_.$postId.deep.tsx:24
msgid "← All Posts"
msgstr "← All Posts"
Expand Down
5 changes: 5 additions & 0 deletions examples/tanstack-start/src/locales/fr/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ msgstr ""
"Plural-Forms: \n"
"X-Generator: Poedit 3.5\n"

#. js-lingui-explicit-id
#: src/routes/deferred.tsx:10
msgid "Hello deferred!"
msgstr "Bonjour différé !"

#: src/routes/posts_.$postId.deep.tsx:24
msgid "← All Posts"
msgstr "← Tous les articles"
Expand Down
63 changes: 63 additions & 0 deletions examples/tanstack-start/src/modules/lingui/router-plugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Fragment, type PropsWithChildren } from 'react'
import { I18nProvider } from "@lingui/react"
import type { AnyRouter } from '@tanstack/react-router'
import { setupI18n, type I18n } from '@lingui/core'

type AdditionalOptions = {
WrapProvider?: (props: { children: any }) => React.JSX.Element
}

export type ValidateRouter<TRouter extends AnyRouter> =
NonNullable<TRouter['options']['context']> extends {
i18n: I18n
}
? TRouter
: never

export function routerWithLingui<TRouter extends AnyRouter>(
router: ValidateRouter<TRouter>,
i18n: I18n,
additionalOpts?: AdditionalOptions,
): TRouter {
const ogOptions = router.options

router.options = {
...router.options,
dehydrate: () => {
return {
...ogOptions.dehydrate?.(),
// When critical data is dehydrated, we also dehydrate the i18n messages
dehydratedI18n: {
locale: i18n.locale,
messages: i18n.messages,
},
}
},
hydrate: (dehydrated: any) => {
ogOptions.hydrate?.(dehydrated)
// On the client, hydrate the i18n catalog with the dehydrated data
i18n.loadAndActivate({
locale: dehydrated.dehydratedI18n.locale,
messages: dehydrated.dehydratedI18n.messages,
})
},
context: {
...ogOptions.context,
// Pass the query client to the context, so we can access it in loaders
i18n,
},
// Wrap the app in a I18nProvider
Wrap: ({ children }: PropsWithChildren) => {
const OuterWrapper = additionalOpts?.WrapProvider || Fragment
const OGWrap = ogOptions.Wrap || Fragment

return <OuterWrapper>
<I18nProvider i18n={i18n}>
<OGWrap>{children}</OGWrap>
</I18nProvider>
</OuterWrapper>
},
}

return router
}
12 changes: 5 additions & 7 deletions examples/tanstack-start/src/router.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import type { I18n } from "@lingui/core"
import { I18nProvider } from "@lingui/react"
import { createRouter as createTanStackRouter } from "@tanstack/react-router"
import { createRouter as createTanStackRouter, type AnyRouter } from "@tanstack/react-router"
import { type PropsWithChildren } from "react"
import { routeTree } from "./routeTree.gen"
import { DefaultCatchBoundary } from "./components/DefaultCatchBoundary"
import { NotFound } from "./components/NotFound"
import { routerWithLingui } from "./modules/lingui/router-plugin"

export interface AppContext {
i18n: I18n
}

export function createRouter({ i18n }: { i18n: I18n }) {
const router = createTanStackRouter({
const router = routerWithLingui(createTanStackRouter({
routeTree,
context: {
i18n,
},
defaultErrorComponent: DefaultCatchBoundary,
defaultNotFoundComponent: () => <NotFound />,
scrollRestoration: true,
Wrap: ({ children }: PropsWithChildren) => {
return <I18nProvider i18n={i18n}>{children}</I18nProvider>
},
})
scrollRestoration: true
}), i18n)

return router
}
Expand Down
4 changes: 2 additions & 2 deletions examples/tanstack-start/src/routes/deferred.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { Suspense, useState } from "react"
import { personServerFn, slowServerFn } from "~/functions/deferred"

export const Route = createFileRoute("/deferred")({
loader: async () => {
loader: async ({ context }) => {
return {
deferredStuff: new Promise<string>((r) =>
setTimeout(() => r("Hello deferred!"), 2000)
setTimeout(() => r(context.i18n.t("Hello deferred!")), 2000)
),
deferredPerson: slowServerFn({ data: "Tanner Linsley" }),
person: await personServerFn({ data: "John Doe" }),
Expand Down