next-sitemap icon indicating copy to clipboard operation
next-sitemap copied to clipboard

Dont take into account default alternateref and self locale

Open josegoval opened this issue 3 years ago • 9 comments

next-sitemap dont take into account the default alternate ref and duplicate self locale, included defaultLocale. Here is my configuration:

my next config:

...
i18n: {
    locales: [
      "en",
      "es",
    ],
    defaultLocale: "es",
  },
...

My alternateRef:

alternateRefs = [
  {
    href: process.env.NEXT_PUBLIC_WEB_URL,
    hreflang: "es",
  },
  {
    href: process.env.NEXT_PUBLIC_WEB_URL + "/en",
    hreflang: "en",
  },
];

The generated xml:

...
<url><loc>https://web-test.com/faq</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2021-06-04T13:17:26.429Z</lastmod><xhtml:link rel="alternate" hreflang="es" href="https://web-test.com/faq"/><xhtml:link rel="alternate" hreflang="en" href="https://web-test.com/en/faq"/></url>
<url><loc>https://web-test.com/es/faq</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2021-06-04T13:17:26.429Z</lastmod><xhtml:link rel="alternate" hreflang="es" href="https://web-test.com/es/faq"/><xhtml:link rel="alternate" hreflang="en" href="https://web-test.com/en/es/faq"/></url>
<url><loc>https://web-test.com/en/faq</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2021-06-04T13:17:26.429Z</lastmod><xhtml:link rel="alternate" hreflang="es" href="https://web-test.com/en/faq"/><xhtml:link rel="alternate" hreflang="en" href="https://web-test.com/en/en/faq"/></url>
...

However on getServerSideProps I managed it, i leave my configuration there:

export const getServerSideProps = async (ctx) => {
  const { data: ports } = await axios.get(getPorts());

  const fields = ports.map((port) => {
    const endpoint = `/ports/${String(port.ID)}`;
    return {
      loc: process.env.NEXT_PUBLIC_WEB_URL + endpoint,
      lastmod: port.UpdatedAt || new Date().toISOString(),
      // changefreq
      // priority
      alternateRefs: alternateRefs.map((ar) => ({
        ...ar,
        href: ar.href + endpoint,
      })),
    };
  });

  return getServerSideSitemap(ctx, fields);
};

josegoval avatar Jun 04 '21 13:06 josegoval

Hi, any updates?

zhengissov avatar Jul 09 '21 12:07 zhengissov

Hi @iamvishnusankar

I'm running into the same issue, the locale from the loc is reused to build the alternate link:

<url>
    <loc>http://localhost:3000/en-US/contact</loc>
    <xhtml:link rel="alternate" hreflang="en-US" href="http://localhost:3000/en-US/en-US/contact"/>
    <xhtml:link rel="alternate" hreflang="de-DE" href="http://localhost:3000/de-DE/en-US/contact"/>
    <xhtml:link rel="alternate" hreflang="it-IT" href="http://localhost:3000/it-IT/en-US/contact"/>
  </url>

May I know why did you close this ticket ? I'm using "^2.5.7" Also this is about the same issue I guess https://github.com/iamvishnusankar/next-sitemap/issues/284.

For now I have applied this workaround Here is my config

alternateRefs: [
    {
      href: process.env.NEXT_PUBLIC_FRONT + "/en-US",
      hreflang: "en-US",
    },
    {
      href: process.env.NEXT_PUBLIC_FRONT + "/de-DE",
      hreflang: "de-DE",
    },
    {
      href: process.env.NEXT_PUBLIC_FRONT + "/it-IT",
      hreflang: "it-IT",
    },
  ]

And the fix

transform: async (config, path) => {
    return {
      loc: path,
      changefreq: config.changefreq,
      priority: config.priority,
      lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
      alternateRefs: config.alternateRefs.map(alternate => {
        // Ex: try to find '/en-US/'
        const hasPathLocale = locales.indexOf(path.substring(1, 6)) !== -1

        //  Only fix alternateRefs if path has a locale
        return hasPathLocale ? {
          ...alternate,
           // Note: concat original alternate with  '/en-US/my-page' => my-page
          href: `${alternate.href}/${path.substring(7)}`,
          hrefIsAbsolute: true
        } : alternate
      }) ?? [],
    };
  }

Thanks!

gkielwasser avatar Mar 09 '22 14:03 gkielwasser

same here

ghost avatar Mar 20 '22 09:03 ghost

Isn't this desired behaviour? default locale must be included in the alternatives.

https://developers.google.com/search/docs/advanced/crawling/localized-versions?visit_id=637838258679446864-2509958702&rd=1#sitemap

Each element must have a child element <xhtml:link rel="alternate" hreflang="supported_language-code"> that lists every alternate version of the page, including itself.

ahmet8282 avatar Mar 25 '22 17:03 ahmet8282

It is the desired behavior, indeed, but the generator appends the locale string twice, which appears to be a bug. With the suggested transformer instead it looks fine. Google search console keeps complaining that it can't parse the sitemap (the sitemap index is fine) but I don't think it's related to this

