formatSallaPlural
Picks the right plural form out of a Salla translation such as '{1} one item|[2,*] :count items' and fills in the number.
import { formatSallaPlural } from '@salla.sa/twilight-theme-engine/utils';In plain words
Some texts change with a number: "1 time", "2 times", "11 times", and Arabic has more forms than English. Salla keeps every form in one translation string, in the Laravel format: {1} One time|{2} Two times|[3,10] :count times|[11,*] :count Time. The translate function t does not understand that format and returns the whole string.
formatSallaPlural(t('pages.products.sold_times'), 5) picks the part that matches 5, puts 5 where :count is, and returns plain text: "5 times".
Signature
function formatSallaPlural(template: unknown, count: number): string
Try it live
- What i18next returns
{1} <span>One time</span>|{2} <span>Two times</span>|[3,10] <span>:count</span> times|[11,*] <span>:count</span> Time- formatSallaPlural(…, 3)
- 3 times
import { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';
import { formatSallaPlural } from '@salla.sa/twilight-theme-engine/utils';
export function Count() {
const { t } = useTranslation();
return <span>{formatSallaPlural(t('pages.products.sold_times'), 3)}</span>;
}
Example
import { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';
import { formatSallaPlural } from '@salla.sa/twilight-theme-engine/utils';
export function ReviewCount({ count }: { count: number }) {
const { t } = useTranslation();
return <span className="review-count">{formatSallaPlural(t('pages.rating.reviews'), count)}</span>;
}
How it behaves
The template is split on
|and the parts are tried in order.{n}matches exactlyn;[a,b]matchesa ≤ count ≤ b;*leaves that end open. The first match wins.Parts without a
{…}or[…]prefix are the Laravelsingular|pluralfallback, used only when no prefixed part matched: the first whencount === 1, the second otherwise.In the chosen text,
:countand{{count}}become the number, every HTML tag is removed, and runs of whitespace become one space.A template without
|gets the same substitutions and nothing else, so calling it on an ordinary translation is harmless.ProductDetailsuses it forpages.products.sold_times. Salla's translations use this format forblocks.header.products_count,blocks.comments.commentandpages.rating.reviewstoo.A plain function, not a hook: call it anywhere.
Gotchas
When no part matches the count, the whole template comes back with only its tags removed.
sold_timeshas no{0}, soformatSallaPlural(t('pages.products.sold_times'), 0)returns{1} One time|{2} Two times|[3,10] 0 times|[11,*] 0 Time; negative and fractional counts do the same. Check the count first, asProductDetailsdoes withsold_quantity > 0.The result is plain text. Markup in the translation (the
<span>around the number) is removed, so it cannot be styled; build that markup yourself.A template that is not a string returns
String(template ?? ''):undefinedgives an empty string.
Related
Source and docs
- Engine source:
packages/theme-engine/src/utils/salla-plural.ts