@bablic-io/sdk-astro

中文文档
1.4.0发布于 2026/11/06MITTypeScriptESM + CJS近 30 天下载 1710

Translate your Astro site with Bablic: server-rendered, SEO-indexable pages in every language.

原始使用文档
文档目录16 节
  1. Requirements
  2. Install
  3. Set up
  4. Prerendered pages: moxieRoute
  5. On-demand pages: moxieMiddleware
  6. Check it works
  7. When you change your languages or URLs
  8. How it works
  9. Clearing the cache
  10. Options
  11. SEO
  12. hreflang on your original pages
  13. Caching and speed
  14. Hosting rules
  15. Links
  16. License

@bablic-io/sdk-astro

Server-side rendering for Bablic on Astro. Your translated pages are rendered on the server, so visitors and search engines receive finished, indexable HTML in their language. In the browser, Bablic keeps translating content that appears later. Built for Astro 6 on @astrojs/vercel; works with any Node adapter.

Next.js site? Use @bablic-io/sdk-vercel instead. This package is for Astro only, on Vercel or any Node host.

You need a Bablic account and project. New to Bablic? Sign up.

Requirements

  • A Bablic project with the Bablic script tag on every page, in the HTML the server sends.
  • A Bablic Pro plan or a free trial. On other plans the SDK serves the original page unchanged (x-moxie: skipped, x-moxie-reason: please subscribe to pro tier) and Bablic keeps translating in the browser. After a plan change, allow about 15 minutes. Plans: Bablic dashboard.
  • Translated URLs set in your Bablic dashboard as language folders (for example example.com/fr-fr/…), or language subdomains on sites rendered on demand. Cookie and query-parameter setups have no separate URL per language, so they keep translating in the browser only: the SDK serves their pages unchanged (x-moxie: skipped), even with a custom resolve.
  • The dashboard folders must be exactly the paths you want: a folder /fr-fr/ serves /fr-fr/…, never /fr/….
  • Astro 6 with a Node adapter (@astrojs/vercel 10 or later on Vercel).
  • Node.js 22.

Install

npm install @bablic-io/sdk-astro

Set up

  1. Keep the Bablic script tag in your base layout. is:inline keeps Astro from bundling it, so it reaches the server HTML.

    <script is:inline src="https://edge.bablic.com/moxie.min.js" data-oljs="P0000"></script>
    

    Copy the exact tag from your Bablic dashboard. P0000 stands for your project key. Don't add the tag from client-side code or a tag manager.

    Add data-glweb-opacity="1" to the tag. Without it, the Bablic script hides each original-language page (near-zero opacity) until its settings arrive, which costs first paint and Lighthouse score. Translated pages served by the SDK never hide; the SDK sets this attribute on them. The tag can also load with defer. Keep the P at the start of data-oljs.

  2. Add a route or middleware with your project key, depending on how your pages render (below). The SDK reads your translated URLs from your Bablic dashboard settings, so you don't list languages or URLs in code.

  3. Vercel Preview deployments with Deployment Protection: in your Vercel project, open Settings → Deployment Protection, turn on Protection Bypass for Automation, then redeploy. Without it, the SDK's fetch of each original page is sent to the Vercel login and no page is translated. The SDK sends the secret Vercel provides (VERCEL_AUTOMATION_BYPASS_SECRET) on its own.

  4. Preview domains: Bablic only answers for domains your project allows, and link rules are set per domain. Add the preview's domain as your project's staging domain in the dashboard. Use the branch's stable domain (<project>-git-<branch>-<team>.vercel.app) or a custom preview domain, since each deployment's own URL changes.

Prerendered pages: moxieRoute

@astrojs/vercel runs middleware for prerendered pages at build time only, so add an on-demand catch-all route. Your prerendered pages take precedence; only URLs without a page reach it.

// src/pages/[...path].ts
import { moxieRoute } from '@bablic-io/sdk-astro';

export const prerender = false;
export const GET = moxieRoute({ project: 'P0000' });
export const HEAD = GET;

Translated URLs are served translated. Any other URL that reaches the route gets 404, as it would without it, with x-moxie: none and an x-moxie-reason saying why.

  • Remove prerendered pages under your language folders. A page such as src/pages/fr/index.astro is served instead of the translation, so the SDK never sees /fr/. Keep one copy of each page, in your original language.

  • Use language folders with this setup. A language subdomain shares its paths with your prerendered pages, so the route never sees those requests.

  • Already have a catch-all route at the root? Call moxieRoute from it first and fall back to your own handling when it returns 404:

    // src/pages/[...path].ts
    import type { APIRoute } from 'astro';
    import { moxieRoute } from '@bablic-io/sdk-astro';
    
    export const prerender = false;
    const bablic = moxieRoute({ project: 'P0000' });
    
    export const GET: APIRoute = async (context) => {
      const translated = await bablic(context);
      if (translated.status !== 404 || translated.headers.get('x-moxie') !== 'none')
        return translated;
      return yourHandler(context); // your existing catch-all logic
    };
    export const HEAD = GET;
    
  • Edge middleware keeps working. With middlewareMode: 'edge', your middleware runs before the route for translated URLs, and again on the SDK's fetch of the original page, so your redirects and status codes (410, 404) apply to translated URLs too. Only moxieMiddleware needs the Node.js runtime.

