Closed KVRA closed 2 years ago
I never used next-sitemap. I gave a quick look to the readme, and if I understand correctly you want to leverage the transform function to translate the path...
The path you get should be the file path prefixed by the locale : translateUrl
handle this.
If you succeed to make it work, please open a pull request here to add the correct config to the readme ! 😃
You could try the following; create sitemap.xml.tsx
within your pages folder with the following content:
import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
import * as React from 'react';
import fs from 'fs';
import { translateUrl } from 'next-translate-routes';
export default function Sitemap() {
return null;
};
export const getServerSideProps: GetServerSideProps = async (props: GetServerSidePropsContext) => {
const { res, locales, defaultLocale } = props;
const url = `${process.env.PROJECT_URL?.replace(/\/+$/, '')}`;
const ourLocales = (Array.isArray(locales) ? locales : [defaultLocale || 'en']);
// Get static paths.
const pagesDirectory = fs.readdirSync('src/pages');
const pages = pagesDirectory
.filter(page => page.match(/.*\.(tsx?)/ig))
.filter(page => !['_app.tsx', '_document.tsx', '_error.tsx', 'sitemap.xml.tsx'].includes(page))
.map(page => page.replace('.tsx', ''));
let paths = pages.map(page => ourLocales.map(locale => ({
locale,
path: `${url}${translateUrl(page, locale)}`,
})));
// Get dynamic paths.
try {
const yourDynamicRequestedPaths: Something[] = await yourAPIRequest();
paths = [
...paths,
...yourDynamicRequestedPaths,
];
} catch (error) {
}
const entries = paths.map((entry) => `
<url>
<loc>${entry.find(path => path.locale === (defaultLocale || 'en'))?.path}</loc>
<lastmod>${new Date().toISOString()}</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
${entry.map(path => `<xhtml:link rel="alternate" hreflang="${path.locale}" href="${path.path}"/>`).join('')}
</url>
`).join('');
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml" >
${entries}
</urlset>`;
res.setHeader('Content-Type', 'text/xml');
res.write(sitemap);
res.end();
return {
props: {},
};
};
This is how I got it working
/** @type {import('next-sitemap').IConfig} */
const path = require('path');
const { translateUrl } = require('next-translate-routes');
const { createNtrData } = require('next-translate-routes/plugin');
const nextConfig = require('./next.config');
const i18NextConfig = require('./next-i18next.config');
const data = createNtrData(
nextConfig,
path.resolve(process.cwd(), './src/pages')
);
global.__NEXT_TRANSLATE_ROUTES_DATA = data;
module.exports = {
siteUrl: process.env.SITE_URL,
generateRobotsTxt: true, // (optional)
// ...other options
transform: async (config, path) => {
const locale =
i18NextConfig.i18n.locales.find(
(locale) => path.indexOf(`/${locale}/`) > -1
) || i18NextConfig.i18n.defaultLocale;
return {
loc: translateUrl(path, locale), // => this will be exported as http(s)://<config.siteUrl>/<path>
changefreq: config.changefreq,
priority: config.priority,
lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
alternateRefs: config.alternateRefs ?? [],
};
},
};
I linked toward @JacobSoderblom's suggestion in the docs.
If someone is is wondering how to add alternateRefs for each language, here's how I got it working
/** @type {import('next-sitemap').IConfig} */
module.exports = {
siteUrl: process.env.NEXT_PUBLIC_SITE_URL,
generateRobotsTxt: true,
transform: (config, path) => {
const locale = i18NextConfig.i18n.locales.find((locale) => path.includes(`/${locale}`));
const fileUrl = urlToFileUrl(path, locale || i18NextConfig.i18n.defaultLocale);
return {
loc: translateUrl(path, locale || i18NextConfig.i18n.defaultLocale),
changefreq: config.changefreq,
priority: config.priority,
lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
alternateRefs: fileUrl
? i18NextConfig.i18n.locales.map((locale) => ({
href: `${process.env.NEXT_PUBLIC_SITE_URL}${fileUrlToUrl(fileUrl, locale)}`,
hreflang: locale,
hrefIsAbsolute: true,
}))
: [],
};
},
};
The package next-sitemap is not getting the translations
How to generate a sitemap with the translated paths ?
I would able to do it manually but translateUrl and translatePath ( methods ) don't seems to work well when the first parameter is a URL in another language that is not the default one,
ex : translateUrl('/home','fr-FR') == gets the path for French But how to get the English path given a French one ? Or a third language given the french path ? Thanks