use-plural-rules
Choose and render a message by CLDR plural category (Intl.PluralRules).
| Package | @vizejs/composable/use-plural-rules |
| Own the source | vize lib pull composable:use-plural-rules |
| Runtime exports | usePluralRules |
| Gzip budget | 2560 B |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/composable
Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.
import { usePluralRules } from "@vizejs/composable/use-plural-rules";
Try it
Word an unread-message count
Choose the right message for zero, one, and many items, using the locale's plural rules rather than count === 1.
What to observe: Zero shows No unread messages from the exact =0 message. Enter 1 for 1 unread message and 2 for 2 unread messages. The plural category below the message shows which rule matched.
Messages are keyed by CLDR category, with optional exact =N overrides; other is required. A function message receives the count and its locale-formatted text. Languages with more categories, such as few or many, need those keys.
Compare the initial and interacted states


Copy the example
Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.
<script setup lang="ts">
import { ref } from "vue";
import { usePluralRules } from "@vizejs/composable/use-plural-rules";
const count = ref(0);
const { message, category } = usePluralRules(
count,
{
"=0": "No unread messages",
one: (_count, formatted) => `${formatted} unread message`,
other: (_count, formatted) => `${formatted} unread messages`,
},
{ locale: "en-US" },
);
</script>
<template>
<div class="composable-example">
<p>Pick the right wording for an unread-message count.</p>
<label>
Unread messages
<input v-model.number="count" type="number" min="0" step="1" />
</label>
<output aria-live="polite">{{ message }}</output>
<p>
Plural category: <code>{{ category }}</code>
</p>
</div>
</template>
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
usePluralRules |
i18n | experimental | deterministic-fallback | caller-managed | none | web, server, worker, native, desktop, terminal | Intl, window |
useLocale |
API
usePluralRules
Choose and render a message by CLDR plural category (Intl.PluralRules). Messages are typed per category with a mandatory other, plus optional exact overrides ("=0": "No items"). Cardinal (1 item) and ordinal (1st, 2nd) rules are supported via type. The count is formatted with the same locale for interpolation. Everything is derived state: no listeners or timers, deterministic during server rendering when the locale is explicit. Invalid options surface as the platform RangeError.
function usePluralRules( count: MaybeRefOrGetter<number>, messages: MaybeRefOrGetter<PluralMessages>, options: MaybeRefOrGetter<UsePluralRulesOptions> = {}, ): PluralRulesControls
const { message } = usePluralRules(count, { "=0": "No files", one: "# file", other: "# files" }, { locale: "en" });
Types
UsePluralRulesOptions
Options for usePluralRules.
| Member | Type | Description |
|---|---|---|
locale? |
string | Intl.Locale |
Locale used for plural selection and count formatting. Pass it explicitly for hydration-stable server rendering. |
PluralRulesControls
Reactive plural selection returned by usePluralRules.
| Member | Type | Description |
|---|---|---|
locale |
ComputedRef<string> |
Canonical locale in use. |
rules |
ComputedRef<Intl.PluralRules> |
Plural rules for the current locale and options. |
category |
ComputedRef<PluralCategory> |
Category of the current count. |
message |
ComputedRef<string> |
Message for the current count with {count} / # interpolated. |
select |
(count: number) => PluralCategory |
Plural category of any count. |
format |
(count: number) => string |
Message for any count. |