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

i18n Multilingual Nuxt Website - The right way - rel-alternate-hreflang #91

Closed
nicolas-giuristante opened this issue Dec 11, 2019 · 17 comments · Fixed by #119
Closed

i18n Multilingual Nuxt Website - The right way - rel-alternate-hreflang #91

nicolas-giuristante opened this issue Dec 11, 2019 · 17 comments · Fixed by #119
Assignees
Milestone

Comments

@nicolas-giuristante
Copy link

nicolas-giuristante commented Dec 11, 2019

What problem does this feature solve?

Hello! 👋🏼

Proposition : Automatically generate adequate sitemap with the concept rel-alternate-hreflang proposed by Google itself when using nuxt-i18n paths feature.

Why : Multilingual website cannot benefit from this plugin's automatic sitemap generation at the moment without heavy modifications/custom code. It would greatly help newcomers that doesn't know how to code this properly AND devs who do not know SEO's current best practices towards multilingual websites.

Source : Tell Google about localized versions of your page[https://support.google.com/webmasters/answer/189077?hl=en]

I am sure this can be implemented easily. nuxt-i18n is already supporting this rel-alternate-hreflang concept with link tags in the head.

What does the proposed changes look like?

Exemple

// contact.vue
nuxtI18n: {
    paths: {
        en: '/contact-us',
        fr: '/contactez-nous',
    },
},

Would generate

// generated sitemap.xml
<url>
    <loc>https://example.ca/en/contact-us/</loc>
    <xhtml:link rel="alternate" hreflang="fr-ca" href="https://example.ca/fr/contactez-nous/" />
    <xhtml:link rel="alternate" hreflang="en-ca" href="https://example.ca/en/contact-us/" />
    <changefreq>monthly</changefreq>
    <priority>1.0</priority>
</url>

Root page x-default when all locales are prefixed
Bonus point if you could support for the newest x-default value on root when i18n's option strategy = prefix

// generated sitemap.xml
<url>
    <loc>https://example.ca/</loc>
    <xhtml:link rel="alternate" hreflang="fr-ca" href="https://example.ca/fr/" />
    <xhtml:link rel="alternate" hreflang="en-ca" href="https://example.ca/en/" />
    <xhtml:link rel="alternate" hreflang="x-default" href="https://example.ca/" />
    <changefreq>monthly</changefreq>
    <priority>1.0</priority>
</url>
This feature request is available on Nuxt community (#c73)
@ghost ghost added the cmty:feature-request label Dec 11, 2019
@nicolas-giuristante nicolas-giuristante changed the title i18n Multilingual Nuxt Website - The right way rel-alternate-hreflang i18n Multilingual Nuxt Website - The right way - rel-alternate-hreflang Dec 11, 2019
@JacekZakowicz
Copy link

Hi! If not translated URLs, at least it should use language suffixes like /de, /fr, etc.

@nicolas-giuristante
Copy link
Author

Hi! If not translated URLs, at least it should use language suffixes like /de, /fr, etc.

I am not sure I get what you mean. Do you mind rephrasing?

@JacekZakowicz
Copy link

Hi,

I mean that instead of this:

<url> <loc>https://my-domain.com/about</loc> </url> <url> <loc>https://my-domain.com/de/about</loc> </url> <url> <loc>https://my-domain.com/fr/about</loc> </url>

we should at least have:

<url> <loc>https://my-domain.com/about</loc> <xhtml:link rel=”alternate” hreflang=”en” href=”https://my-domain.com/about”/> <xhtml:link rel=”alternate” hreflang=”de” href=”https://my-domain.com/de/about”/> <xhtml:link rel=”alternate” hreflang=”fr” href=”https://my-domain.com/fr/about”/> </url>

But you can consider it as two separate issues probably.

@nicolas-giuristante
Copy link
Author

@JacekZakowicz That is one main aspect of my proposition. (:

You explicitly displayed the root problem. So thank you for that. Right now, every locale is its own, which is technically bad for SEO. My proposition above would fix that. And without canonical nonsense as a bonus (which are now not recommended between translated pages).

@stouch
Copy link

stouch commented Apr 10, 2020

I'd need this too ! Is this available in the current version ?

@NicoPennec
Copy link
Member

NicoPennec commented Apr 14, 2020

@nicolas-giuristante Thank your for this great idea 👍

I'm starting to do some tests with sitemap + nuxt-i18n. The first results are on the right track!

But I'm not sure to understand when to push the "x-default" value, depending on each strategy.

For eg. with the following nuxt-i18n config, see bellow each routes generated by strategy:

i18n: {
  defaultLocale: 'en',
  locales: ['en', 'es', 'fr'],
  strategy: ...
}
  • prefix_except_default
{ name: 'about___en', url: '/about/' },
{ name: 'about___es', url: '/es/about/' },
{ name: 'about___fr', url: '/fr/about/' }
  • prefix
{ name: 'about___en', url: '/en/about/' },
{ name: 'about___es', url: '/es/about/' },
{ name: 'about___fr', url: '/fr/about/' }
  • prefix_and_default
{ name: 'about___en___default', url: '/about/'}
{ name: 'about___en', url: '/en/about/' },
{ name: 'about___es', url: '/es/about/' },
{ name: 'about___fr', url: '/fr/about/' }

So, from my understanding, the "x-default" should be only available for the last strategy "prefix_and_default", with a generated sitemap.xml as follows:

<url>
    <loc>http://localhost:3000/en/about/</loc>
    <xhtml:link rel="alternate" hreflang="x-default" href="http://localhost:3000/about/" />
    <xhtml:link rel="alternate" hreflang="en" href="http://localhost:3000/en/about/" />
    <xhtml:link rel="alternate" hreflang="es" href="http://localhost:3000/es/about/" />
    <xhtml:link rel="alternate" hreflang="fr" href="http://localhost:3000/fr/about/" />
</url>

@NicoPennec NicoPennec self-assigned this Apr 22, 2020
@damienroche
Copy link

any news about this feature ?

@NicoPennec NicoPennec added this to the 2.x milestone May 3, 2020
@NicoPennec
Copy link
Member

NicoPennec commented May 4, 2020

@damienroche coming soon!

You can test the feature branch with npm install nuxt-community/sitemap-module#i18n-support with i18n option (see docs)

@damienroche
Copy link

Hi @NicoPennec
thanks for this. I've just updated my module, but I have an issue.
When I call the sitemap.xml, Nuxt returns this error : Cannot read property 'split' of undefined from builder.js line 53 route.name.split(routesNameSeparator)

My nuxt.config.js file looks like this :

export default {
  ...,
  modules: {
   ...,
   [ 'nuxt-i18n', {
     locales: [
      {
         code: 'fr',
         iso: 'fr-FR',
         name: 'Français'
      },
      {
         code: 'en,
         iso: 'en-US',
         name: 'English'
      }
     ],
     defaultLocale: 'en',
     detectBrowserLanguage: {
      useCookie: true,
      alwaysRedirect: true
     },
     vueI18n: {
      messages: { fr, en }
     }
   }
  '@nuxtjs/sitemap' 
  },
  sitemap: {
   hostname: 'https://www.nuatelier.com',
   gzip: true,
   i18n: 'en',
   routes: [
     {
      url: 'shop',
      priority: 1
     },
     {
      url: 'project',
      priority: 0.8
     },
     {
      url: 'contact',
      priority: 0.7
     },
     {
      url: 'press',
      priority: 0.5
     }
   ]
  }
}

@NicoPennec
Copy link
Member

@damienroche my bad... I just pushed a fix.
This feature is currently on WIP status, so more testing are needed before releasing it.
A big thanks for your help 🙏

@mccare
Copy link

mccare commented May 9, 2020

Just tried it:

  • excludes do not honor the language specific files, e.g. wanting to exclude  /test/* I needed to write
    exclude: ['/de/test/*', '/test/*' ]
  • you need to set defaultLocale in i18n module

Otherwise did work as advertised.

@NicoPennec
Copy link
Member

NicoPennec commented May 9, 2020

Many thanks for your feedback @mccare 🙏

  • 1/ yes, currently you have to use a glob pattern depending of your i18n strategy option, eg. exclude: ['/*/test']. The data returned by the vue-router do not allow to do otherwise.

  • 2/ no, the "defaultLocale" of the sitemap module is deliberately
    not related to the "defaultLocale" of the i18n module.
    eg. you can set as follows and it works

i18n: { locales: ['en', 'de'] },
sitemap: { i18n: true },

NicoPennec added a commit that referenced this issue May 11, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
fix #91
@NicoPennec
Copy link
Member

This feature is available since the release 2.3.0.
See docs

Thank @nicolas-giuristante for your proposal and @damienroche @mccare for the review 🙏

@b-jan
Copy link

b-jan commented May 25, 2020

This new feature is not working for my config.
I get errors in console (maybe not related) and I only see:
image

When removing the i18n property in sitemap config, no error.

i18n: {
   locales: [
     {
       code: 'en',
       iso: 'en-US'
     },
     {
       code: 'fr',
       iso: 'fr-FR'
     }
   ],
   seo: true,
   defaultLocale: 'fr',
   vueI18n: {
     fallbackLocale: 'fr',
     messages: {
       fr: require('./locales/fr.json'),
       en: require('./locales/en.json')
     }
   }
 },

@NicoPennec
Copy link
Member

NicoPennec commented May 25, 2020

@b-jan your console errors are about a chrome extension.

Then, your output seems good. It's only a rendering issue on your browser, due to the xml namespace of the elements xhtml:link. Your browser will convert the XML rendering to a XHTML page rendering because it see a know "xhtml:*" namespace.

Check the source code of the sitemap.xml, you will see that your XML file is correct.
As you know, a sitemap is an XML file for crawler, but not for human ;-)

@b-jan
Copy link

b-jan commented May 25, 2020

Thanks @NicoPennec it is perfect :)

@nicolas-giuristante
Copy link
Author

Thank you @NicoPennec and all others who participated for this integration. I'm sorry for my lack of feedback and update on one of my own initial initiative. In any case, I am glad it was considered and built in the meantime, simply amazing! I am sure it will benefit a lot people in the long run.

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

Successfully merging a pull request may close this issue.

7 participants