I need to set up global head in Nuxt for my app, which some subpages will overwrite. Those global head needs to contain translated data.
I created seoHead.js
file with code:
import Vue from "vue"; export const $t = (sign) => Vue.prototype.$nuxt.$options.i18n.t(sign); export default { title: $t("seoGlobal.title"), meta: [ { charset: "utf-8" }, { name: "viewport", content: "width=device-width, initial-scale=1" }, { hid: "description", name: "description", content: $t("seoGlobal.description"), }, { hid: "ogSiteName", name: "og:site_name", content: "Test Page", }, { hid: "ogTitle", name: "og:title", content: $t("seoGlobal.ogTitle"), }, (...) ], };
I import and use this data in my index.vue
and other pages like this:
import seoHead from "~/constants/seoHead"; export default { head() { const metaI18n = this.$nuxtI18nSeo(); const currentPath = process.env.LP_URL + this.$router.currentRoute.fullPath; return { ...seoHead, meta: [ { hid: "ogLocale", name: "og:locale", content: metaI18n.meta[0].content, }, { hid: "ogLocaleAlternate", name: "og:locale:alternate", content: metaI18n.meta[1].content, }, { hid: "ogUrl", name: "og:url", content: currentPath, }, ], }; }, (...)
Unfortunately, I am facing Cannot read property '$options' of undefined
error. It’s strange for me, because I already used export const $t = (sign) => Vue.prototype.$nuxt.$options.i18n.t(sign);
code in another js file. Anyone know why this error appears? You know the best way to translate global head options?
Advertisement
Answer
As discussed in the comments, there seems to be a timing issue with the Nuxt lifecycle and your component: at the time your component seoHead.js
is imported, Nuxt has not yet injected its $nuxt
object into Vue
. So an easy workaround would be to delay the execution of your $t
function (which accesses $nuxt
):
- Change your component to export a function which returns the object, instead of directly exporting the object:
export default function() { return { title: $t("seoGlobal.title"), // ... } }
- In
index.vue
, change yourhead
function to callseoHead
when spreading it:
return { ...seoHead(), // ...
This way, the code which accesses $nuxt
will be executed later — not when seoHead
is imported, but only when the head
function is executed. At this time, the Nuxt lifecycle hopefully has finished its startup work and the required object is in place.
As I said, this is merely a workaround; if you would be calling head
immediately in index.vue
, the same error would appear. So unless you find out a proper way to integrate into the Nuxt lifecycle, I suggest to also put a safeguard into your translation function:
const $t = (sign) => Vue.prototype.$nuxt ? Vue.prototype.$nuxt.$options.i18n.t(sign) : sign
This will return the i18n key if the required infrastructure is not yet in place. Not great, but better than an exception 😉
Alternatively you might be able to directly import your i18n functionality, without going through Nuxt at all; this way you wouldn’t have any dependency on the infrastructure at all — much better.