diff --git a/cms-i18n/directus/docker-compose.yaml b/cms-i18n/directus/docker-compose.yaml index 6e0249c9..be765e28 100644 --- a/cms-i18n/directus/docker-compose.yaml +++ b/cms-i18n/directus/docker-compose.yaml @@ -10,7 +10,7 @@ services: POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: ${DB_DATABASE} healthcheck: - test: ["CMD", "pg_isready", "-U", "${DB_USER}", "-d", "${DB_DATABASE}", "-h", "localhost"] + test: ['CMD', 'pg_isready', '-U', '${DB_USER}', '-d', '${DB_DATABASE}', '-h', 'localhost'] interval: 10s timeout: 5s retries: 5 @@ -20,7 +20,7 @@ services: cache: image: redis:6 healthcheck: - test: ["CMD-SHELL", "[ $$(redis-cli ping) = 'PONG' ]"] + test: ['CMD-SHELL', "[ $$(redis-cli ping) = 'PONG' ]"] interval: 10s timeout: 5s retries: 5 @@ -42,17 +42,17 @@ services: environment: SECRET: ${DIRECTUS_SECRET} - DB_CLIENT: "pg" - DB_HOST: "database" - DB_PORT: "5432" + DB_CLIENT: 'pg' + DB_HOST: 'database' + DB_PORT: '5432' DB_DATABASE: ${DB_DATABASE} DB_USER: ${DB_USER} DB_PASSWORD: ${DB_PASSWORD} CACHE_ENABLED: ${CACHE_ENABLED} CACHE_AUTO_PURGE: ${CACHE_AUTO_PURGE} - CACHE_STORE: "redis" - REDIS: "redis://cache:6379" + CACHE_STORE: 'redis' + REDIS: 'redis://cache:6379' ADMIN_EMAIL: ${ADMIN_EMAIL} ADMIN_PASSWORD: ${ADMIN_PASSWORD} diff --git a/cms-i18n/nuxt/.gitignore b/cms-i18n/nuxt/.gitignore index 611cf1dc..98356901 100644 --- a/cms-i18n/nuxt/.gitignore +++ b/cms-i18n/nuxt/.gitignore @@ -4,3 +4,4 @@ .cache/ .output/ dist/ +.pnpm-store diff --git a/cms-i18n/nuxt/README.md b/cms-i18n/nuxt/README.md index 117ddcb3..2823db1d 100644 --- a/cms-i18n/nuxt/README.md +++ b/cms-i18n/nuxt/README.md @@ -1,18 +1,27 @@ -# Nuxt 3 CMS Template with Directus Integration +# Nuxt 4 CMS Template with Directus Integration & i18n Support
- Nuxt 3 CMS Template Thumbnail + Nuxt 4 CMS Template with i18n Thumbnail
-This is a **Nuxt 3-based CMS Template** that is fully integrated with [Directus](https://directus.io/), offering a CMS -solution for managing and delivering content seamlessly. The template leverages modern technologies like **Nuxt 3's -file-based routing system**, **Tailwind CSS**, and **Shadcn Vue components**, providing a complete and scalable starting -point for building CMS-powered web applications. +This is a **Nuxt 4-based CMS Template with Internationalization (i18n) support** that is fully integrated with +[Directus](https://directus.io/), offering a CMS solution for managing and delivering multilingual content seamlessly. +The template leverages modern technologies like **Nuxt 4's file-based routing system**, **Tailwind CSS**, **Shadcn Vue +components**, and **built-in i18n support**, providing a complete and scalable starting point for building multilingual +CMS-powered web applications. + +> **Note**: This is the i18n-enabled version of the Nuxt CMS template. For a single-language version, see the +> [standard Nuxt CMS template](../nuxt/README.md). ## **Features** -- **Nuxt 3 File-Based Routing**: Uses Nuxt's built-in routing system with dynamic page handling. -- **Full Directus Integration**: Directus API integration for fetching and managing relational data. +- **Nuxt 4 File-Based Routing**: Uses Nuxt's built-in routing system with dynamic page handling. +- **Internationalization (i18n)**: Built-in support for multiple languages with locale-based routing, automatic + translation fetching from Directus, and language switcher component. +- **Full Directus Integration**: Directus API integration for fetching and managing relational data with translation + support. +- **Locale-Aware Content**: Automatic content translation based on URL locale prefixes (e.g., `/en/`, `/es/`) with + fallback to default locale. - **Tailwind CSS**: Fully integrated for rapid UI styling. - **TypeScript**: Ensures type safety and reliable code quality. - **Shadcn Vue Components**: Pre-built, customizable UI components for modern design systems. @@ -35,7 +44,7 @@ you’ll find `pnpm` very similar in usage. You can still use `npm` if you prefe ### **Draft Mode Overview** -Directus allows you to work on unpublished content using **Draft Mode**. This Nuxt 3 template is configured to support +Directus allows you to work on unpublished content using **Draft Mode**. This Nuxt 4 template is configured to support Directus Draft Mode out of the box, enabling live previews of unpublished or draft content as you make changes. ### **Live Preview Setup** @@ -71,14 +80,42 @@ https://yourwebsite.com/blog/some-post?preview=true --- +## **Internationalization (i18n)** + +### **How It Works** + +This template includes built-in internationalization support: + +- **Locale-Based Routing**: URLs automatically include locale prefixes (e.g., `/en/about`, `/es/about`) with the default + locale (en-US) using clean URLs without a prefix. +- **Directus Translation Integration**: Translations are stored in Directus `{collection}_translations` tables and + automatically fetched based on the current locale. +- **Automatic Content Merging**: Translations are automatically merged onto base content objects, so components can use + `item.title` directly without checking for translations. +- **Language Switcher**: Built-in `LanguageSwitcher` component for easy language selection. +- **SSR & Client Support**: Locale detection works on both server-side (via middleware) and client-side (via route + detection). + +### **Directus Setup for i18n** + +The i18n schema (languages collection, translation tables, etc.) is included in the Directus template located in +`../directus/template/`. Apply it to your Directus instance using the +[Directus Template CLI](https://github.com/directus/template-cli): + +```bash +npx directus-template-cli@latest apply +``` + +--- + ## **Getting Started** ### Prerequisites To set up this template, ensure you have the following: -- **Node.js** (16.x or newer) -- **npm** or **pnpm** +- **Node.js** (20.x or newer) +- **pnpm** (8.6.0 or newer) or **npm** - Access to a **Directus** instance ([cloud or self-hosted](../../README.md)) ## ⚠️ Directus Setup Instructions @@ -92,9 +129,9 @@ For instructions on setting up Directus, choose one of the following: You can instantly deploy this template using one of the following platforms: -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/directus-labs/starters/tree/main/cms/nuxt&env=DIRECTUS_URL,NUXT_PUBLIC_SITE_URL,DIRECTUS_SERVER_TOKEN,NUXT_PUBLIC_ENABLE_VISUAL_EDITING) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/directus-labs/starters/tree/main/cms-i18n/nuxt&env=DIRECTUS_URL,NUXT_PUBLIC_SITE_URL,DIRECTUS_SERVER_TOKEN,NUXT_PUBLIC_ENABLE_VISUAL_EDITING) -[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/directus-labs/starters&branch=main&create_from_path=cms/nuxt) +[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/directus-labs/starters&branch=main&create_from_path=cms-i18n/nuxt) ### **Environment Variables** @@ -193,9 +230,22 @@ app/ # Main Nuxt application folder │ │ ├── search/index.ts # Search functionality │ │ ├── users/[id].ts # Fetches user data │ │ ├── authenticated-user.ts # Auth check endpoint +│ ├── middleware/ # Server middleware +│ │ ├── locale.ts # Locale detection and context setup │ ├── utils/ # Backend utilities │ │ ├── directus-server.ts # Directus server-side utilities │ │ ├── directus-utils.ts # General Directus helpers +│ │ ├── directus-i18n.ts # i18n-specific Directus utilities +│ │ ├── i18n.ts # i18n helper functions │ ├── shared/ # Shared backend logic │ │ ├── types/schema.ts # Directus schema types +├── middleware/ # Client-side middleware +│ ├── locale.global.ts # Global locale middleware +├── app/ +│ ├── lib/ +│ │ ├── i18n/ # i18n configuration and utilities +│ │ │ ├── config.ts # Locale configuration +│ │ │ ├── utils.ts # Locale path utilities +│ ├── composables/ +│ │ ├── useLocale.ts # Locale composable for components ``` diff --git a/cms-i18n/nuxt/app/app.vue b/cms-i18n/nuxt/app/app.vue index 27009bab..a0b302d9 100644 --- a/cms-i18n/nuxt/app/app.vue +++ b/cms-i18n/nuxt/app/app.vue @@ -2,7 +2,6 @@ useHead({ meta: [{ charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }], link: [{ rel: 'icon', href: '/favicon.ico' }], - htmlAttrs: { lang: 'en' }, }); diff --git a/cms-i18n/nuxt/app/components/Footer.vue b/cms-i18n/nuxt/app/components/Footer.vue index 31564b8c..adb9452d 100644 --- a/cms-i18n/nuxt/app/components/Footer.vue +++ b/cms-i18n/nuxt/app/components/Footer.vue @@ -1,4 +1,7 @@