From f1b4417e00836480278441d6a6c786da5ba4648a Mon Sep 17 00:00:00 2001 From: Adam Brauer <400763+ambrauer@users.noreply.github.com> Date: Tue, 17 Nov 2020 07:48:13 -0600 Subject: [PATCH] [NextJs] i18n updates (#493) * Source Next.js i18n defaultLocale from package config * Fallback to using package config language for page props (allows sample to run when Next.js i18n is disabled) * Add locale variants of configured rewrites * Upgraded next-localization (w/ rosetta) library as dictionary solution of choice (atm). Simplified usage examples. Updated comments in _app.tsx. * Remove export scripts and build logic for now (since it doesn't work with next.js v10 i18n and image optimization), to be addressed in separate task --- samples/nextjs/next.config.js | 45 ++++++++++++++----- samples/nextjs/package-lock.json | 6 +-- samples/nextjs/package.json | 4 +- samples/nextjs/src/components/Layout.tsx | 8 ++-- .../Styleguide-Multilingual/index.tsx | 6 +-- samples/nextjs/src/pages/[[...path]].tsx | 39 ++++++---------- samples/nextjs/src/pages/_app.tsx | 5 ++- .../src/pages_examples/[[...path]].SSR.tsx | 4 +- 8 files changed, 66 insertions(+), 51 deletions(-) diff --git a/samples/nextjs/next.config.js b/samples/nextjs/next.config.js index ec4ad2fad3..078f4746e9 100644 --- a/samples/nextjs/next.config.js +++ b/samples/nextjs/next.config.js @@ -1,20 +1,25 @@ const jssConfig = require('./src/temp/config'); +const packageConfig = require('./package.json').config; const disconnectedServerUrl = `http://localhost:${process.env.DISCONNECTED_SERVER_PORT || 3042}/`; const disconnected = process.env.JSS_MODE === 'disconnected'; module.exports = (phase) => { - + const env = { // Expose current Next.js phase as an environment variable // See available phases here: https://github.com/vercel/next.js/blob/canary/packages/next/next-server/lib/constants.ts#L1-L4 - NEXT_PHASE: phase - } + NEXT_PHASE: phase, + }; const i18n = { + // These are all the locales you want to support in your application. + // These should generally match (or at least be a subset of) those in Sitecore. locales: ['en', 'da-DK'], - defaultLocale: 'en' - } + // This is the locale that will be used when visiting a non-locale + // prefixed path e.g. `/styleguide`. + defaultLocale: packageConfig.language, + }; async function rewrites() { if (disconnected) { @@ -24,12 +29,20 @@ module.exports = (phase) => { source: '/sitecore/:path*', destination: `${disconnectedServerUrl}/sitecore/:path*`, }, + { + source: '/:locale/sitecore/:path*', + destination: `${disconnectedServerUrl}/sitecore/:path*`, + }, // media items { source: '/data/media/:path*', destination: `${disconnectedServerUrl}/data/media/:path*`, }, - ] + { + source: '/:locale/data/media/:path*', + destination: `${disconnectedServerUrl}/data/media/:path*`, + }, + ]; } else { // When in connected mode we want to proxy Sitecore paths off to Sitecore return [ @@ -37,23 +50,35 @@ module.exports = (phase) => { source: '/sitecore/:path*', destination: `${jssConfig.sitecoreApiHost}/sitecore/:path*`, }, + { + source: '/:locale/sitecore/:path*', + destination: `${jssConfig.sitecoreApiHost}/sitecore/:path*`, + }, // media items { source: '/-/:path*', destination: `${jssConfig.sitecoreApiHost}/-/:path*`, }, + { + source: '/:locale/-/:path*', + destination: `${jssConfig.sitecoreApiHost}/-/:path*`, + }, // visitor identification { source: '/layouts/:path*', destination: `${jssConfig.sitecoreApiHost}/layouts/:path*`, }, - ] + { + source: '/:locale/layouts/:path*', + destination: `${jssConfig.sitecoreApiHost}/layouts/:path*`, + }, + ]; } - } + }; return { env, i18n, - rewrites + rewrites, }; -}; \ No newline at end of file +}; diff --git a/samples/nextjs/package-lock.json b/samples/nextjs/package-lock.json index 5d9b2764a9..b3d6ec7982 100644 --- a/samples/nextjs/package-lock.json +++ b/samples/nextjs/package-lock.json @@ -6330,9 +6330,9 @@ } }, "next-localization": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/next-localization/-/next-localization-0.9.3.tgz", - "integrity": "sha512-hUdxaOENTYZ2WsgpjMYTjVbTecL/EmFPXcaF9tsAFN2vC8uxXiMYNDNmCHgo+aJHmVjxtt2xcxh7CoQoxTnkPA==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/next-localization/-/next-localization-0.10.0.tgz", + "integrity": "sha512-VjooqaJBuHhqUFbeiEqsKrs9y1Ivzh+gc0aTsK2mRfQUxor0mS8zGQpQVUQQ+cMuKSWrBd70oXwi71U8PxF9TA==", "requires": { "eslint": "^7.12.1", "rosetta": "1.1.0" diff --git a/samples/nextjs/package.json b/samples/nextjs/package.json index 357f539371..2a9af9d1df 100644 --- a/samples/nextjs/package.json +++ b/samples/nextjs/package.json @@ -47,7 +47,7 @@ "graphql": "~14.5.7", "graphql-tag": "~2.10.1", "next": "^10.0.0", - "next-localization": "^0.9.3", + "next-localization": "^0.10.0", "nprogress": "~0.2.0", "react": "^16.9.0", "react-apollo": "~3.1.1", @@ -86,11 +86,9 @@ "lint": "eslint --fix ./src/**/*.tsx ./src/**/*.ts ./sitecore/definitions/**/*.ts ./scripts/**/*.ts ./data/**/*.yml", "bootstrap": "ts-node --project tsconfig.scripts.json scripts/bootstrap.ts", "build": "npm-run-all --serial bootstrap next:build", - "export": "cross-env-shell BUILD_MODE=export \"npm-run-all --serial bootstrap next:build next:export\"", "graphql:update": "ts-node --project tsconfig.scripts.json ./scripts/update-graphql-fragment-data.ts", "next:build": "next build", "next:dev": "cross-env NODE_OPTIONS='--inspect' next dev", - "next:export": "next export", "next:start": "next start", "scaffold": "ts-node --project tsconfig.scripts.json scripts/scaffold-component.ts", "start": "npm-run-all --serial bootstrap --parallel next:dev start:watch-components", diff --git a/samples/nextjs/src/components/Layout.tsx b/samples/nextjs/src/components/Layout.tsx index 7ec835c34f..738b9cea21 100644 --- a/samples/nextjs/src/components/Layout.tsx +++ b/samples/nextjs/src/components/Layout.tsx @@ -15,7 +15,7 @@ const LOGO_SIZE = { WIDTH: 221, HEIGHT: 48 }; // This is boilerplate navigation for sample purposes. Most apps should throw this away and use their own navigation implementation. // Most apps may also wish to use GraphQL for their navigation construction; this sample does not simply to support disconnected mode. const Navigation = () => { - const i18n = useI18n(); + const { t } = useI18n(); return (
This is a static dictionary entry from /data/dictionary
:
- {i18n.t('styleguide-sample')}
+ {t('styleguide-sample')}
@@ -38,7 +38,7 @@ const StyleguideMultilingual = (props: StyleguideMultilingualProps): JSX.Element
-The current language is: {i18n.locale()}
+The current language is: {locale()}