Preview links don't redirect properly for non-default locales

We have a Nuxt fully-static site that's deployed to Netlify, and uses nuxt-i18n for localization.

"dependencies": {
    "nuxt": "^2.15.6",
    "nuxt-i18n": "^6.27.0",
    "@nuxtjs/prismic": "^1.3.1",
    "@prismicio/client": "^4.0.0",
}

When we go to preview a page from Prismic on localhost, it successfully redirects to the preview page no matter what locale we're previewing.

However, when we go to preview on our Netlify deployment, it doesn't seem to strip the preview url (/prismic-preview) from the final URL.

For example, here's what happens for the en-au version of our FAQ page:

  • When previewing on localhost, it navigates to http://localhost:3000/en-au/faq :tada:
  • When previewing to our Netlify deployment, it navigates to https://our-project.netlify.app/prismic-preview/en-au/faq

Because this route doesn't exist (with prismic-preview in it), we get a 404. The weird thing is this only happens with non-default locales! Our default locale doesn't have any locale code in the URL, and prismic successfully goes to https://our-project.netlify.app/faq to preview it.

Previewing other locales was definitely working until recently, so we're quite puzzled over how it stopped seemingly overnight.

Thanks so much for your help!

Hi Rachel,

This seems like a strange one. Can you share with me...

  1. the linkresolver for your project
  2. an example of the structure of your pages directory
  3. your settings for @nuxtjs/prismic in the nuxt.config
  4. the content of the generate object in your nuxt.config

This information will really help me debug your issue.

Thanks.

Hey Phil,

Sure thing. Thanks for looking into this for us.

link-resolver.js:

import articlesJSON from '@/data/cms/clarity_article.json' // this is populated by a prismic data pull
import { matchLanguage } from '@/utils/prismic-tools.mjs'

const getArticleData = (uid) => {
  const foundArticle = articlesJSON['en-us'].find(article => article.uid === uid)

  if (foundArticle) {
    return foundArticle.data
  }

  throw new Error(`link-resolver.js was unable to find clarity article with the UID of ${uid}`)
}

const getLocaleURL = (prismicLocale) => {
  // this just matches the prismic locale codes to our i18n locale codes
  const i18nLocale = matchLanguage(prismicLocale) 

  if (i18nLocale === 'en-us') {
    return ''
  }

  return i18nLocale;
}

export default function(doc) {
  const localeURL = getLocaleURL(doc.lang)

  if (doc.isBroken) {
    return `${localeURL}/not-found`
  }

  if (doc.type === 'clarity_article') {
    if (!doc.data) {
      doc.data = getArticleData(doc.uid)
    }

    return `${localeURL}/clarity/${doc.data.category.uid}/${doc.uid}`
  }

  if (doc.type === 'author') {
    return `${localeURL}/clarity`
  }

  if (doc.type === 'case_study_listing') {
    return `${localeURL}/case-studies`
  }

  if (doc.type === 'case_study') {
    return `${localeURL}/case-studies/${doc.uid}`
  }

  if (doc.type === 'clarity_category' || doc.type === 'clarity_listing') {
    return `${localeURL}/clarity`
  }

  if (doc.type === 'founder_details') {
    return `${localeURL}/founders-of-clearco/${doc.uid}`
  }

  if (doc.type === 'founders_listing') {
    return `${localeURL}/founders-of-clearco`
  }

  if (doc.type === 'faq') {
    return `${localeURL}/faq`
  }

  if (doc.type === 'simple_lander') {
    return `${localeURL}/go/${doc.uid}`
  }

  if (doc.type === 'about_us_legacy') {
    return `${localeURL}/about-us`
  }

  if (doc.type === 'partners_legacy') {
    return `${localeURL}/partners`
  }

  if (doc.type === 'homepage_rebrand') {
    return `${localeURL}/`
  }

  return `${localeURL}/not-found`
}

Page directory structure:

/pages/faq.vue is the page I referenced as an example.

We also have other subpages & dynamic routes, for example our case studies:

