Skip to content

Add Pluralization rules based on Intl.PluralRules #2020

Open
@ssendev

Description

@ssendev

Clear and concise description of the problem

The default pluralization rules are pretty simple and Intl.PluralRules has 97% browsersupport so it would be nice to have an implementation based on it with fallback to the current simple one. Which maybe needs revising since it can currently return a number greater than choicesLength - 1 that then crashes vue

Suggested solution

Here is an implementation that works with the current api but the implementation could be cleaner without the Proxy

const pluralOrder: Intl.LDMLPluralRule[] = [
  'zero',
  'one',
  'two',
  'few',
  'many',
  'other',
]

function pluralSort(a: Intl.LDMLPluralRule, b: Intl.LDMLPluralRule) {
  return pluralOrder.indexOf(a) - pluralOrder.indexOf(b)
}

const pluralRules = new Proxy(
  {} as {
    [lang: string]:
      | ((choice: number, choicesLength: number) => number)
      | undefined
  },
  {
    get: (target, prop: string) => {
      if (prop in target) return target[prop]

      try {
        const rules = new Intl.PluralRules(prop)
        const categories = rules
          .resolvedOptions()
          .pluralCategories.sort(pluralSort)

        return (target[prop] = (choice: number, choicesLength: number) => {
          const rule = rules.select(choice)
          const n = categories.indexOf(rule)

          return Math.min(n, choicesLength - 1)
        })
      } catch (e) {
        target[prop] = undefined
      }
    },
  },
)

Alternative

If shipping it by default is considered too large it could live in an extra import so that it's easy to use

import pluralRules from '@intlify/plural'

The implementation could also be cleaner if instead of an object pluralRules could be a function that receives the locale maybe it would be a factory so that it only gets called once per locale

Additional context

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions