Next.js Discord

Discord Forum

Next-translate error when trying to send mail via Resend

Unanswered
West African Lion posted this in #help-forum
Open in Discord
West African LionOP
Hey there.
I've been trying to send mails with Resend in my Next.js app. So far so good, it works with "raw data".

But then I've tried to enhance my templates with translations, reusing my already in place next-translate.

At first, I've added at the beginning of my template a useTranslationwhich I believed was working server-side despite its hook name, but it crashed the whole process.

I've tried to replace it by createTranslation, and while working in local, it does not work in prod. By looking at vercel logs once deployed, I have
TypeError: Cannot read properties of undefined (reading 'localesToIgnore')


I wanted to try the getT method as well, but I haven't even been able to load a translation in local with this method.

Am I missing something, is there a common way to achieve this?

32 Replies

Original message was deleted
thanks for sharing all the files. We might need them later. Can you share the specific errors & issues that you got, that you described like
but it crashed the whole process.
@B33fb0n3 thanks for sharing all the files. We might need them later. Can you share the specific errors & issues that you got, that you described like > but it crashed the whole process.
West African LionOP
Once deployed, the send-otp route returns a 500 error with, within Vercel logs, this displayed:
⨯ TypeError: Cannot read properties of null (reading 'useContext')

And from what I've seen no further useful log.

Like I said, replacing by createTranslation just gives another error about an undefined property, trying to read localesToIgnore (from what I've seen on https://github.com/aralroca/next-translate/blob/master/src/createTranslation.tsx it means that config is not defined, but anyways if useTranslation is supposed to be working I'd be fine with any solution)
@B33fb0n3 can you comment out the red line and add this to the green line: tsx const { t } = useTranslation('emails'); Are you able to access the translations?
West African LionOP
Is the goal to check if it crashes prod as well? Locally, it works of course
@B33fb0n3 I think it only crashes in prod, right?
West African LionOP
yep, just verified it was working locally, but it's being deployed atm
@B33fb0n3 I think it only crashes in prod, right?
West African LionOP
Same error logged in Vercel:
⨯ TypeError: Cannot read properties of null (reading 'useContext')
    at t.useContext (/var/task/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:12:183619)
    at /var/task/.next/server/app/api/auth/send-otp/route.js:1:6618
    at u (/var/task/.next/server/app/api/auth/send-otp/route.js:1:6699)
    at d (/var/task/.next/server/app/api/auth/send-otp/route.js:1:1455)
    at /var/task/node_modules/@sentry/nextjs/build/cjs/common/wrapRouteHandlerWithSentry.js:59:44
    at Object.handleCallbackErrors (/var/task/node_modules/@sentry/core/build/cjs/utils/handleCallbackErrors.js:26:26)
    at /var/task/node_modules/@sentry/nextjs/build/cjs/common/wrapRouteHandlerWithSentry.js:58:47
    at /var/task/node_modules/@sentry/opentelemetry/build/cjs/index.js:870:15
    at Object.handleCallbackErrors (/var/task/node_modules/@sentry/core/build/cjs/utils/handleCallbackErrors.js:26:26)
    at /var/task/node_modules/@sentry/opentelemetry/build/cjs/index.js:869:19
As expected, just wrapped the code in the POST method:
console.log('will init t from useTranslation "hook"');
  const { t } = useTranslation('emails');
  console.log('send-otp translate ', t('otp.isYourLoginCode'));