/pages/case-studies/_id.vue, and
/pages/case-studies/index.vue

Settings for @nuxtjs/prismic in the nuxt.config:

prismic: {
    endpoint: 'https://clearbanccom.cdn.prismic.io/api/v2',
    linkResolver: '@/plugins/link-resolver',
    htmlSerializer: '@/plugins/html-serializer'
  },

Generate object in nuxt.config:


// We populate dynamicRoutes using json files created by our prismic data pull, like this:

import studies from './data/cms/case_study.json'

let dynamicRoutes = []

studies['en-us'].forEach((study) => {
  dynamicRoutes.push(`/case-studies/${study.uid}`)
})

generate: {
    fallback: '404.html',
    routes: dynamicRoutes
  }

Please also see this other help ticket we created, which explains why we don't have
preview: '/prismic-preview'

In our nuxt.config for Prismic (for good measure, I tried adding that and it didn't appear to make any difference).

Thanks again!

OK, thanks a lot this really helps. My first guess is that the preview system doesn't have access to your i18n file in the link resolver in static mode, so the best way to do this is actually just get the lang from the document itself like we do in our nuxt multi-lang example here:

Hey Phil,

We already do use the doc.lang from Prismic. With this line: const i18nLocale = matchLanguage(prismicLocale) in our link-resolver, we simply match Prismic's locale code to the language prefixes that i18n uses.

See here:

/**
 * Using the Prismic locale code, return the matching locale code that i18n uses
 * @param {string} entryLang - Prismic languge code
 * @returns {string} i18n language code
 */
const matchLanguage = (entryLang) => {
  const languages = {
    // prismicCode: i18nCode
    'en-ca': 'en-us',
    'en-gb': 'en-uk',
    'en-au': 'en-au',
    'en-eu': 'en-eu'
  }
  const i18nLocale = languages[entryLang]

  if (i18nLocale) {
    return i18nLocale
  }

  throw new Error(
    "Data from Prismic is in a language the doesn't match our languages object"
  )
}

I've been trying to debug this all day... I've tried setting up previews from scratch on the project using the docs, downgrading the prismic & nuxt-i18n packages, gradually stripping our project of functionality to see where the issue is, etc.

I managed to fix it!

I realized that the URL returned by link-resolver for non-default locales didn't have a leading slash, whereas the URL for en-us DID have a leading slash (and that one was working). This, combined with some other fixes specific to additional functionality in our codebase, did it!

I wonder if this brittle-ness related to the leading slash is new? In any case, I'm glad to have been able to find a fix.

OK, I understand better why your i18n file is necessary in your case.

I'm really glad you figured this out :smile:

I haven't seen this leading slash issue before in the link resolver, although I have seen it in the route resolver (There was a fix pushed for that). So I'll create an issue in our tracker for the team to investigate this issue once they get time.

Is there any chance you can share your fix for this? It would really help future users who encounter this problem.

Thanks.

Sure.

So we had

const getLocaleURL = (prismicLocale) => {
  const i18nLocale = matchLanguage(prismicLocale)
  if (i18nLocale === 'en-us') {
    return ''
  }

  return '/' + i18nLocale // Added the slash here
}

Used in our link-resolver:

export default function(doc) {
  const localeURL = getLocaleURL(doc.lang)

  if (doc.isBroken) {
    return `${localeURL}/not-found`
  }

  if (doc.type === 'case_study_listing') {
    return `${localeURL}/case-studies`
  }
}

This made it so that routes with AND without a locale code started with /.

Additionally, we had an issue with previews sometimes not working on localhost. Here's how we were getting the preview data in our page files:

async fetch() {
    if (this.$prismic.isPreview) {
      const pageContentLatest = await fetchPrismicData('case_study_listing')
     
      this.pageContent = pageContentLatest
    }
  },

Well, it turns out we had to add fetchOnServer: false, and that fixed the intermittent issues we had on localhost.

1 Like

Thanks this is really useful :slight_smile:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.