Skip to content

Commit

Permalink
Set context locale based on the header from lib-nextxp #635
Browse files Browse the repository at this point in the history
  • Loading branch information
pmi committed Jul 18, 2023
1 parent 2dbefc9 commit 3407ef1
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 34 deletions.
4 changes: 0 additions & 4 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ SITE_KEY=/hmdb
# Absolute URL to Content API
CONTENT_API=http://127.0.0.1:8080/site

LAYER_NO=hmdb-no
LAYER_EN=hmdb
LAYER_DEFAULT=hmdb

######## Making the values from .env.development and .env.production PUBLIC to the browser:
NEXT_PUBLIC_APP_NAME=$APP_NAME
NEXT_PUBLIC_MODE=$MODE
Expand Down
11 changes: 11 additions & 0 deletions i18n.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
i18n: {
locales: ['en', 'no'],
defaultLocale: 'en',
},
projects: {
no: 'hmdb-no',
en: 'hmdb',
default: 'hmdb',
}
};
18 changes: 2 additions & 16 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const withTM = require('next-transpile-modules')(['@enonic/nextjs-adapter']);
const withEnonicCache = require('@enonic/nextjs-adapter/server').withEnonicCache;
const i18nConfig = require('./i18n.config');

function getEnonicWebpackConfig(config) {
config.resolve.fallback = {
Expand Down Expand Up @@ -27,22 +28,7 @@ async function getEnonicHeaders() {

const config = {
reactStrictMode: true,
i18n: {
locales: ['en', 'no'],
defaultLocale: 'en',
domains: [
{
// Note: subdomains must be included in the domain value to be matched
// e.g. www.example.com should be used if that is the expected hostname
domain: 'example.com',
defaultLocale: 'en',
},
{
domain: 'example.no',
defaultLocale: 'no',
},
]
},
i18n: i18nConfig.i18n,
webpack: getEnonicWebpackConfig,
headers: getEnonicHeaders,
};
Expand Down
41 changes: 41 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {NextRequest, NextResponse} from 'next/server'
import {PROJECT_ID_HEADER} from '@enonic/nextjs-adapter'
import {projects} from '../i18n.config'

const PUBLIC_ASSET = /\.(.*)$/

export async function middleware(req: NextRequest) {
if (
req.nextUrl.pathname.startsWith('/_next') ||
req.nextUrl.pathname.includes('/api/') ||
PUBLIC_ASSET.test(req.nextUrl.pathname)
) {
return
}

const projectId = req.headers.get(PROJECT_ID_HEADER);
const locale = getProjectLocale(projectId);
if (locale && req.nextUrl.locale !== locale) {
const url = new URL(`/${locale}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url);
console.info(`Middleware: project "${projectId}" needs "${locale}" locale, redirecting to: ${url}`);

const response = NextResponse.redirect(url);

response.headers.set('Accept-Language', locale);
response.cookies.set('NEXT_LOCALE', locale);

return response;
}

return NextResponse.next();
}

function getProjectLocale(projectId: string | null): string | undefined {
if (!projectId) {
return;
}

return Object.keys(projects).find(l => {
return projects[l]?.toLowerCase() === projectId.toLowerCase();
});
}
31 changes: 22 additions & 9 deletions src/pages/[[...contentPath]].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {PageComponent, PageRegion, RegionTree} from '@enonic/nextjs-adapter/guil
// Register component mappings
import "@enonic/nextjs-adapter/baseMappings";
import "../components/_mappings";
import { GetStaticPropsResult, Redirect } from 'next';
import {GetStaticPropsResult, Redirect} from 'next';
import * as i18nConfig from '../../i18n.config'

const query = `query($path: ID) {
guillotine {
Expand All @@ -38,7 +39,7 @@ const query = `query($path: ID) {

export async function getStaticProps(context: Context): Promise<GetStaticPropsResult<FetchContentResult>> {
const path = context.params?.contentPath || [];
console.info(`Accessing static page ${context.preview ? '(preview) ' : ''}at: ${path}`);
console.info(`Accessing static page (locale=${context.locale}) ${context.preview ? '(preview) ' : ''}at: ${path}`);

if (context.preview) {
populateXPHeaders(context);
Expand All @@ -50,7 +51,7 @@ export async function getStaticProps(context: Context): Promise<GetStaticPropsRe
meta,
error = null,
page = null,
} = await fetchContent(path, context);
} = await fetchContent(path, i18nConfig.projects, context);

// HTTP 500
if (error && error.code === '500') {
Expand Down Expand Up @@ -108,7 +109,7 @@ function populateXPHeaders(context: Context) {
}

export async function getStaticPaths() {
const contentApiUrl = getContentApiUrl();
const contentApiUrl = getContentApiUrl(i18nConfig.projects);
const paths = await recursiveFetchChildren(contentApiUrl, '\${site}/', 4);

return {
Expand All @@ -118,7 +119,8 @@ export async function getStaticPaths() {
}

interface Item {
params: { contentPath: string[] }
params: { contentPath: string[] },
locale?: string,
}

export async function recursiveFetchChildren(contentApiUrl: string, path: string, maxLevel: number = 3, filter: (content: any) => boolean = filterUnderscores): Promise<Item[]> {
Expand Down Expand Up @@ -161,11 +163,22 @@ async function doRecursiveFetch(contentApiUrl: string, path: string, maxLevel: n
}

const contentPath = child._path.replace(`/${child.site?._name}/`, '');
prev.push({
params: {
contentPath: contentPath.split('/')
if (i18nConfig?.i18n?.locales?.length) {
for (const locale of i18nConfig.i18n.locales) {
prev.push({
params: {
contentPath: contentPath.split('/')
},
locale
});
}
});
} else {
prev.push({
params: {
contentPath: contentPath.split('/')
}
})
}

// also push all the component urls
if (child.pageAsJson?.regions) {
Expand Down
3 changes: 2 additions & 1 deletion src/pages/_component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import MainView from '@enonic/nextjs-adapter/views/MainView';
// Register component mappings
import "@enonic/nextjs-adapter/baseMappings";
import "../components/_mappings";
import {projects} from '../../i18n.config'

// TODO: Components are now handled by [[...contentPath]].tsx
// Keeping for backwards compatibility
Expand All @@ -18,7 +19,7 @@ export async function getServerSideProps(context: Context) {
meta,
error = null,
page = null,
} = await fetchContent(path, context);
} = await fetchContent(path, projects, context);

// HTTP 500
if (error && error.code === '500') {
Expand Down
3 changes: 2 additions & 1 deletion src/pages/_renderable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import {Context, fetchContent, IS_DEV_MODE, RENDER_MODE} from '@enonic/nextjs-adapter';
import Empty from '@enonic/nextjs-adapter/views/Empty';
import {projects} from '../../i18n.config'

// Register component mappings
import "@enonic/nextjs-adapter/baseMappings";
Expand All @@ -14,7 +15,7 @@ export async function getServerSideProps(context: Context) {
const {
meta,
error = null,
} = await fetchContent(path, context);
} = await fetchContent(path, projects, context);

// HTTP 500
if (error && error.code === '500') {
Expand Down
5 changes: 3 additions & 2 deletions src/pages/api/preview.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {JSESSIONID_HEADER, PROJECT_ID_HEADER, RENDER_MODE_HEADER, XP_BASE_URL_HEADER} from '@enonic/nextjs-adapter';
import {ParsedUrlQuery} from 'querystring';
import {NextApiRequest, NextApiResponse} from 'next';

export default async function handler(req: any, res: any) {
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const {token, path} = req.query;
if (token !== process.env.API_TOKEN) {
// XP hijacks 401 to show login page, so send 407 instead
Expand Down Expand Up @@ -30,7 +31,7 @@ export default async function handler(req: any, res: any) {
}
});

res.redirect(path);
res.redirect(path as string);
}

function extractParams(query: ParsedUrlQuery, omit: string[]) {
Expand Down
3 changes: 2 additions & 1 deletion src/pages/api/revalidate.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {recursiveFetchChildren} from "../[[...contentPath]]";
import {getContentApiUrl} from '@enonic/nextjs-adapter';
import {NextApiRequest, NextApiResponse} from 'next';
import {projects} from '../../../i18n.config'

interface ResponseData {
message: string
Expand All @@ -15,7 +16,7 @@ export default async function handler(req: NextApiRequest,
return res.status(407).json({message: 'Invalid token'});
}

const contentApiUrl = getContentApiUrl({req});
const contentApiUrl = getContentApiUrl(projects, {req});

try {
// Return 200 immediately and do revalidate in background
Expand Down

0 comments on commit 3407ef1

Please sign in to comment.