Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Interpolation & Plurals

Parameterized Strings

Use {param} placeholders in your strings and pass values as a second argument:

import { Text } from "perry/ui";

Text("Hello, {name}!", { name: user.name })
Text("Total: {price}", { price: order.total })

Translation files use the same {param} syntax:

// locales/en.json
{
  "Hello, {name}!": "Hello, {name}!",
  "Total: {price}": "Total: {price}"
}

// locales/de.json
{
  "Hello, {name}!": "Hallo, {name}!",
  "Total: {price}": "Gesamt: {price}"
}

Parameters are substituted at runtime after the locale-appropriate template is selected. The substitution handles any value type (numbers, strings, dates) by converting to string.

Compile-Time Validation

Perry validates parameters across all locales during compilation:

ConditionSeverity
{param} in translation but not provided in codeError
Param in code but {param} not in translationError
Parameter set differs between locales for same keyError

Plural Rules

Plural forms use dot-suffix keys based on CLDR plural categories: .zero, .one, .two, .few, .many, .other.

Locale Files

// locales/en.json
{
  "You have {count} items.one": "You have {count} item.",
  "You have {count} items.other": "You have {count} items."
}

// locales/de.json
{
  "You have {count} items.one": "Du hast {count} Artikel.",
  "You have {count} items.other": "Du hast {count} Artikel."
}

// locales/pl.json (Polish: one, few, many)
{
  "You have {count} items.one": "Masz {count} element.",
  "You have {count} items.few": "Masz {count} elementy.",
  "You have {count} items.many": "Masz {count} elementow.",
  "You have {count} items.other": "Masz {count} elementu."
}

Usage in Code

Reference the base key without any suffix. Perry detects the plural variants automatically:

Text("You have {count} items", { count: cart.items.length })

Perry determines which plural form to use based on the count parameter value and the current locale’s CLDR rules.

Supported Locales

Perry includes hand-rolled CLDR plural rules for 30+ locales:

PatternLocales
one/otherEnglish, German, Dutch, Swedish, Danish, Norwegian, Finnish, Estonian, Hungarian, Turkish, Greek, Hebrew, Italian, Spanish, Portuguese, Catalan, Bulgarian, Hindi, Bengali, Swahili, …
one (0-1) / otherFrench
no distinctionJapanese, Chinese, Korean, Vietnamese, Thai, Indonesian, Malay
one/few/manyRussian, Ukrainian, Serbian, Croatian, Bosnian, Polish
one/few/otherCzech, Slovak
zero/one/two/few/many/otherArabic
one/few/otherRomanian, Lithuanian
zero/one/otherLatvian

Compile-Time Validation

ConditionSeverity
.other form missing for any localeError
Required CLDR category missing (e.g., .few for Polish)Error
Extra category locale doesn’t use (e.g., .few for English)Warning

Explicit API for Non-UI Strings

For strings outside UI components (API responses, notifications, etc.), use t():

import { t } from "perry/i18n";

const message = t("Your order has been shipped.");
const welcome = t("Welcome back, {name}!", { name: user.name });

This uses the same key lookup, validation, and interpolation as UI strings.