On-demand pages: moxieMiddleware

// src/middleware.ts
import { sequence } from 'astro:middleware';
import { moxieMiddleware } from '@bablic-io/sdk-astro';

export const onRequest = sequence(moxieMiddleware({ project: 'P0000' }) /*, your middleware */);

It skips prerendered pages and supports language folders and subdomains. It runs Bablic in your middleware, so it needs the Node.js runtime: don't combine it with middlewareMode: 'edge'. For edge middleware, use moxieRoute.

Check it works

curl -sI https://<your-translated-url>        # x-moxie: MISS, then HIT on a second request

On a protected Vercel Preview, add the bypass secret: curl -sI -H "x-vercel-protection-bypass: <secret>" https://<your-translated-url>.

View the page source: <html … data-moxie-mode="ssr"> and one <script type="application/json" id="moxie-manifest">.

While your project is in Staging, add ?bablic_preview=1 to the URL. Staging responses are never cached.

Every response the SDK handles carries x-moxie; all but HIT, STALE, MISS and bypass also carry x-moxie-reason:

x-moxieMeaning
HITServed from the cache.
STALEServed from the cache while a newer translation is prepared in the background.
MISSTranslated for this request, then cached.
noneNot a translated URL (404). The reason lists the folders the SDK sees and how old its config is, or why the config couldn't be read.
redirectThe original page redirects; Location follows your link rules. The reason shows both URLs.
passThe original page isn't a 200 HTML page (404, 410, JSON …); served as is.
skippedNot translated on the server: your plan doesn't include it, or the project doesn't translate this page (not live, no script tag, or translation off).
failedTranslation failed; the original page was served under the failure rule.
bypassRequest from the Bablic editor; original page, uncached.

When you change your languages or URLs

The SDK reads your project settings from Bablic and caches them for 5 minutes; Bablic's own cache adds up to 10. A change in the dashboard reaches the SDK within about 15 minutes, with no code change or redeploy. x-moxie-reason on a 404 shows the folders the SDK currently sees. To drop the SDK's copy sooner, POST {"config": true} to the revalidate route (Clearing the cache).

How it works

  1. A request for a translated URL reaches the route or middleware. A cached translation is served at once (x-moxie: HIT).
  2. On a miss, the SDK fetches the original page from the same deployment (for a language folder, the same path without the folder; the CDN serves prerendered pages) and translates it on the server with your project's translations.
  3. The translated page is cached and served (x-moxie: MISS).
  4. In the browser, the Bablic script translates content added later, including text that islands (client:*) render, without redoing the server's work.

Links and redirects follow your project's link rules in Bablic, for the domain the request is on. The SDK never invents a URL: with no rules, links stay as they are. The translated page's <html lang> is the language's code from your dashboard (unless your project sets its own HTML language), so browsers don't offer to translate it again. Translated URLs keep the original path under the language folder (/fr-fr/pricing); translated slugs aren't supported yet.

If translation fails or times out, nothing partial is served or cached: search engines get 503, visitors get the original page with noindex.

Clearing the cache

Pages refresh on their own after pageTtl (1 hour). To clear them sooner, add a signed purge route:

// src/pages/api/bablic/revalidate.ts
import type { APIRoute } from 'astro';
import { createRevalidateHandler, runtimeCache } from '@bablic-io/sdk-astro';

export const prerender = false;
const revalidate = createRevalidateHandler({
  secret: import.meta.env.MOXIE_REVALIDATE_SECRET,
  cache: runtimeCache(),
});
export const POST: APIRoute = ({ request }) => revalidate(request);

POST {"tkey":"<translation key>"} (add "url_hashes": [...] for single pages), or {"config": true} to re-read your project settings, with the header x-moxie-signature: sha256=<hex HMAC-SHA256 of the body, keyed with the secret>.

Options

project, pageTtl, staleTtl, timeoutMs, backgroundTimeoutMs, cache, editorCookie, onResult, onUnsupported, resolve, moxie, host, fetch, plus buildId and sourceHeaders. Defaults are described in the @bablic-io/sdk-vercel README.

SEO

