Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong sitemap #21

Closed
KVRA opened this issue Mar 16, 2022 · 5 comments
Closed

Wrong sitemap #21

KVRA opened this issue Mar 16, 2022 · 5 comments

Comments

@KVRA
Copy link

KVRA commented Mar 16, 2022

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

@cvolant
Copy link
Collaborator

cvolant commented Jul 25, 2022

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 ! 😃

@gehaktmolen
Copy link

gehaktmolen commented Aug 12, 2022

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: {},
  };
};

@JacobSoderblom
Copy link

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 ?? [],
    };
  },
};

@cvolant
Copy link
Collaborator

cvolant commented Nov 2, 2022

I linked toward @JacobSoderblom's suggestion in the docs.

@cvolant cvolant closed this as completed Nov 2, 2022
@vbrzezina
Copy link

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,
          }))
        : [],
    };
  },
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants