Langsys with Nuxt

The pattern is the same everywhere: the server fetches the catalog once (write key stays server-side), and the client initializes langsys-js-vue from that seed with a read-only key — no duplicate fetch. The translating itself happens in the browser: the HTML the server sends is in the base language, which is also what search engines index, and the page switches to the visitor's language as it loads.

1 · A server route proxies the catalog

A Nitro route fetches the catalog so the write key stays in private runtime config — the browser only ever talks to your own /api route. The write key stays on the server; the client gets a read-only key. Both halves see the same catalog — the client just skips the initial fetch.

// server/api/langsys.get.ts
export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig();
  const locale = (getQuery(event).locale as string) ?? 'en-US';
  const res = await $fetch<{ data: unknown }>(
    `https://api.langsys.dev/api/projects/${config.langsysProjectId}/translations`,
    { query: { locale }, headers: { 'x-Authorization': config.langsysApiKey } }
  );
  return { locale, translations: res.data };
});

2 · Seed during SSR, initialize on the client

useAsyncData runs the fetch on the server and serializes the payload into the page, so the client initializes from it without refetching. Init runs in onMounted — the SDK is a browser SDK; the server half of Nuxt only supplies the data.

<!-- app.vue -->
<script setup lang="ts">
import { LangsysApp, createLocaleStore } from 'langsys-js-vue';
import type { iCategories } from 'langsys-js-vue';

const { data } = await useAsyncData('langsys', () =>
  $fetch('/api/langsys', { query: { locale: 'en-US' } })
);

const store = createLocaleStore(data.value!.locale);

onMounted(() => {
  LangsysApp.init({
    projectid: useRuntimeConfig().public.langsysProjectId,
    key: useRuntimeConfig().public.langsysApiKey, // read-only
    UserLocaleStore: store,
    initialTranslations: data.value!.translations as iCategories,
    initialTranslationsLocale: data.value!.locale,
    ssrTokenStrategy: 'client',
  });
});
</script>

<template>
  <NuxtPage />
</template>

3 · Use it anywhere below

From here it is the plain Vue SDK: useT() in any component, store.set() to switch locale. If your app already owns the locale in a ref (Pinia, useState), adapt it with the Vue binding's refToLocaleSource instead of migrating to createLocaleStore.

<script setup>
import { useT } from 'langsys-js-vue';
const t = useT();
</script>

<template>
  <h1>{{ t('Welcome to our store', 'Home') }}</h1>
</template>
Search the docs & Learning Center