Clocale

Nuxt.js

This guide demonstrates how to integrate Clocale into your Nuxt.js application, supporting both client-side rendering (CSR) and server-side rendering (SSR) for a seamless internationalization experience.


Installing Dependencies

Begin by adding the Clocale package to your Vue.js project using npm:

npm install @clocale/vue

This package provides all the necessary tools and composables for managing translations in your Vue application.


Client-Side Setup

Step 1: Register the Client Plugin

Create a client-side plugin to enable reactive translations throughout your application. This plugin initializes Clocale with client-side capabilities and reads the user's locale preference from a cookie:

// plugins/clocale.client.ts
import { ClocalePlugin } from '@clocale/vue';

export default defineNuxtPlugin((nuxtApp) => {
  const locale = useCookie('locale').value || 'en';
  const runtime = useRuntimeConfig();

  nuxtApp.vueApp.use(ClocalePlugin, {
    type: 'client',
    locale,
    baseUrl: runtime.public.clocaleBaseUrl,
    isDev: process.dev,
  });
});

What this does:

  • Retrieves the user's saved locale from a cookie (defaults to 'en')
  • Configures Clocale to fetch translations from your specified endpoint
  • Enables development mode helpers when running in dev environment

Step 2: Use Translations in Your Components

After setting up the plugin, you can access translations and locale controls in any component:

<script setup lang="ts">
import { useTranslation, useLocale } from '@clocale/vue';

const { t } = useTranslation('common');
const { locale, setLocale } = useLocale();
</script>

<template>
  <h1>{{ t('home.title') }}</h1>
  <button @click="setLocale(locale === 'en' ? 'fr' : 'en')">Toggle</button>
</template>

Key composables:

  • useTranslation('namespace') - Provides the t() function for accessing translations
  • useLocale() - Gives you the current locale and ability to switch languages

Server-Side Rendering (SSR)

For optimal performance and SEO, you'll want translations to be available during server-side rendering. This eliminates the "flash of untranslated content" and ensures search engines see properly localized pages.

Step 1: Configure the Server Plugin

Create a server-side plugin that preloads translations before rendering your pages:

// plugins/clocale.server.ts
import { defineNuxtPlugin } from '#app';
import { ClocalePlugin } from '@clocale/vue';
import { getCookie } from 'h3';
import { getClocaleClient } from '~/utils/clocale';

export default defineNuxtPlugin(async (nuxtApp) => {
  const event = nuxtApp.ssrContext?.event;
  const initialLocale = event ? getCookie(event, 'locale') || 'en' : 'en';

  // Preload SSR translations
  const clocaleClient = await getClocaleClient();
  const ssrTranslations = clocaleClient?.fetchTranslations(['test']);

  nuxtApp.vueApp.use(ClocalePlugin, {
    type: 'server',
    locale: initialLocale,
    ssrTranslations: (await ssrTranslations) || [],
    isDev: import.meta.env.DEV,
  });

  return {
    provide: {
      clocaleClient,
    },
  };
});

This plugin fetches translations on the server for each request, ensuring your HTML is fully translated before it reaches the browser.

Step 2: Create Server Utilities

Build reusable utilities for server-side translation fetching:

// app/utils/clocale.ts
import { ClocaleNuxt, createServerClient } from '@clocale/vue/nuxt';
import { getLocale } from '~/utils/locale';

export const { getTranslation, getClocaleClient } = createServerClient({
  getLocale,
  builder: async (locale) =>
    ClocaleNuxt().init({
      locale,
      baseUrl: process.env.CLOCALE_URL,
      isDev: true,
    }),
});

This creates a per-request Clocale client that properly handles locale isolation in SSR contexts.

Step 3: Set Up Locale Management

Create helpers to read and write the user's locale preference using cookies:

// app/utils/locale.ts
const COOKIE_NAME = 'locale';

export const getLocale = () => {
  const cookie = useCookie(COOKIE_NAME);
  return cookie.value || 'en';
};

export const setLocale = (locale: string) => {
  const cookie = useCookie(COOKIE_NAME);
  cookie.value = locale;
};

These utilities provide a single source of truth for locale management across your application.

Step 4: Create a Locale API Endpoint

Build a server API route to handle locale updates from the client:

// server/api/locale.ts
export default defineEventHandler(async (event) => {
  const method = getMethod(event);

  if (method === 'GET') {
    const locale = getCookie(event, 'locale') || 'en';
    return { locale };
  }

  if (method === 'POST') {
    const body = await readBody<{ locale?: string }>(event);
    const next = body?.locale || 'en';
    setCookie(event, 'locale', next, {
      path: '/',
      sameSite: 'lax',
      maxAge: 60 * 60 * 24 * 365,
    });
    return { ok: true, locale: next };
  }

  return sendError(
    event,
    createError({ statusCode: 405, statusMessage: 'Method Not Allowed' })
  );
});

Since cookies can only be set on the server, this endpoint allows your client-side components to update the locale preference. When users switch languages, the API persists the change server-side for subsequent SSR requests.

Step 5: Use SSR Translations in Components

Here's a complete example showing server-side translation fetching with dynamic locale switching:

<script setup lang="ts">
import { getTranslation } from '~/utils/clocale';
import { useLocale } from '@clocale/vue';

const { setLocale: setClientLocale } = useLocale();

const { data, refresh } = await useAsyncData('home-ssr', async () => {
  const { t } = await getTranslation('test');
  return { title: t('project_overview.title') };
});

const switchLocale = async (newLocale: string) => {
  await $fetch('/api/locale', { method: 'POST', body: { locale: newLocale } });

  setClientLocale(newLocale);
  setLocale(newLocale);
  await refresh();
};
</script>

<template>
  <div>
    <LocaleSwitcher @change="switchLocale" />

    <h1>{{ data?.title }}</h1>

    <div>client demo</div>
    <ClientTranslation />
  </div>
</template>

Notes: Keep the cookie/locale logic consistent between server and client to avoid hydration mismatches.


Quick Reference

Composable/UtilityPurposeUsage Context
useTranslation('namespace')Access translationsClient & Server components
useLocale()Get/set current localeClient-side only
getTranslation('namespace')Fetch server translationsServer-side data fetching
getClocaleClient()Get server client instanceServer plugin
getLocale()Retrieve saved localeServer & Client utilities
setLocale(locale)Save locale preferenceServer & Client utilities