Luck dev
Luck dev

Reputation: 435

How to detect and use the page language in nextJS (ReferenceError: window is not defined)

Im trying to make a site that could identify the country and set the language.

To do this in react i use to call thw window.navigator.language. The entire file:

import * as pt from "./pt";
import * as en from './en';

let translate;

if (window.navigator.language == 'pt-PT' || window.navigator.language == 'pt-BR') {
  translate = pt.default;
} else {
  translate = en.default;
}
export default translate

the pt / en files its just JSONS with all texts.

But window doesnt exist in nextJS

That error appears: ReferenceError: window is not defined

I need to use out of a react file. Because i just import and use like this: {Translate.header.label_opts_clients}

I will import and I use this in a XML (react) file and in a JSON file like:

export const headerOptions = [
  {
    title: "`${Translate.header.label_opts_home}`",
...

How can i do this? I know that exist useRouter(hook), so if you need to take the url in a page you can use. I already had that problem, and i solved with this:

...

const { pathname } = useRouter()
  
  const [crumbs, setCrumbs] = useState<string[]>();

  useEffect(()=>{
    renderCrumbs()
  },[pathname])

  const setHref = (links:string[], index:number|string) => {
    let linkPath = ""
    
    for (let i = 0; i <= index; i++) {      
      linkPath = linkPath + "/" + links[i]      
    }

    return linkPath
  }

  const renderCrumbs = () => {
    let links = pathname.split('/').slice(1);
    let limit = links.length;
    let array = [];

...

But this just work in a function component.

I tried to put the condition in a function and return the let translate, and use the translate with parentheses ({Translate().header.something}) but didnt work.

I tried to use this too (but doesnt work):

if (window !== undefined) {
  // browser code
}

And i cant use hooks or components did/will mounth.

My code pictures:

My folder organization

The translates

The translate code

How i will import

The EN JSON

My other JSON that i need to use the translate

trying to do a useEffect in my _app (laoult)

Window verification in JS script and brought the JSON file to translate archive

Upvotes: 0

Views: 7136

Answers (2)

Luck dev
Luck dev

Reputation: 435

I found. If you are using NextJS v10.0.0 you can use a new advanced feature.

Internationalized Routing - i18n

https://nextjs.org/docs/advanced-features/i18n-routing

First of all you need to config your next.config.js and add the i18n module export. If you already had some other plugins (like me) you will need to put them together.

const withImages = require('next-images')
const path = require('path')

module.exports = withImages({
    esModule: false,
    i18n: {
        locales: ['en-US', 'pt-BR', 'pt-PT', 'es-ES'],
        defaultLocale: 'pt-BR',
      },
});

With my project configured for the languages that i want, I went to my translation file and used a next hook - useRouter from next/router

import * as pt from "./pt";
import * as en from './en';
import { useRouter } from "next/router"

export const traducao = () =>{
  let routes = useRouter();

  let translate;
 
    if (routes.locale == 'pt-PT' || routes.locale == 'pt-BR') {
      translate = pt.default;
    } else {
      translate = en.default;
    }
  
  return translate 
}

And the i just use in my project like a function:

{traducao().homeText.button_text}

Work well, recognizes the browser language and switche. But unfortunaly you cant use in a Json, because you are using a hook, and hooks just works in a function component.

Upvotes: 2

Prav
Prav

Reputation: 610

The window object can be referenced once the DOM is rendered. Usually, it is used in useEffect hook like so -

useEffect(() => {
    console.log(window) // window is not undefined here
}, [])

in your case, from what I understand, you are trying to check the language and return the content from the pt file and further use it in another react component as header options.

Here's what might work, Change your translate file to a function -

import * as pt from './pt'
import * as en from './en'

const translate = (window) => {
    const { language } = window.navigator
    
    if(language == 'pt-PT' || language == 'pt-BR') return pt.default
    else return en.default
}

export default translate

Now use it in your react file in a useEffect function -

import translate from 'YOUR_PATH_TO_TRANSLATE'

const SomeReactComponent = (props) => {
    useEffect(() => {
        const translatedData = translate(window) // now window is defined

        let headerData = {
            title: translatedData.header.label_opts_home
            ... 
        }
        
        
    }, []) // componentDidMount in classes
}

Or, if you want to get the JSON header data from a separate file, you can create a separate file like so -

import translate from 'YOUR_PATH_TO_TRANSLATE'

const getHeaderData = (window) => {
    const translatedData = translate(window) // now window is defined

    let headerData = {
        title: translatedData.header.label_opts_home
        ... 
    }

    return headerData
}

and then, use it in your main component like so,

import getHeaderData from 'YOUR_PATH_TO_GETHEADERDATA'

const SomeReactComponent = (props) => {
    useEffect(() => {
        let headerData = getHeaderData(window)
    }, [])
}

I hope this works.

Upvotes: 0

Related Questions