Nuxt で使う Langsys

どの環境でもパターンは同じです。サーバーがカタログを1回だけ取得し(書き込みキーはサーバー側に保持)、クライアントは読み取り専用キーを使ってそのシードから langsys-js-vue を初期化します。重複した取得は発生しません。翻訳そのものはブラウザー上で行われます。サーバーが送信する HTML は基準言語のままで、検索エンジンにインデックスされるのもこの言語です。ページは読み込み時に訪問者の言語へ切り替わります。

1 · サーバールートがカタログをプロキシする

Nitroルートがカタログを取得するため、書き込みキーはプライベートなランタイム設定内に保持され、ブラウザが通信するのは自分自身の /api ルートだけになります。書き込みキーはサーバー側に留まり、クライアントには読み取り専用キーが渡されます。どちらも同じカタログを参照しますが、クライアント側は最初の取得をスキップするだけです。

// 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 · SSR 中にシードし、クライアントで初期化する

useAsyncData はサーバー上でフェッチを実行し、ペイロードをページにシリアライズするため、クライアントは再取得せずにそこから初期化されます。初期化は onMounted で実行されます。SDK はブラウザー用の SDK であり、Nuxt のサーバー側はデータを提供するだけです。

<!-- 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 · 以下のどこでも使用する

ここからは通常のVue SDKと同じです。任意のコンポーネントでuseT()を使い、store.set()でロケールを切り替えます。アプリがすでにref(Pinia、useState)でロケールを管理している場合は、createLocaleStoreに移行せず、Vueバインディングのrefr ToLocaleSourceで適合させてください。

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

<template>
  <h1>{{ t('Welcome to our store', 'Home') }}</h1>
</template>
ドキュメントとラーニングセンターを検索