I have written a simple nextjs with next-i18next as i18n library. I have used dynamic routing by putting the locale inside the path as /pages/mysite/mysubsite/[locale]/section/. I do not use the localeSubpaths because I would like the fix the path as above instead of putting the locale at the end of the path.
The main program is like this
/pages/mysite/mysubsite/[locale]/section/index.js
import { useRouter } from 'next/router';
import PropTypes from 'prop-types'
import { i18n, Link, withTranslation } from '../../../../../i18n'
const Index = ({isMobileView, t}) => {
const router = useRouter();
const { locale } = router.query;
if (i18n.language !== locale) {
console.log('switching locale from ' + i18n.language + ' to ' + locale);
i18n.changeLanguage(locale);
}
if (isMobileView) {
return (
<div> {t('mobile')}
{locale}
</div>
)
} else {
return (
<div> {t('desktop')}
{locale}
</div>
)
}
};
Index.getInitialProps = async function (context) {
let isMobileView = (context.req
? context.req.headers['user-agent']
: navigator.userAgent).match(
/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i
)
//Returning the isMobileView as a prop to the component for further use.
return {
isMobileView: Boolean(isMobileView),
namespacesRequired: ['items'],
}
}
Index.propTypes = {
t: PropTypes.func.isRequired,
}
export default withTranslation('items')(Index);
the /pages/i18n is like this:-
const NextI18Next = require('next-i18next').default;
module.exports = new NextI18Next({
defaultLanguage: 'en',
otherLanguages: ['tw'],
});
and I have stored the json items.json two keys only, the tw one below:-
{
"mobile": "手機",
"desktop": "桌面"
}
and the end one below:-
{
"mobile": "Mobile",
"desktop": "Desktop"
}
I found that when the program first run, the result would be like:-
desktopopen
and from the chrome consolelog it is printing:-
switching locale from undefined to en
And the server consolelog looks simular:-
react-i18next:: i18n.languages were undefined or empty undefined switching locale from undefined to en
That means I have changed the local using i18n.changeLanguage(locale) and the locale itself is correct.
But I m pretty lost. Why is the locale in the UI is open whereas I can print the correct locale from the console log?
Another strange thing is that I have opened the console of chrome and also switched to responsive mobile view. That means the mobile agent detection also doesn't work in the first run. Then I pressed shift F5 to refresh the page. And the UI turns:-
mobileen
and console log doesn't print anything.
Again, it is printing the key instead of the value of the json while the mobile detection is correct this time.
The things would goes normal when I press the shift F5 the third time. And the correct UI is shown:-
Mobileen
During the whole debugging exercise, I have tried to close everything (browser and the node process) and restart again and again to observe the behavior, while it is kind of strange that some time desktopopen will not happen while it will be like mobileen instead. That means whenever desktopopen is there, the mobile detection doesn't work as well. I really cannot cache the behavior.
The version of libraries using are as below:-
"dependencies": {
"next": "^9.1.6",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"@quentin-sommer/react-useragent": "^3.1.0",
"next-i18next": "^3.0.1"
}
Also the /pages/_app.js are as below:-
import React from 'react'
import App from 'next/app'
import { appWithTranslation } from '../i18n'
class MyApp extends App {
render() {
const { Component, pageProps } = this.props
return (
<Component {...pageProps} />
)
}
}
export default appWithTranslation(MyApp)
I am suspecting it is bcoz the problem is relating to state management and have tried switch using react hooks by modifying the main program as:-
import React, { useState } from 'react';
import { useRouter } from 'next/router';
import PropTypes from 'prop-types'
import { i18n, Link, withTranslation } from '../../../../../i18n'
const Index = ({isMobileView, t}) => {
const router = useRouter();
const [ locale ] = useState(router.query.locale);
if (i18n.language !== locale) {
console.log('switching locale from ' + i18n.language + ' to ' + locale);
i18n.changeLanguage(locale);
}
if (isMobileView) {
return (
<div> {t('mobile')}
{locale}
</div>
)
} else {
return (
<div> {t('desktop')}
{locale}
</div>
)
}
};
Index.getInitialProps = async function (context) {
let isMobileView = (context.req
? context.req.headers['user-agent']
: navigator.userAgent).match(
/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i
)
//Returning the isMobileView as a prop to the component for further use.
return {
isMobileView: Boolean(isMobileView),
namespacesRequired: ['items'],
}
}
Index.propTypes = {
t: PropTypes.func.isRequired,
}
export default withTranslation('items')(Index);
But the problem is almost the same. The only difference is I cannot cache the moment where the output is "desktopopen".
My question can be summarized as:-
- Why is the mobile detection not working on the first run some of the time?
- Why the dynamic path variable is not correctly printing in the UI but it does work in the console log on the first run some of the time?
- Why is the defaultlanguage not working even I have specify the defaultLanguage in the i18n.js?
- Is changing language success or not? Why it is printing the key of the json instead of the json value? I would assume the change language is not successful, right? Is it that I should take a look in the react hook? Coz I suspect it is a matter of state problem. But why is the problem persist even after I have deployed react hook? Does that means it is not state management problem?