And the first one is displayed, then it crashes
@B33fb0n3 hm pretty weird. Looks like it's a vercel limitation 🤔
West African LionOP
Maybe. I was thinking another ugly-ish solution which would just be to translate manually?
Since it's working for the whole application except mails, maybe creating a public/locales/XX/emails.json and then importing the json file in templates for direct use (considering I have the locale to do the right dynamic import?) would work... idk
@B33fb0n3 yea.. what do you think about sending the (already translated) texts directly to the route handler? And then read it from the body of the route handler? Woudln't that work?
West African LionOP
You mean since translations are available on client, I could send them to the route handler from there?
If that's what you meant, then I'd have 2 concerns:
- Increased payload / traffic weight w/ translated texts
- Other use cases that would still be problematic, e.g. when stripe webhooks are triggered, there's no client side hence I'll still have to deal with translations in the backend
Increased payload / traffic weight w/ translated texts
of couse it would be a bit more. However not really that much more (you don't send the whole file. Only the parts that are needed)

Other use cases that would still be problematic, e.g. when stripe webhooks are triggered, there's no client side hence I'll still have to deal with translations in the backend
how do you expect rn the backend knows which language the output should be?
@B33fb0n3 > Increased payload / traffic weight w/ translated texts of couse it would be a bit more. However not really that much more (you *don't* send the whole file. Only the parts that are needed) > Other use cases that would still be problematic, e.g. when stripe webhooks are triggered, there's no client side hence I'll still have to deal with translations in the backend how do you expect rn the backend knows which language the output should be?
West African LionOP
Yeah that's right, template are not that heavy but I guess it always counts.

From what I've browsed in the payload sent by stripe, there are several leads I can exploit
- The country within customer address that could be normalized and used somehow (e.g. transform FR into fr and such); could be problematic if lots of countries are not tied to a language
- Another lead which seems better, the return url. Since routing includes the lang within the app, the return url sent back by stripe contains the locale that was used during checkout.
More generally of course, if I ever needed more mails to be sent from the BE, I'd have to store the user's locale in db or something similar... But that's not in the plans for now, not sure if I should anticipate that.
@B33fb0n3 yea and that may be the issue, that next-translate is facing right now. He doesn't have a context and also can't create a context
West African LionOP
Probably. I need to see if my leads can solve that, or... send mails in english for now 🫠
@West African Lion Probably. I need to see if my leads can solve that, or... send mails in english for now 🫠
yea, try to initialize your dict with a language code and then use the translations from that. That's why I like to use the nextjs integrated internationalization system as it's soooo easy:
@B33fb0n3 yea, try to initialize your dict with a language code and then use the translations from that. That's why I like to use the nextjs integrated internationalization system as it's soooo easy:
West African LionOP
I don't know much about next i18n system tbh (if there's something besides routing), I'll take a look at that, ty 👌
@B33fb0n3 Sure thing. For reference: https://nextjs.org/docs/app/building-your-application/routing/internationalization
West African LionOP
Oh that's a similar idea in the end, it's cool. Maybe simpler or more explicit than mine. I've implemented it like this in my email.ts file:
export const loadEmailTranslations = async (lang: string) => {
  // Cannot be dynamic or files will not be included in the bundle
  switch (lang) {
    case 'en':
      return (await import('@/locales/en/emails.json')).default;
    case 'fr':
      return (await import('@/locales/fr/emails.json')).default;
    default:
      return (await import('@/locales/en/emails.json')).default;
  }
};

A bit more verbose since it's a switch rather than an object, but there's a fallback language 🤔
Haven't dived much deeper to see important differences w/ what's suggested on the page
@B33fb0n3 yea, it's similar to the getDirectories function from i18n of nextjs itself. Rename it, so it can be served as this
West African LionOP
Is it possible that it broke something somehow?
A page that is not using the [lang] slug now crashes
West African LionOP
Nvm I don't see what it could be linked to, since error also happens in local and it seems to be located on
const redisClientSingleton = () => {
  return new Redis({
    url: process.env.UPSTASH_REDIS_REST_URL,
    token: process.env.UPSTASH_REDIS_REST_TOKEN,
  });
};

Which is weird since I haven't touched it for 2 months. Somehow latest changes broke this, or at least it explodes there...
@B33fb0n3 don't you have a fallback value?
West African LionOP
I don't even need next-translate on this page, so there's nothing requested and everything was working fine until... now
https://console.upstash.com/redis
Idk why it seems broken for me.
If there was an issue on their side it would be an explanation but eh
If I would be in your situation I would migrate to next's default i18n system. I hate to have these kind of "unfixable" errors
West African LionOP
I hate them too yeah...