Back to all docs

BeMyWords with Vue

Integration guide for Vue 3 applications using vue-i18n.

Shape of the integration:

  1. At build time, fetch translations from BeMyWords into JSON resource files.
  2. Configure vue-i18n to load them at app init.
  3. Use $t() / useI18n() in components.

Prerequisites

  • A Vue 3 project (Vite-based assumed).
  • vue-i18n installed: npm install vue-i18n@latest.
  • A BeMyWords workspace, project, namespace, API key.

1. Environment variables

.env.local:

BEMYWORDS_BASE_URL=https://www.bemywords.no
BEMYWORDS_PROJECT_ID=<your-project-uuid>
BEMYWORDS_API_TOKEN=<your-api-token>
BEMYWORDS_NAMESPACE=app

Do not prefix BEMYWORDS_API_TOKEN with VITE_ — it must stay server-side.

2. Fetch script

scripts/fetch-translations.mjs:

import { writeFileSync, mkdirSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = dirname(fileURLToPath(import.meta.url));
const OUTPUT_DIR = join(__dirname, "..", "src", "locales");

const BASE_URL = process.env.BEMYWORDS_BASE_URL || "https://www.bemywords.no";
const PROJECT_ID = process.env.BEMYWORDS_PROJECT_ID;
const API_TOKEN = process.env.BEMYWORDS_API_TOKEN;
const NAMESPACE = process.env.BEMYWORDS_NAMESPACE || "app";

const LANGUAGES = ["en", "nb"];

async function fetchLanguage(lang) {
  const url = `${BASE_URL}/api/${PROJECT_ID}/latest/${lang}/${NAMESPACE}`;
  const res = await fetch(url, { headers: { Authorization: `Token token=${API_TOKEN}` } });
  if (!res.ok) throw new Error(`${lang}: HTTP ${res.status}`);
  return res.json();
}

async function main() {
  mkdirSync(OUTPUT_DIR, { recursive: true });
  if (!PROJECT_ID || !API_TOKEN) {
    console.warn("BEMYWORDS_* env vars not set.");
    return;
  }
  for (const lang of LANGUAGES) {
    const data = await fetchLanguage(lang);
    writeFileSync(join(OUTPUT_DIR, `${lang}.json`), JSON.stringify(data, null, 2) + "\n");
  }
}

main().catch((e) => { console.error(e); process.exit(1); });

3. Configure vue-i18n

src/i18n.ts:

import { createI18n } from "vue-i18n";
import en from "./locales/en.json";
import nb from "./locales/nb.json";

export default createI18n({
  legacy: false, // Composition API mode
  locale: "en",
  fallbackLocale: "en",
  messages: { en, nb },
});

src/main.ts:

import { createApp } from "vue";
import App from "./App.vue";
import i18n from "./i18n";

createApp(App).use(i18n).mount("#app");

4. Use in components

Composition API:

<script setup>
import { useI18n } from "vue-i18n";
const { t } = useI18n();
</script>

<template>
  <h1>{{ t("home.hero.title") }}</h1>
  <p>{{ t("home.hero.subtitle") }}</p>
</template>

Options API / templates-only:

<template>
  <h1>{{ $t("home.hero.title") }}</h1>
</template>

BeMyWords returns flat dot-keys. vue-i18n reads dot notation natively — no conversion needed.

5. Hook into build

package.json:

{
  "scripts": {
    "predev": "node scripts/fetch-translations.mjs",
    "prebuild": "node scripts/fetch-translations.mjs",
    "dev": "vite",
    "build": "vite build"
  }
}

Pluralization and interpolation

vue-i18n uses pipe-separated plurals and {name} interpolation:

{
  "apples": "no apples | 1 apple | {count} apples",
  "greeting": "Hello, {name}!"
}

Store these strings verbatim in BeMyWords. Enable placeholder validation in project settings.


API reference

See Astro integration guide.

Status

This guide is a best-effort draft — not yet verified in a production Vue deployment. Please test before relying on it and report corrections.