Next-translate: How do you translate in an API route (/pages/api/...) ?

Created on 23 Nov 2020  路  17Comments  路  Source: vinissimus/next-translate

Hi,

I am currently evaluating this lib, and it looks great!

I have few newbies questions:

1) how can we get the t function inside an api route ?

2) Inside an api route, how can we translate to another language (changeLanguage) ?
use case: a user click a Like button ie: /pages/api/like.js and inside the api route we notify the recipient which can use another language

Thanks

All 17 comments

@fillon Right now there is no way, but if you are interested we could implement this feature. We usually advise that the translations are better used inside React, while outside (in the api or inside methods like getStaticProps) it is better to use the translation keys.

@aralroca Thanks for your quick reply :)

I will keep migrating our pages from next-i18next and will come back to you if I still have issues with /api routes.

@fillon I have made a PR adding getT, with this you can use translations directly in api route. https://github.com/vinissimus/next-translate/pull/383

@fillon I pre-released the change under 1.0.0-canary.8. I would appreciate it if you could try it out on your project and give me feedback that everything is working well for you 馃槉

If you wonder how to migrate to version 1.0, here is a guide:

Any doubt, tell me. Thank you very much for reporting it 馃檹 I guess that version 1.0 will be released soon.

@aralroca Everything worked with @canary.7

@canary.8

I am getting a ReferenceError: globalThis is not defined on a page when using loadNamespaces

export async function getStaticProps(ctx) {
  return {
    props: await loadNamespaces ({
      ...ctx,
      pathname: '/hello',
    }),
  };
}

i18n.js

module.exports = {
  defaultLocale: 'en',
  loader: false,
  locales: [
    'en',
...
    'vi',
    'zh',
  ],
  // localesPath: 'locales',
  loadLocaleFrom: (lang, ns) =>
    import (`./locales/${lang}/${ns}.json`).then (m => m.default),
};

next.config.js

// const { locales, defaultLocale } = require ('./i18n.js');
const nextTranslate = require ('next-translate');

module.exports = nextTranslate (
  withMDX ({
    pageExtensions: [ 'js', 'jsx', 'md', 'mdx' ],
  })
);

_app.js
I was using <I18nProvider lang={router.locale} namespaces={pageProps._ns}>
I removed it.

_app.js

...

// used with canary.7
// export const loadNamespaces = async (namespaces, lang) => {
//  let res = {};
//  for (let ns of namespaces) {
//    res[ns] = await import (`../../locales/${lang}/${ns}.json`).then (
//      m => m.default
//    );
//  }
//  return res;
// };

MyApp.propTypes = {
  Component: PropTypes.elementType.isRequired,
  pageProps: PropTypes.object.isRequired,
};

export default function MyApp(props) {
  const { Component, pageProps } = props;

  return (
    <>
      <ThemeProvider theme={theme}>
        <AuthProvider>
            <CssBaseline />
...
            <Component {...pageProps} />
        </AuthProvider>
        <ReactQueryDevtools initialIsOpen={false} />
      </ThemeProvider>
    </>
  );
}

my locales are in the root folder

/locales
    /en
        common.json
    ...
/src
    /pages
        _app.js
        ...
i18n.js
next.config.js

@fillon are you using a Node version lower than 12? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis

and what browser are you using?

perhaps the most correct is to change the globalThis to global or window to extend the support, it is only to save the i18n configuration.

Thanks 馃檹

@aralroca node v10

let me upgrade it and come back to you :)

@fillon globalThis is supported on Node +12, I hope it works for you after migrating. I'm also thinking about changing it to justglobal to give more support so you can use it on Node 10. Although all the tests we have are from Node 12 onwards...

@fillon I did another prerelease, 1.0.0-canary.9, replacing globalThis to global, now it should work with Node 10 馃憤 馃槉

@aralroca with 1.0.0-canary.9 it's compiling again

I still have an error, it doesn't seem to loadnamespaces

next-translate - compiled page: /hello - locale: fr - namespaces: - used loader: -

i18n.js

module.exports = {
  defaultLocale: 'en',
  loader: false, // This deactivate the webpack loader that loads the namespaces
  // When loader === false, then loadLocaleFrom is required
  loadLocaleFrom: (lang, ns) =>
    import (`./locales/${lang}/${ns}.json`).then (m => m.default),
  locales: [
    'ar',
    'da',
    'de',
    'en',
    'es',
...
  ],
  pages: {
    '*': ['common'],
    // '/hello': ['common'],
  },
};

/pages/hello.js

export async function getStaticProps(ctx) {
  return {
    props: await loadNamespaces ({
      ...ctx,
      pathname: '/hello',
    }),
  };
}

@aralroca Do we still need to wrap MyApp with appWithI18n like in the canary examples?

=> Wrapped MyApp with appWithI18n => all working on pages

In your configuration locales fr is missing. But the detected locale is fr.

@aralroca fr was defined.. it's working ok in the pages

For /api endpoint:

const t = await getT ('fr', 'common'); if i specify the locale.. translation is working great

how does req.query.__nextLocale get initialized ? I always get 'en'

Fetching like this on the client side:

await fetch ('/api/v3/ping', {
      method: 'POST',
      headers: {
        'Accept-Language': router.locale,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify ({
...
      }),
    });

This req.query.__nextLocale is introduced by Next.js. If is returning always English is because you are requesting to /api/endpoint instead of /fr/api/endpoint. Another way you can archive this is by using a cookie named NEXT_LOCALE, this way also is saving the preferred user language. This is introduced by Next.js i18n routing. I hope it helps

@aralroca it helps a lot 馃憤

I will finally be able to uninstall i18next and in-house i18middleware.

Great work!! Love this lib. Simple straight to the point.

Was this page helpful?
0 / 5 - 0 ratings