# Translations

**Turns the texts of a `translations` prop into the functions a state machine wants.**

Many translations depend on state: the name of a file, the value of a number, the item a screen reader announces. A machine wants a function for those, but Fluid has no callbacks. A template writes a text with `%placeholders%` instead, a client script passes the function, and `resolveTranslations()` makes both the same function.

## Usage

In a template, write the text. The `%` form survives Fluid, a curly-brace placeholder would be read as a variable:

```html
<ui:numberInput.root translations="{valueText: '%value% pieces'}"> ... </ui:numberInput.root>
```

In a client script, pass the function itself:

```typescript
import { mountAll } from 'fluid-primitives';
import { NumberInput } from 'fluid-primitives/numberInput';

mountAll('primitives:numberInput', ({ props }) =>
    new NumberInput({
        ...props,
        translations: { ...props.translations, valueText: value => `${value} pieces` },
    }).init()
);
```

## Build a component with translations

Pass the `translations` prop and the keys that are functions to `resolveTranslations()`. Each key lists what fills its placeholders from the details the machine calls it with. Keys that are not listed stay texts, anything else is left out so the machine keeps its default.

```typescript
import { resolveTranslations } from 'fluid-primitives';

const translations = resolveTranslations(props.translations, {
    valueText: (value: string) => ({ value }),
});
```

Use `fillPlaceholders()` where you build the text yourself. A placeholder without a value stays as written.

## API Reference

Turns the texts of a `translations` prop into what a machine takes. Fluid can't author a callback, so a template writes a text with `%placeholders%` for each translation that a machine wants as a function, while a client script passes the function itself. Both end up as the same function here.

Every key of `functions` becomes a function: a text is filled with the placeholder values `functions` derives from the details the machine calls it with, a function is kept as it is. Every other key stays a text. Anything else, such as `false`, is left out, so the machine falls back to its own default.

```typescript
resolveTranslations<T = Record<string, unknown>>(translations: Record<string, unknown> | undefined, functions?: Record<string, (details: any) => PlaceholderValues>): T | undefined
```

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `translations` | `Record<string, unknown> \| undefined` | Yes | `-` | The `translations` prop as it arrives, or `undefined`. |
| `functions` | `Record<string, (details: any) => PlaceholderValues>` | No | `{}` | The keys that are functions in the machine, each with what fills its placeholders. |

**Returns** `T | undefined`. The translations for the machine, or `undefined` without any.

```typescript
resolveTranslations(
    { valueText: '%value% items', incrementLabel: 'More' },
    { valueText: (value: string) => ({ value }) }
);
// { valueText: value => `${value} items`, incrementLabel: 'More' }
```

Replaces every `%name%` in `text` with the value of `name`. A placeholder without a value is left as written, so a typo stays visible.

```typescript
fillPlaceholders(text: string, values: PlaceholderValues): string
```

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `text` | `string` | Yes | `-` | The text with its placeholders. |
| `values` | `PlaceholderValues` | Yes | `-` | The values by placeholder name. |

```typescript
fillPlaceholders('Preview of %fileName%', { fileName: 'a.png' }); // 'Preview of a.png'
```

A translation as a template author or a client script writes it: a text with `%placeholders%` for what is only known when the text is shown, or a function that builds the text from the same details.

```typescript
type TranslationText<TDetails> = string | ((details: TDetails) => string)
```

What a `%placeholder%` of a translation can be filled with.

```typescript
type PlaceholderValues = Record<string, string | number | null | undefined>
```
