#What's the best place to initialise a server-side locale translator function?

9 messages · Page 1 of 1 (latest)

wary sequoia
#

I'm using use-intl for my i18n (which is the core library from next-intl. I want to initialise the translator function and inject it into the request context so I can use it in the backend, but have it load the necessary data from user preferences only once.

export const Route = createRootRouteWithContext<MyRouterContext>()({
  beforeLoad: async ({ context }) => {
    const [
      auth,
      userPreference,
    ] = await Promise.all([
      context.queryClient.ensureQueryData(authQueryOptions()),
      context.queryClient.ensureQueryData(userPreferencesQueryOptions()),
    ])

    const locale = await context.queryClient.ensureQueryData(
      localeQueryOptions(userPreference.locale),
    )
    const translator = createTranslator(locale)

    return {
      auth,
      translator
    }
  },
  shellComponent: RootDocument,
})

However, I'm getting a ... is not assignable to type '"Function is not serializable"

I suppose this is not supported. So, where's the good place to do this?

midnight summit
#

it depends really where you need that translator

#

only in react?

wary sequoia
# midnight summit only in react?

In places where we can't call hooks. My example was inspired by this repo
https://github.com/aaronlin0122/tanstack-boilerplate

And here's how they use it
https://github.com/search?q=repo%3Aaaronlin0122%2Ftanstack-boilerplate+context.translator&type=code

GitHub

A fully type-safe boilerplate with a focus on UX and DX, complete with multiple examples. - aaronlin0122/tanstack-boilerplate

GitHub

GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.

midnight summit
#

so inside router lifecycle methods then?

#

would put it into the router context in getRouter()

wary sequoia
#

Something like this?

export const getRouter = async () => {
  const rqContext = TanstackQuery.getContext()
  const queryClient = rqContext.queryClient
  const userPreference = await queryClient.ensureQueryData(userPreferencesQueryOptions())

  const locale = await queryClient.ensureQueryData(
    localeQueryOptions(userPreference.locale),
  )
  const translator = createTranslator(locale)
  
  const router = createRouter({
    routeTree,
    context: { ...rqContext, translator },
    defaultPreload: "intent",
    Wrap: (props: { children: React.ReactNode }) => {
      return <TanstackQuery.Provider {...rqContext}>{props.children}</TanstackQuery.Provider>
    },
  })

  setupRouterSsrQueryIntegration({ router, queryClient: rqContext.queryClient })

  return router
}

This should work for my use case. I don't need it at the moment, but is there any option if I want to do the same thing for a specific route only?

midnight summit
#

it probably should be tweaked so you don't refetch on the client

#

we are working on lifecycle methods that would allow you to this per route without serializing