Skip to content
Tier

Fill strings

Free · MIT

The text's first letter in upper case, as the locale writes it: "Environment" from "environment", "İstanbul" from "istanbul" in Turkish. The first grapheme, so a letter with combining marks stays whole. For headings and the start of a sentence.

Markdown
Version 5.2.0· other versions

This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).

Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1, 2.6.2, 2.7.0, 2.8.0 and 2.9.0: the page came later, or had another name then.

Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.

Preview

Loading the preview

Install

With the Candor CLI
Open the starter in StackBlitz

Opens the free starter app in StackBlitz, in your browser, on stackblitz.com. Fill strings isn’t added for you: run npx candor-ui add fill-strings in its terminal. The starter’s agent needs an Anthropic API key to chat; without one it shows the components only.

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/fill-strings

Brings in: tokens

Usage

TSX · The example above
"use client"

import { englishStrings } from "@/lib/candor/fill-strings"

// A helper that names a tool outside any component (on the server, or in an adapter's toolTitle) reads its table
// with englishStrings; in a component, pass useStrings' translator instead, so the app's words apply.
const toolStrings = {
  toolStopRun: "Stop {run}",
  theRun: "the run",
  steps: { one: "{count} step", other: "{count} steps" },
}

const t = englishStrings(toolStrings)

export default function Example() {
  return (
    <ul className="flex flex-col gap-1 text-sm">
      <li>{t("toolStopRun", { run: "run-7" })}</li>
      <li>{t("toolStopRun", { run: t("theRun") })}</li>
      <li>{t("steps", { count: 1 })}</li>
      <li>{t("steps", { count: 12 })}</li>
    </ul>
  )
}

Functions

startOf(text: string, locale?: string)
fill(template: string, vars: Vars | undefined, number: (n: number) => string = String, nouns?: NounTable, locale?: string)

Fill {name} placeholders: from vars first, then from the app's nouns ({environment} in the form the message's count picks, else its one form). {Environment} reads vars.Environment, else startOf(vars.environment), so a value given for the noun also starts a sentence; with neither, a noun named Environment, else the noun's start, else startOf it. A placeholder with none of these stays as written. Numbers go through number, the locale's number format in a component.

pick(message: Phrase, count: number | undefined, rules: Intl.PluralRules, nouns?: NounTable, vars?: Vars)

The form of a message for count: plural forms fall back to other; a SelectPhrase takes its case from vars[select], else from the gender of the noun called select, else other.

singularNouns(nouns: NounTable)

Each noun in its singular (or only) form.

englishStrings(table: T, options?: { /** The app's nouns, over Candor's own (`nounDefaults`), for `{environment}` and the like. */ nouns?: Partial<NounTable> | undefined; })

A translate function over a table of English defaults, for code that runs outside a component: on the server, or a helper called without the component's useStrings. It fills placeholders, the app's nouns among them, and picks plural and select forms as useStrings does with no overrides, in English. This module has no "use client", so a server module can import it.

const t = englishStrings(dataTableStrings)
t("selected", { count: 3 }) // "3 selected"
englishStrings(table, { nouns: { environment: "workspace" } })
withNouns(base: NounTable, nouns: Partial<NounTable> | undefined)

nouns over base, noun by noun; a noun left out (or undefined) keeps the one below. An environment with an other form and no environments beside it gives environments that form, so {environments} follows the app's plural; an environments the app sets wins.

Values

nounDefaults

Candor's own nouns, which the app's replace one by one.

{ environment: { one: string; other: string; }; environments: string; account: { one: string; other: string; }; product: string; }

Types

PluralPhrase
A message's plural forms, chosen by its `count`; `other` is the one every language has.
{ other: string } & Partial<Record<Intl.LDMLPluralRule, string>>
SelectPhrase
A message's forms chosen by a word: `vars[select]` when it names a case, else the `gender` of the noun called `select`, else `other`. Each case is a string or plural forms: ``` { select: "environment", cases: { feminine: "Nouvelle {environment}", other: "Nouvel {environment}" } } ```
{ select: string; cases: { other: string | PluralPhrase } & Record<string, string | PluralPhrase> }
Phrase
One string, its plural forms by `count`, or its forms by a word; `{name}` placeholders are filled in.
string | PluralPhrase | SelectPhrase
Noun
One of the app's nouns: a word ("workspace"), or its plural forms (`{ one: "workspace", other: "workspaces" }`), with a `gender` for messages that select on it and a `start` for the start of a sentence where upper-casing the first letter isn't how the language does it.
string | (PluralPhrase & { gender?: string | undefined; start?: string | PluralPhrase | undefined })
NounTable
The app's nouns by name; a message names one as `{environment}`, or `{Environment}` at the start of a sentence.
Record<string, Noun>
Nouns
Each noun in its singular (or only) form, for the app's own code: what `useNouns()` gives.
{ /** One place agents act in: "environment", or the app's "workspace", "project". */ environment: string; /** More than one of them: the app's own word, else the `other` form of the app's `environment`. */ environments: string; /** The paying customer that owns the environments. */ account: string; /** The product's own name, for labels like "In the app" and "What the app will read". */ product: string; } & Record<string, string>