apuntovanini avatar Mar 25 '22 18:03 apuntovanini

Ah. I started using hrefIsAbsolute. It fixed that

ahmet8282 avatar Mar 25 '22 19:03 ahmet8282

solution from @gkielwasser fixed the issue for me. Thanx!

@iamvishnusankar I think this patch should be applied to the package.

mosusky avatar Mar 29 '22 14:03 mosusky

@iamvishnusankar @josegoval This issue seem to be resolved in V3! 🎉

CloutProject avatar Jun 10 '22 05:06 CloutProject

@CloutProject got my hopes up there for a moment 😂 I am on v3.0.5 and my sitemap is broken when I remove the fix above https://github.com/iamvishnusankar/next-sitemap/issues/172#issuecomment-1062962507

jlarmstrongiv avatar Jun 10 '22 05:06 jlarmstrongiv

Closing this issue due to inactivity.

github-actions[bot] avatar Mar 07 '23 04:03 github-actions[bot]

This issue is not stale! Please reopen

jlarmstrongiv avatar Mar 07 '23 12:03 jlarmstrongiv

Closing this issue due to inactivity.

github-actions[bot] avatar May 08 '23 04:05 github-actions[bot]

reopen 4.2.3 with this config


module.exports = {
  siteUrl: process.env.SITE_URL || 'https://lesfm.net',
  changefreq: 'daily',
  priority: 0.9,
  generateRobotsTxt: true,
  outDir: './out',
  robotsTxtOptions: {
    policies: [
      {
        userAgent: '*',
        allow: '/',
        disallow: [
          '/login/',
          '/account/',
          '/auth/',
          '/licensing/',
          '/logout/',
          '/dashboard/',
          '/api/',
        ],
      },
    ],
  },
  alternateRefs: [
    {
      href: 'https://lesfm.net/',
      hreflang: 'en',
    },
    {
      href: 'https://lesfm.net/uk/',
      hreflang: 'uk',
    },
    {
      href: 'https://lesfm.net/cs/',
      hreflang: 'cs',
    },
    {
      href: 'https://lesfm.net/da',
      hreflang: 'da',
    },
    {
      href: 'https://lesfm.net/de',
      hreflang: 'de',
    },
    {
      href: 'https://lesfm.net/es',
      hreflang: 'es',
    },
    {
      href: 'https://lesfm.net/fr',
      hreflang: 'fr',
    },
    {
      href: 'https://lesfm.net/it',
      hreflang: 'it',
    },
    {
      href: 'https://lesfm.net/hu',
      hreflang: 'hu',
    },
    {
      href: 'https://lesfm.net/nl',
      hreflang: 'nl',
    },
    {
      href: 'https://lesfm.net/pl',
      hreflang: 'pl',
    },
    {
      href: 'https://lesfm.net/pt',
      hreflang: 'pt',
    },
    {
      href: 'https://lesfm.net/pt-BR',
      hreflang: 'pt-BR',
    },
    {
      href: 'https://lesfm.net/fi',
      hreflang: 'fi',
    },
    {
      href: 'https://lesfm.net/sv',
      hreflang: 'sv',
    },
    {
      href: 'https://lesfm.net/tr',
      hreflang: 'tr',
    },
    {
      href: 'https://lesfm.net/ru',
      hreflang: 'ru',
    },
    {
      href: 'https://lesfm.net/th',
      hreflang: 'th',
    },
    {
      href: 'https://lesfm.net/th',
      hreflang: 'th',
    },
    {
      href: 'https://lesfm.net/ko',
      hreflang: 'ko',
    },
    {
      href: 'https://lesfm.net/ja',
      hreflang: 'ja',
    },
    {
      href: 'https://lesfm.net/zh-CN',
      hreflang: 'zh-CN',
    },
    {
      href: 'https://lesfm.net/zh-TW',
      hreflang: 'zh-TW',
    },
    {
      href: 'https://lesfm.net/ar',
      hreflang: 'ar',
    },
    {
      href: 'https://lesfm.net/he',
      hreflang: 'he',
    },
    {
      href: 'https://lesfm.net/hi',
      hreflang: 'hi',
    },
    {
      href: 'https://lesfm.net/id',
      hreflang: 'id',
    },
    {
      href: 'https://lesfm.net/fil',
      hreflang: 'tl',
    },
    {
      href: 'https://lesfm.net/vi',
      hreflang: 'vi',
    },
    {
      href: 'https://lesfm.net/el',
      hreflang: 'el',
    },
  ],
  exclude: [
    '/404/',
    '/[a-z]/403/',
    '/500/',
    '/auth/',
    '/admin/',
    '/api/',
    '/_next/',
    '/static/',
    '/dashboard/',
    '/login/',
    '/logout/',
    'login-unprotected/',
    '/reset-password/',
    '/new-password/',
    '/register/',
    '/subscriptionError/',
    '/verify/',
    '/register-unprotected/',
    '/analytics/',
  ],

  // Default transformation function
  transform: async (config, path) => {
    return {
      loc: path, // => 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 ?? [],
    };
  },
};

kapyar avatar Apr 23 '24 21:04 kapyar