What the SDK does on every translated page:

  • <html lang> and the content-language header carry the language's code from your dashboard, as a BCP-47 tag (fr-FR).
  • A canonical, og:url or twitter:url that names the original page is pointed at the translated URL, so each language is its own page, not a duplicate. A canonical that names a different page is left alone.
  • Titles, descriptions, Open Graph and Twitter tags, JSON-LD and image alt text are translated with the rest of the page.
  • JSON-LD (structured data) points at the translated page: url, item, mainEntityOfPage and @id values that name a page of your site get the translated URL, and inLanguage the page's language. Site-wide nodes, whose @id is your home page plus a # name (#organization, #website), stay the same on every page. Files and other sites' URLs are left alone.
  • hreflang values are valid BCP-47 tags. A language code with a private-use region, such as Spanish (Universal) ES-XM, is written es, in hreflang and in og:locale, since search engines ignore a region that doesn't exist.

What your project and site decide:

  • hreflang. Bablic adds alternates for every language plus x-default to translated pages when hreflang is enabled for your project (ask Bablic support), and only on pages with no hreflang tags of their own. Your original-language pages need the same set, and prerendered pages never pass through the SDK, so add the build step below. Don't print hreflang tags yourself: a partial set (only en and x-default) stops Bablic from adding the rest.

hreflang on your original pages

bablicHreflang writes the hreflang set into each prerendered page when the site builds, from your project's languages in the Bablic dashboard. Translated pages still get theirs from Bablic, with the same links.

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel';
import { bablicHreflang } from '@bablic-io/sdk-astro';

export default defineConfig({
  site: 'https://<your-domain>', // the links' origin
  adapter: vercel(),
  integrations: [bablicHreflang({ project: 'P0000' })],
});
  • Rebuild after adding or removing a language in the dashboard. The build log says how many pages got links.
  • It follows your trailingSlash setting (/fr or /fr/ for a language home page).
  • Pages are left alone when they have no Bablic script tag, have their own hreflang tags, are noindex, have a canonical naming another page, or sit under a language folder. 404 and 500 pages too.
  • If the project config can't be read, the build goes on without links and logs a warning.
  • Sitemap. The SDK doesn't change your sitemap. Add each language's URLs (your original paths under each language folder) with your sitemap tool.
  • Images. og:image and other images stay as your site sets them, unless your project translates images.
  • Links. Links follow your project's link rules for the domain the page is served on. A domain with no rules keeps the original links, so set rules for your production domain and for any staging or preview domain.

Caching and speed

  • Fresh for pageTtl (1 hour): served from the cache (x-moxie: HIT).
  • Stale after that, or after a new deploy: still served at once (x-moxie: STALE), and refreshed in the background. After a deploy, a page whose original HTML is unchanged keeps its translation (one fetch of the original, no new translation). An expired page is always translated again, so edits in Bablic show up within pageTtl.
  • Kept for staleTtl (7 days) after it expires; only a page nobody visits that long is translated while a visitor waits.
  • Slow first translation: if a page's first translation runs past timeoutMs, the visitor gets the failure rule and the SDK finishes it in the background (backgroundTimeoutMs, 15 s), so the next visitor gets a HIT.
  • Warming: request each translated URL once after a deploy (without ?bablic_preview=1, which is never cached) to fill the cache before visitors arrive.
  • Server-Timing on every response shows where the time went, for example mx;desc="MISS", cache;dur=3, source;dur=42, translate;dur=870, total;dur=918. Browser dev tools and Lighthouse show it.

Hosting rules

  • Turn off ISR for your translated URLs. ISR ignores cookies, so it would cache Staging and editor responses.
  • A CDN in front of your site must not cache HTML for requests carrying the opemoxieoverride cookie.
  • Keep the Bablic script tag on every page, including the original-language pages.

License

MIT

版本与发布记录

@bablic-io/sdk-astro 共发布 13 个版本,首次发布于 2026/10/14;过去 12 个月发布了 13 个版本。

版本发布日期距今
1.4.0latest2026/11/064 天前
1.3.02026/11/055 天前
1.2.02026/10/2912 天前
1.1.02026/10/2120 天前
1.0.02026/10/2120 天前
0.2.02026/10/1724 天前

关于 @bablic-io/sdk-astro 的常见问题

@bablic-io/sdk-astro 是什么?

Translate your Astro site with Bablic: server-rendered, SEO-indexable pages in every language.

如何安装 @bablic-io/sdk-astro?

在项目目录运行 npm install @bablic-io/sdk-astro,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:astro(>=5.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@bablic-io/sdk-astro 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@bablic-io/sdk-astro 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@bablic-io/sdk-astro 可以商用吗?

@bablic-io/sdk-astro 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@bablic-io/sdk-astro 的下载量有多少?

根据 npm 官方下载统计,@bablic-io/sdk-astro 在 2026/10/08 – 2026/11/06 这 30 天内被下载 1,710 次,日均约 57 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bablic-io/sdk-astro 还在维护吗?

最新版本 1.4.0 发布于 2026/11/06(4 天前);至今共发布 13 个版本,其中过去 12 个月发布了 13 个;首次发布于 2026/10/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。