Integrations

Nuxt I18n

Last updated by Harlan Wilton in doc: i18n usage (#424).

Introduction

OG Image components render as Nuxt Islands (server components), which means useI18n() composables don't have automatic access to locale context or lazy-loaded messages.

This guide covers two patterns for creating localized OG images with @nuxtjs/i18n.

The simplest approach is to resolve translations at the page level and pass them as props to your OG image component.

pages/index.vue
<script setup lang="ts">
const { t } = useI18n()

// Pass already-translated strings as props
defineOgImageComponent('MyOgImage', {
  title: t('og.title'),
  description: t('og.description'),
})
</script>

Your OG image component receives the translated strings directly:

components/OgImage/MyOgImage.vue
<script setup lang="ts">
defineProps<{
  title: string
  description: string
}>()
</script>

<template>
  <div class="w-full h-full flex flex-col justify-center p-12 bg-white">
    <h1 class="text-6xl font-bold">
      {{ title }}
    </h1>
    <p class="text-2xl text-gray-600">
      {{ description }}
    </p>
  </div>
</template>
This pattern is recommended because it's simple, works reliably, and keeps your OG image components reusable.

Pattern 2: Using useI18n with loadLocaleMessages

If you need to use useI18n() directly inside your OG image component (for example, to access many translation keys), you can pass the locale as a prop and use loadLocaleMessages() to load the messages.

pages/index.vue
<script setup lang="ts">
const { locale } = useI18n()

// Pass locale as a prop
defineOgImageComponent('MyOgImage', {
  locale: locale.value,
})
</script>

In your OG image component, load the messages for the requested locale:

components/OgImage/MyOgImage.vue
<script setup lang="ts">
const props = defineProps<{
  locale?: string
}>()

const { t, locale, loadLocaleMessages } = useI18n()

// Load messages for the requested locale, then set it as active
if (props.locale) {
  await loadLocaleMessages(props.locale)
  locale.value = props.locale
}
</script>

<template>
  <div class="w-full h-full flex flex-col justify-center p-12 bg-white">
    <h1 class="text-6xl font-bold">
      {{ t('og.title') }}
    </h1>
    <p class="text-2xl text-gray-600">
      {{ t('og.description') }}
    </p>
  </div>
</template>
The loadLocaleMessages() function is provided by @nuxtjs/i18n. It asynchronously loads the messages for a specific locale, which is necessary because OG image components render in an isolated server context.

Why Direct useI18n Doesn't Work

When you use useI18n() in a regular page component, the i18n module:

  1. Detects the locale from the URL path (e.g., /es/about), cookies, or headers
  2. Loads the messages for that locale
  3. Provides them to the composable

OG image components render as Nuxt Islands via an internal request like /__nuxt_island/MyOgImage_abc123.json. This request:

  • Doesn't have the locale prefix in the URL
  • Doesn't have the user's cookies (when fetched by social platforms)
  • Doesn't have locale messages pre-loaded

This is why you need to either pass translated strings as props (Pattern 1) or explicitly load the messages (Pattern 2).

Did this page help you?