Tutorial

Translate Ghost Blog Posts to 8 Languages with SiteLocaleAI

Published September 14, 2026

Translate Ghost Blog Posts to 8 Languages with SiteLocaleAI

Auto‑Translate Ghost Blog Posts to 8 Languages with SiteLocaleAI

Published on 2026‑09‑14

Introduction

Ghost is a popular open‑source publishing platform, but by default it only serves content in a single language. For businesses that want to capture global traffic, manually translating each post is costly and error‑prone. SiteLocaleAI solves this by providing a drop‑in JavaScript library that:

  • Works with any framework (including Ghost’s default Handlebars templates).
  • Uses your own LLM API keys (Claude, GPT‑4o‑mini, etc.) – no third‑party data collection.
  • Localizes prices with psychological rounding per currency.
  • Generates SEO‑friendly static pages via a CLI pre‑renderer.

In this tutorial we’ll set up a Ghost blog that automatically:
1. Translates every new post into eight languages (English, Spanish, French, German, Italian, Portuguese, Japanese, and Russian).
2. Adjusts any price tags for each market.
3. Pre‑renders the translated pages so Google can index them.

By the end you’ll have a multilingual, SEO‑optimized blog without any ongoing manual effort.


Prerequisites

  • A running Ghost installation (self‑hosted or Ghost(Pro) with access to the theme files).
  • Node.js ≥ 18 for the SiteLocaleAI CLI.
  • API keys for the LLM you plan to use (e.g., OPENAI_API_KEY for GPT‑4o‑mini).
  • A domain with HTTPS (required for LLM calls from the browser).

1. Install the SiteLocaleAI library

Open a terminal in your Ghost theme directory and run:

npm install @sitelocaleai/core

This adds the core library to your theme’s node_modules. Because Ghost themes are static assets, we’ll bundle the library with esbuild:

npm install --save-dev esbuild
nbuild src/index.js --bundle --outfile=assets/sitelocaleai.js

Tip: If you already use a bundler (Webpack, Vite, etc.) you can skip the manual esbuild step and add @sitelocaleai/core to your existing pipeline.


2. Create a tiny wrapper for translation

Create a new file src/translate.js:

import { SiteLocaleAI } from '@sitelocaleai/core';

// Pull your LLM key from an environment variable (never commit it)
const LLM_API_KEY = process.env.SITELOCALEAI_API_KEY;

// Languages we want to support – ISO‑639‑1 codes
const LANGUAGES = ['en', 'es', 'fr', 'de', 'it', 'pt', 'ja', 'ru'];

// Initialize the library
const locale = new SiteLocaleAI({
  apiKey: LLM_API_KEY,
  provider: 'openai', // or 'anthropic', 'cohere', etc.
  targetLanguages: LANGUAGES,
  priceRounding: true, // enable psychological rounding
});

/**
 * Translate a raw HTML string (the post content) into all target languages.
 * Returns an object: { en: '<html>', es: '<html>', … }
 */
export async function translatePost(html) {
  const translations = await locale.translate(html);
  return translations;
}

The translate method automatically:
- Detects the source language.
- Sends the content to the LLM.
- Rewrites any $XX price patterns using locale‑specific rounding (e.g., $9.99 → $10 for US, €8.99 → €9 for EU).


3. Hook into Ghost’s post‑publish webhook

Ghost can fire a webhook after a post is published. In your Ghost admin panel go to Integrations → Webhooks → Add webhook and set:

  • Event: post.published
  • URL: https://your‑domain.com/api/translate
  • Secret: (optional, for verification)

Create a tiny Express server to receive the webhook and store translations as static HTML files:

// server.js
import express from 'express';
import bodyParser from 'body-parser';
import fs from 'fs';
import path from 'path';
import { translatePost } from './src/translate.js';

const app = express();
app.use(bodyParser.json());

app.post('/api/translate', async (req, res) => {
  const { post } = req.body; // Ghost sends the full post object
  const html = post.html;
  const slug = post.slug;

  try {
    const translations = await translatePost(html);
    // Write each translation to a language‑specific folder
    for (const [lang, content] of Object.entries(translations)) {
      const dir = path.join('public', lang);
      fs.mkdirSync(dir, { recursive: true });
      fs.writeFileSync(path.join(dir, `${slug}.html`), content);
    }
    res.status(200).send('Translations saved');
  } catch (e) {
    console.error(e);
    res.status(500).send('Translation error');
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`⚡️ Translation service listening on ${PORT}`));

Deploy this server alongside your Ghost instance (Docker, PM2, etc.). The generated HTML files will be served under https://your‑domain.com/<lang>/<slug>.html.


4. Pre‑render for SEO with the SiteLocaleAI CLI

SiteLocaleAI ships a CLI that crawls your site, fetches the translated pages, and writes static snapshots for search engines. Install it globally:

npm install -g @sitelocaleai/cli

Run the pre‑render step after each deployment:

sitelocaleai prerender \
  --base-url https://your‑domain.com \
  --languages en,es,fr,de,it,pt,ja,ru \
  --output public/seo-snapshots

The CLI will:
1. Request https://your‑domain.com/<lang>/<slug>.html for every post.
2. Save the fully rendered HTML (including meta tags) to public/seo-snapshots.
3. Optionally generate a sitemap that includes all language versions.

Add this command to your CI pipeline so every new post automatically gets an SEO‑ready snapshot.


5. Add language switcher to your Ghost theme

Edit default.hbs (or your custom theme’s header) and inject a simple switcher that points to the static files:

<nav class="lang-switcher">
  {{#each @site.languages}}
    <a href="/{{this}}/{{slug}}.html" rel="alternate" hreflang="{{this}}">{{uppercase this}}</a>
  {{/each}}
</nav>

In default.hbs also expose the list of languages via a helper:

// helpers/languages.js
module.exports = function () {
  return ['en','es','fr','de','it','pt','ja','ru'];
};

Now visitors can jump directly to the version that matches their locale, and search engines see the rel="alternate" links for proper indexing.


6. Verify SEO indexing

  1. Open Google Search ConsoleURL Inspection.
  2. Test a translated URL, e.g., https://your‑domain.com/es/my‑post.html.
  3. You should see a fully rendered page with correct <title>, <meta description>, and hreflang tags.

If you used the CLI’s sitemap generation, submit the sitemap (/sitemap.xml) to Google. Within a few days you’ll start seeing impressions for each language.


7. Internal resources

For deeper configuration options, see the official docs: SiteLocaleAI Docs. You can also explore advanced price‑localization rules and custom LLM prompts there.


8. Wrap‑up

You now have a fully automated pipeline:
- Publish a post in Ghost → webhook triggers translation.
- Store language‑specific HTML files.
- Pre‑render them for SEO.
- Serve them via a simple language switcher.

All of this runs on your own infrastructure, keeping data private and costs predictable.


Ready to go global?

Give SiteLocaleAI a spin on your own Ghost blog and watch international traffic grow. Try SiteLocaleAI today – the free Indie plan starts at just $5/month, and the Enterprise tier offers dedicated support for massive multilingual sites.