Skip to main content

Translate URL slugs

Use different path words in each locale while keeping translated documents connected.

Enable translated slugs only when path segments need different words in each locale. Keep the default shared-slug mode when only the locale prefix changes.

nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@lupinum/ginko-content', '@nuxtjs/i18n'],
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'de'],
    strategy: 'prefix_except_default'
  },
  content: {
    i18n: {
      translatedSlugs: true,
      fallback: {
        de: ['en']
      }
    }
  }
})

Nuxt I18n owns locales and defaultLocale. content.i18n contains only Ginko's fallback and translated-slug policy.

The collection must opt into localization and declare locale-specific route mounts:

content.config.ts
import { defineCollection, defineContentConfig } from '@lupinum/ginko-content/config'

export const docs = defineCollection({
  type: 'page',
  source: '1.*/**/*.md',
  i18n: true,
  route: {
    en: '/docs',
    de: '/dokumentation'
  }
})

export default defineContentConfig({ collections: { docs } })

Build a multilingual site covers shared slugs and fallback before this translated-slug variant.

Translate folder and file names

Name folders and files in each language. Keep the same numeric prefix chain for equivalent documents.

content/
  en/
    1.docs/
      1.getting-started.md
      2.installation.md
  de/
    1.dokumentation/
      1.erste-schritte.md
      2.installation.md

Ginko matches variants by that chain:

  • With /guide and /leitfaden configured as the collection mounts, canonical key 1 joins getting-started and erste-schritte. The mounted source directory is deliberately excluded from canonical identity.
  • 1/2 joins both installation pages.

The translated names become URL segments. Numeric prefixes do not appear in the public path.

Numeric prefixes define identity as well as order. Renaming only 1.getting-started.md to 3.getting-started.md disconnects it from 1.erste-schritte.md. To reorder translated content, change the equivalent prefix in every locale together and update any references that used the generated canonical key.

Switch languages

Build a language switcher from page.route.alternates. Ginko returns already-projected paths, so the browser never has to translate or replace path segments.

vue
<NuxtLink
  v-for="alternate in page.route.alternates"
  :key="alternate.locale"
  :to="alternate.path"
>
  {{ alternate.locale }}
</NuxtLink>

Set content.i18n.strictTranslatedSlugs: true in CI to turn missing-prefix warnings into validation errors.