> ## Documentation Index
> Fetch the complete documentation index at: https://docs.astilba.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Install @astilba/core and use the vendored CLDR plural rules and MT masking utilities.

The fastest path into astilba: install the published package, `@astilba/core`, and use its
two most directly useful capabilities — the **vendored CLDR plural rules** and the
**MT masking utilities**. These are the parts of the engine that work standalone, with no
file-format adapter.

## Prerequisites

* **Node.js >= 22.14**
* A package manager that resolves the `@astilba/core` package from npm (`pnpm`, `npm`, or
  `yarn`).

<Note>
  astilba is **pre-1.0**. These examples reflect the API as it ships today; the public API
  may change before 1.0.
</Note>

## Install

```bash theme={null}
pnpm add @astilba/core
```

`@astilba/core` ships two entry points:

* `@astilba/core` — the full API: the canonical model, `AstilbaError`, the harness contracts,
  and masking utilities.
* `@astilba/core/cldr` — just the vendored CLDR plural rules.

## Select a plural category

The CLDR table is **vendored**, not read from `Intl.PluralRules`, so it is identical on
Node, Bun, Deno, browsers, and Workers:

```ts theme={null}
import { selectCategory, categoriesFor } from "@astilba/core";

// English cardinal: two categories.
categoriesFor("en", "cardinal");
// → ["one", "other"]

// Which category does a count select?
selectCategory("en", 1, false); // → "one"
selectCategory("en", 2, false); // → "other"

// Russian has four cardinal categories.
selectCategory("ru", 21, false); // → "one"
selectCategory("ru", 3, false); //  → "few"
selectCategory("ru", 5, false); //  → "many"
```

Languages not in the vendored table fall back to `other`-only. You can check ahead of time:

```ts theme={null}
import { isSupportedLanguage, SUPPORTED_LANGUAGES } from "@astilba/core";

isSupportedLanguage("en"); // → true
isSupportedLanguage("xh"); // → false (falls back to "other"-only)

SUPPORTED_LANGUAGES; // → ["ar", "de", "en", "fr", "ja", "ko", "pl", "ru", "zh"]
```

See [CLDR plural rules](/concepts/plural-rules) for why the table is vendored.

## Mask a value before machine translation

Before you send a string to a machine-translation engine, mask everything that must **not**
be translated — interpolation variables, formatter keywords, `$t()` nesting refs, and markup.
`maskTokens` replaces each non-text token with an opaque sentinel; `unmask` restores it.

`maskTokens` works on the canonical token view. If you have a raw i18next value string and
want to tokenize it, you currently need an adapter's tokenizer; from pure core you can mask a
hand-built token array directly:

```ts theme={null}
import { maskTokens, unmask } from "@astilba/core";

const tokens = [
  { type: "text", raw: "Hello, " },
  { type: "interpolation", raw: "{{name}}", variable: "name" },
  { type: "text", raw: "!" },
] as const;

const { masked, parts } = maskTokens(tokens);
// masked → "Hello, \uE0000\uE001!"   (the variable is a private-use-area sentinel)

const back = unmask(translated, parts); // restore after MT returns
```

After translation comes back, validate the placeholders survived unmodified — see
[MT masking](/concepts/masking).

## Where to go next

* To round-trip **i18next resource files** (parse → export → render), you need the i18next-v4
  adapter, which lives in the repo but is not yet published. See
  [the adapter reference](/reference/adapter-i18next).
* For the full `@astilba/core` export surface, see the [core API reference](/reference/core-api).

<Tip>
  Need help, or found something that looks wrong? Open an issue on
  [GitHub](https://github.com/astilbahq/astilba/issues).
</Tip>
