
Product
Socket Now Protects the Microsoft Edge Extension Ecosystem
Enterprise security teams can now detect malware, credential theft, suspicious network activity, and risky updates across Microsoft Edge extensions.
@sonenta/astro
Advanced tools
Official Astro integration for Sonenta i18n — build-time CDN translations, zero client JS (SSG).
Official Astro integration for Sonenta i18n.
Your translations live in Sonenta; this integration pulls the released bundles from the CDN at build time and inlines them into your static HTML. There is zero client-side JavaScript — it's pure SSG, the way Astro content sites want i18n to work.
npm install @sonenta/astro
# or: pnpm add @sonenta/astro / yarn add @sonenta/astro
v0.2 — standalone. This release does string resolution,
{var}interpolation, source-language fallback, and device-surface variants (responsive text via build-time overlays + CSS, zero JS). CLDR plurals and accessibility surfaces arrive additively in0.3.0(backed by@sonenta/i18n-core) without any breaking change to the API below — see CONTRACT.md.
// astro.config.mjs
import { defineConfig } from "astro/config";
import sonenta from "@sonenta/astro";
export default defineConfig({
// Astro's native i18n routing — the integration reads Astro.currentLocale.
i18n: { defaultLocale: "fr", locales: ["fr", "en", "es"] },
integrations: [
sonenta({
project: "your-project-uuid", // from your Sonenta dashboard
locales: ["fr", "en", "es"],
defaultLocale: "fr",
namespaces: ["common"],
}),
],
});
---
// src/pages/index.astro
import { getT, defaultLocale } from "sonenta:i18n";
const t = getT(Astro.currentLocale ?? defaultLocale);
---
<html lang={Astro.currentLocale ?? defaultLocale}>
<head><title>{t("home.title")}</title></head>
<body>
<h1>{t("home.title")}</h1>
<p>{t("home.greeting", { name: "Ada" })}</p>
</body>
</html>
That's it. astro build fetches common.json for every locale and freezes the
strings into the page. Nothing ships to the browser.
sonenta:i18n virtual moduleThe integration exposes a virtual module you can import from any .astro file
(or .ts/.js run at build time):
| Export | Description |
|---|---|
getT(locale) | Returns a t(key, vars?) bound to locale. |
locales | The locales fetched into the build. |
defaultLocale | The resolved source/default locale. |
getCatalog(locale, ns?) | Raw fetched dictionary, or null if absent. |
TypeScript types for the virtual module are injected automatically (Astro's
injectTypes), so getT is fully typed with no extra config.
t("home.cta.label").ns:key syntax: t("docs:intro").
Un-prefixed keys resolve against the first namespace (default "common").t("greeting", { name: "Ada" }) replaces {name}.
Unknown placeholders are left intact.fallbackLng (default: the
source locale). A locale whose bundle is absent (e.g. plan-limit) falls back
the same way. Still missing everywhere → the raw key is returned (i18next
parity).A surface lets one key carry different values per device — e.g. a CTA that
reads "Commencer gratuitement" on desktop and "Commencer" on mobile. Values
come from a sparse CDN overlay ({ns}.{surface}.json) layered over the base
bundle; nothing about your authoring changes except adding per-surface values
in the dashboard.
Because SSG can't know the viewport at build time, the integration fetches every surface and renders them all — a CSS media query reveals the right one. No client JavaScript.
Enable surfaces in the integration, then use the <SurfaceText> component:
// astro.config.mjs
sonenta({
project: "your-project-uuid",
locales: ["fr", "en", "es"],
surfaces: ["desktop", "mobile"], // also fetch these overlays
})
---
import SurfaceText from "@sonenta/astro/SurfaceText.astro";
const locale = Astro.currentLocale ?? "fr";
---
<a href="/signup">
<SurfaceText key="cta.start" locale={locale} />
</a>
<!-- desktop → "Commencer gratuitement", mobile → "Commencer" -->
<SurfaceText> auto-collapses: when a key has no overlay (every surface
resolves equal) it renders a single element — no wrapper spans, no <style>,
no bloat. Props: key, locale, vars?, as? (wrapper tag, default
span), class?, breakpoints?.
Prefer your own markup (e.g. Tailwind hidden md:inline)? Use the primitives:
---
import { getSurfaces, getT } from "sonenta:i18n";
const { desktop, mobile } = getSurfaces(locale, "cta.start");
const oneSurface = getT(locale).surface("cta.start", "mobile");
---
Breakpoint ladder (mirrors @sonenta/react-i18next): mobile < 640px,
tablet 640–1023px, desktop ≥ 1024px; configurable via surfaceBreakpoints
or the <SurfaceText breakpoints> prop.
Surface overlays must be published on the CDN for the key (dashboard / backend side). A key with no overlay simply renders its base value on every surface — safe by default.
Prefer an explicit top-level await? Use the runtime directly — no virtual
module, no Vite plugin:
// src/i18n.ts
import { createSonentaI18n } from "@sonenta/astro/runtime";
export const i18n = await createSonentaI18n({
project: "your-project-uuid",
locales: ["fr", "en", "es"],
defaultLocale: "fr",
});
export const getT = i18n.getT;
| Option | Type | Default | Notes |
|---|---|---|---|
project | string | — | Required. Project UUID. |
locales | string[] | — | Required. Locales to fetch + freeze. |
version | string | "main" | Released version slug / pinned hash. |
defaultLocale | string | locales[0] | Source / fallback locale. |
fallbackLng | string | string[] | [defaultLocale] | Missing-key fallback chain. |
namespaces | string[] | ["common"] | Bundle files; first is the default ns. |
surfaces | Surface[] | [] (off) | Device surfaces to fetch (desktop/mobile/tablet). |
surfaceBreakpoints | {mobile,tablet} | {640,1024} | <SurfaceText> media-query ladder. |
cdnBase | string | https://cdn.sonenta.com | CDN host (no /p). Env: SONENTA_CDN_BASE. |
apiBase | string | https://api.sonenta.dev | Reserved (forward-compat). |
fetchImpl | typeof fetch | global fetch | Custom fetch (runtime API only). |
Bundles are fetched from
{cdnBase}/p/{project}/{version}/latest/{locale}/{namespace}.json — the same
CDN layout as @sonenta/react-i18next.
$value that is a plural dict is
treated as "no string" (resolves to fallback/raw key); t.aria/t.alt and
pluralization arrive in 0.3.0 on @sonenta/i18n-core. See
CONTRACT.md.@sonenta/feedback, @sonenta/realtime, and
@sonenta/in-context are runtime/DOM SDKs — they run inside Astro client
islands (reusing the React bindings), not in static .astro output.MIT © Sonenta
FAQs
Official Astro integration for Sonenta i18n — build-time CDN translations, zero client JS (SSG).
The npm package @sonenta/astro receives a total of 1 weekly downloads. As such, @sonenta/astro popularity was classified as not popular.
We found that @sonenta/astro demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Product
Enterprise security teams can now detect malware, credential theft, suspicious network activity, and risky updates across Microsoft Edge extensions.

Research
/Security News
Socket researchers found 18 Chrome extensions and one Edge extension delivering a wallet drainer, credential theft, and other malicious payloads.

Product
Create ClickUp tasks from Socket alerts, automate ticketing with custom rules, and keep alert and task status synchronized.