From 3bc3a20522bc5910b506fd6acbd557a574d98af6 Mon Sep 17 00:00:00 2001 From: Justin York Date: Mon, 17 Aug 2020 11:15:05 -0600 Subject: [PATCH 1/3] Try using next-i18next --- package.json | 10 ++--- .../locales/{en.json => en/common.json} | 0 .../locales/{es.json => es/common.json} | 0 src/i18n.js | 39 ++++++++++--------- src/pages/_app.js | 15 +++---- src/pages/index.js | 2 +- 6 files changed, 34 insertions(+), 32 deletions(-) rename public/static/locales/{en.json => en/common.json} (100%) rename public/static/locales/{es.json => es/common.json} (100%) diff --git a/package.json b/package.json index 8080b1d..9f5ddb9 100644 --- a/package.json +++ b/package.json @@ -3,17 +3,17 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "nodemon server.js", + "dev": "NODE_ENV=local nodemon server.js", "build": "next build", "start": "NODE_ENV=production node server.js" }, "dependencies": { "express": "^4.17.1", - "i18next": "^19.4.5", "next": "^9.5.0", - "nodemon": "^2.0.4", "react": "16.13.1", - "react-dom": "16.13.1", - "react-i18next": "^11.5.0" + "react-dom": "16.13.1" + }, + "devDependencies": { + "nodemon": "^2.0.4" } } diff --git a/public/static/locales/en.json b/public/static/locales/en/common.json similarity index 100% rename from public/static/locales/en.json rename to public/static/locales/en/common.json diff --git a/public/static/locales/es.json b/public/static/locales/es/common.json similarity index 100% rename from public/static/locales/es.json rename to public/static/locales/es/common.json diff --git a/src/i18n.js b/src/i18n.js index aa5c27d..ac23eb1 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -1,21 +1,22 @@ -import i18n from "i18next"; -import { initReactI18next } from "react-i18next"; +const NextI18Next = require('next-i18next').default +const path = require('path') -export const supportedLocales = ["en", "de", "es"]; +const supportedLangs = ['en', 'es']; -export default function initI18N(lang) { - console.log("initI18N: lang:", lang); - i18n.use(initReactI18next); - i18n.init({ - fallbackLng: "en", - lng: lang || "en", - resources: { - en: { - translation: { - helloWorld: "Hello world", - }, - }, - }, - }); - return i18n; -} +module.exports = new NextI18Next({ + defaultLanguage: 'en', + otherLanguages: supportedLangs, + localePath: path.resolve('./public/static/locales'), + serverLanguageDetection: false, + browserLanguageDetection: false +}); + +// module.exports = function iniI18N(locale) { +// return new NextI18Next({ +// defaultLanguage: locale, +// otherLanguages: supportedLangs, +// localePath: path.resolve('./public/static/locales'), +// serverLanguageDetection: false, +// browserLanguageDetection: false +// }); +// }; diff --git a/src/pages/_app.js b/src/pages/_app.js index 847e430..0c9c201 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -1,20 +1,21 @@ import { I18nextProvider } from "react-i18next"; -import i18n from "../i18n"; +import i18n, { appWithTranslation } from "../i18n"; import { useRouter } from "next/router"; import Layout from "../components/Layout"; import "../styles.css"; +import App from 'next/app' function MyApp({ Component, pageProps }) { const router = useRouter(); const { locale } = router.query; console.log("App locale:", locale); return ( - - - - - + + + ); } -export default MyApp; +MyApp.getInitialProps = async (appContext) => ({ ...await App.getInitialProps(appContext) }); + +export default appWithTranslation(MyApp); diff --git a/src/pages/index.js b/src/pages/index.js index 4150797..20fc2d1 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "../i18n"; import { useRouter } from "next/router"; export default function Home() { From 4fa5d23d56afc82d3860dab1b2d018b72301a8c5 Mon Sep 17 00:00:00 2001 From: Justin York Date: Mon, 17 Aug 2020 11:38:58 -0600 Subject: [PATCH 2/3] Domain specific routing https://github.com/isaachinman/next-i18next/issues/16#issuecomment-520853281 --- nodemon.json | 5 --- package.json | 7 ++--- public/static/locales/en/common.json | 1 + public/static/locales/es/common.json | 1 + server.js | 46 ---------------------------- src/components/Header.js | 8 ++--- src/i18n.js | 40 ++++++++++++++++-------- src/pages/_app.js | 5 +-- src/pages/_document.js | 22 ------------- src/pages/gip.js | 14 --------- src/pages/index.js | 4 ++- 11 files changed, 39 insertions(+), 114 deletions(-) delete mode 100644 nodemon.json delete mode 100644 server.js delete mode 100644 src/pages/_document.js delete mode 100644 src/pages/gip.js diff --git a/nodemon.json b/nodemon.json deleted file mode 100644 index e4d7bfb..0000000 --- a/nodemon.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "verbose": true, - "ignore": ["node_modules", ".next", "src/components", "src/pages"], - "watch": ["server.js", "i18n.js"] -} \ No newline at end of file diff --git a/package.json b/package.json index 9f5ddb9..b4e077f 100644 --- a/package.json +++ b/package.json @@ -3,17 +3,14 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "NODE_ENV=local nodemon server.js", + "dev": "next dev", "build": "next build", - "start": "NODE_ENV=production node server.js" + "start": "next start" }, "dependencies": { "express": "^4.17.1", "next": "^9.5.0", "react": "16.13.1", "react-dom": "16.13.1" - }, - "devDependencies": { - "nodemon": "^2.0.4" } } diff --git a/public/static/locales/en/common.json b/public/static/locales/en/common.json index afc6c65..5a47de6 100644 --- a/public/static/locales/en/common.json +++ b/public/static/locales/en/common.json @@ -1,3 +1,4 @@ { + "home": "Home", "helloWorld": "Hello World" } diff --git a/public/static/locales/es/common.json b/public/static/locales/es/common.json index 347de88..723beb4 100644 --- a/public/static/locales/es/common.json +++ b/public/static/locales/es/common.json @@ -1,3 +1,4 @@ { + "home": "Inicio", "helloWorld": "Hola mundo" } diff --git a/server.js b/server.js deleted file mode 100644 index a12239a..0000000 --- a/server.js +++ /dev/null @@ -1,46 +0,0 @@ -/* eslint-disable */ -const express = require("express"); -const next = require("next"); - -const port = process.env.PORT || 3000; -// We use NEXT_ENV instead of NODE_ENV here so that we can -// enable Next's prod mode while running locally. -const app = next({ dev: process.env.NEXT_ENV !== "production" }); -const handle = app.getRequestHandler(); - -const DEFAULT_LOCALE = "en"; -const domainLocaleMap = { - localhost: "en", - "nexttest.com": "en", - "nexttest.es": "es", - "nexttest.de": "de", - "it.nexttest.international": "it", - "ua.nexttest.international": "ua", -}; - -function detectLocale(req, res, next) { - const locale = domainLocaleMap[req.hostname] || DEFAULT_LOCALE; - // Only handle original page requests; ignore _next requests - if (req.url.indexOf("/_next") === -1 && req.url.indexOf("/__next") === -1) { - console.log('original url:', req.url); - console.log('middleware: locale:', locale); - if (req.url.indexOf('?') !== -1) { - req.url = `${req.url}&locale=${locale}`; - } else { - req.url = `${req.url}?locale=${locale}`; - } - console.log('final url:', req.url); - } - next(); -} - -(async () => { - await app.prepare(); - const server = express(); - - server.use(detectLocale); - server.get("*", (req, res) => handle(req, res)); - - await server.listen(port); - console.log(`> Ready on http://localhost:${port}`); // eslint-disable-line no-console -})(); diff --git a/src/components/Header.js b/src/components/Header.js index a8f317d..1da8b37 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -1,15 +1,13 @@ import Link from "next/link"; +import { useTranslation } from "../i18n"; import styles from "./Header.module.css"; function Header() { + const { t } = useTranslation(); return (
- Home - - {" | "} - - getInitialProps + {t('home')}
); diff --git a/src/i18n.js b/src/i18n.js index ac23eb1..6c60b30 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -2,21 +2,37 @@ const NextI18Next = require('next-i18next').default const path = require('path') const supportedLangs = ['en', 'es']; +const domainLocaleMap = { + localhost: "en", + "nexttest.com": "en", + "nexttest.es": "es", + "nexttest.de": "de", + "it.nexttest.international": "it", + "ua.nexttest.international": "ua", +}; + +const domainDetector = { + name: 'domain', + lookup(req, res, options) { + let language = 'en' + if (typeof window !== 'undefined' ) { + language = domainLocaleMap[window.location.hostname]; + } else { + language = domainLocaleMap[req.hostname]; + } + return language + }, + cacheUserLanguage(req, res, language, options = {}) { + //todo + }, +} module.exports = new NextI18Next({ defaultLanguage: 'en', otherLanguages: supportedLangs, localePath: path.resolve('./public/static/locales'), - serverLanguageDetection: false, - browserLanguageDetection: false + customDetectors: [domainDetector], + detection: { + order: ['domain'] + } }); - -// module.exports = function iniI18N(locale) { -// return new NextI18Next({ -// defaultLanguage: locale, -// otherLanguages: supportedLangs, -// localePath: path.resolve('./public/static/locales'), -// serverLanguageDetection: false, -// browserLanguageDetection: false -// }); -// }; diff --git a/src/pages/_app.js b/src/pages/_app.js index 0c9c201..2385466 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -1,5 +1,4 @@ -import { I18nextProvider } from "react-i18next"; -import i18n, { appWithTranslation } from "../i18n"; +import { appWithTranslation } from "../i18n"; import { useRouter } from "next/router"; import Layout from "../components/Layout"; import "../styles.css"; @@ -7,8 +6,6 @@ import App from 'next/app' function MyApp({ Component, pageProps }) { const router = useRouter(); - const { locale } = router.query; - console.log("App locale:", locale); return ( diff --git a/src/pages/_document.js b/src/pages/_document.js deleted file mode 100644 index 4ae54e4..0000000 --- a/src/pages/_document.js +++ /dev/null @@ -1,22 +0,0 @@ -import Document, { Html, Head, Main, NextScript } from "next/document"; - -class MyDocument extends Document { - static async getInitialProps(ctx) { - const initialProps = await Document.getInitialProps(ctx); - return { ...initialProps }; - } - - render() { - return ( - - - -
- - - - ); - } -} - -export default MyDocument; diff --git a/src/pages/gip.js b/src/pages/gip.js deleted file mode 100644 index eb3ae51..0000000 --- a/src/pages/gip.js +++ /dev/null @@ -1,14 +0,0 @@ -function GetInitialPropsPage({ data }) { - return
{JSON.stringify(data, null, 2)}
; -} - -GetInitialPropsPage.getInitialProps = async () => { - return { - data: { - date: new Date(), - number: Math.random(), - }, - }; -}; - -export default GetInitialPropsPage; diff --git a/src/pages/index.js b/src/pages/index.js index 20fc2d1..82e9f7d 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -8,5 +8,7 @@ export default function Home() { } Home.getInitialProps = async () => { - return {}; + return { + namespacesRequired: ['common'] + }; }; From 6c0824d96570d7dcd802a1410bc5eb22592c4b25 Mon Sep 17 00:00:00 2001 From: Justin York Date: Mon, 17 Aug 2020 12:01:46 -0600 Subject: [PATCH 3/3] Fix language detection on the server --- src/i18n.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/i18n.js b/src/i18n.js index 6c60b30..51a709c 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -1,6 +1,7 @@ const NextI18Next = require('next-i18next').default const path = require('path') +const DEFAULT_LOCALE = 'en'; const supportedLangs = ['en', 'es']; const domainLocaleMap = { localhost: "en", @@ -14,21 +15,22 @@ const domainLocaleMap = { const domainDetector = { name: 'domain', lookup(req, res, options) { - let language = 'en' + let locale = DEFAULT_LOCALE; if (typeof window !== 'undefined' ) { - language = domainLocaleMap[window.location.hostname]; + locale = domainLocaleMap[window.location.hostname]; } else { - language = domainLocaleMap[req.hostname]; + const hostname = req.headers.host?.split(':')[0]; + locale = domainLocaleMap[hostname]; } - return language + return locale; }, - cacheUserLanguage(req, res, language, options = {}) { + cacheUserLanguage(req, res, locale, options = {}) { //todo }, } module.exports = new NextI18Next({ - defaultLanguage: 'en', + defaultLanguage: DEFAULT_LOCALE, otherLanguages: supportedLangs, localePath: path.resolve('./public/static/locales'), customDetectors: [domainDetector],