Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pluralisation support to i18n functionality #2853

Merged
merged 7 commits into from
Sep 15, 2022

Conversation

querkmachine
Copy link
Member

Expands the i18n functionality to add pluralisation support, via passing the special count option through the t() method. Doing so will locate the appropriate plural form suffix for the current locale and append this to the lookup key.

Suffixes are based on the Unicode CLDR specification and align with the output of the Intl.PluralRules implementation.

For example, calling the method with testKey will instead use the following lookup keys in the configured locales:

t('testKey', { count: 0 })
// locale: 'en' => testKeyOther
// locale: 'cy' => testKeyZero
// locale: 'fr' => testKeyOne

t('testKey', { count: 1 })
// locale: 'en' => testKeyOne
// locale: 'cy' => testKeyOne
// locale: 'zh' => testKeyOther

t('testKey', { count: 6 })
// locale: 'en' => testKeyOther
// locale: 'cy' => testKeyMany
// locale: 'ga' => testKeyFew

Closes #2804.

Changes

  • Added config parameter to the I18n constructor. Currently this only has one option, locale. Unlike the locale option in earlier spikes, this one is only intended to be used internally and isn't configurable by users. Falls back to the document language if not specified.
  • Modifies the t method to check for the presence of a count option and, if present, calls getPluralSuffix and modifies the lookup key to point to the appropriate plural form.
  • Modifies the replacePlaceholders method to check if the placeholder is of type 'number' and, if so, to format it according to the configured locale. The number will not be formatted if Intl.NumberFormat isn't supported.
  • Added three of new functions to I18n:
    • hasIntlPluralRulesSupport: Checks for browser support for Intl.PluralRules and related dependencies. Used by getPluralSuffix.
    • hasIntlNumberFormatSupport: Checks for browser support for Init.NumberFormat and related dependencies. Used by replacePlaceholders.
    • getPluralSuffix: Gets the CLDR specification plural form type (zero, one, two, few, many or other) based on the given number and configured locale. Falls back to the hardcoded plural rules if Intl.PluralRules is not supported.
  • Added two lookup maps to I18n:
    • pluralRules: Provides a fallback set of functions for determining the correct plural suffix to use for a given number and language.
    • pluralRulesMap: Object mapping language codes to the appropriate function within pluralRules.
  • Added unit tests.
    • Checks that placeholders of type 'number' are formatted as numbers.
    • Checks that placeholders that look like numbers, but are not (i.e. strings) are not formatted as numbers.
    • Checks that an error is thrown if the currently required plural form hasn't been passed in the translations object.
    • Checks that string interpolation of the count option is possible and uses the appropriate plural form for the value of count.
    • Checks that the fallback pluralRules functions produce values consistent with Intl.PluralRules.

Supported fallback languages

Browsers that support Intl.PluralRules theoretically support any language the browser vendor chooses to support. For older browsers (primarily Internet Explorer), we provide a set of fallback functions for a limited set of languages.

We don't have any definitive data on what languages are used by forms services on GOV.UK (the main expected use case for these changes). This list has been compiled by combining languages we know are used by GOV.UK services, some assumptions, and languages that, although not in known use, have plural rules identical to other supported languages and are 'quick wins' for support.

Known in use by GOV.UK services:

  • Arabic (ar)
  • Bangla (bn)
  • Chinese (zh)
  • English (en)
  • French (fr)
  • Gujarati (gu)
  • Hindi (hi)
  • Indonesian (id)
  • Japanese (jp)
  • Korean (ko)
  • Russian (ru)
  • Spanish (es)
  • Tamil (ta)
  • Thai (th)
  • Turkish (tr)
  • Urdu (ur)
  • Vietnamese (vi)
  • Welsh (cy)

Languages that are assumed may be in use:

  • Irish Gaelic (ga)
  • Scottish Gaelic (gd)

'Quick win' languages:

  • Afrikaans (af)
  • Albanian (sq)
  • Armenian (hy)
  • Azerbaijani (az)
  • Basque (eu)
  • Bulgarian (bg)
  • Burmese (my)
  • Catalan (ca)
  • Danish (da)
  • Dutch (nl)
  • Estonian (et)
  • Farsi (fa)
  • Finnish (fi)
  • Georgian (ka)
  • German (de)
  • Greek (el)
  • Hungarian (hl)
  • Italian (it)
  • Javanese (jv)
  • Luxembourgish (lb)
  • Malay (ms)
  • Norwegian (de)
  • Portuguese (European) (pt-PT)
  • Punjabi (pa)
  • Somali (so)
  • Swahili (sw)
  • Swedish (sv)
  • Telugu (te)
  • Ukrainian (uk)
  • Zulu (zu)

@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2853 September 15, 2022 11:43 Inactive
@querkmachine querkmachine requested a review from a team September 15, 2022 11:44
Copy link
Contributor

@36degrees 36degrees left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very, very cool.

Well commented, tests seem to make sense.

is there anything that we've used as a reference, copied or adapted that should be credited either in the commit messages or comments? (And do we need to check the licensing on anything?)

src/govuk/i18n.mjs Outdated Show resolved Hide resolved
src/govuk/i18n.unit.test.mjs Outdated Show resolved Hide resolved
src/govuk/i18n.unit.test.mjs Show resolved Hide resolved
@36degrees
Copy link
Contributor

I think this also closes #2568 – worth associate this PR with it and moving it into Needs Review so nobody else tries to pick it up?

@querkmachine querkmachine linked an issue Sep 15, 2022 that may be closed by this pull request
@querkmachine
Copy link
Member Author

@36degrees Good point. Have added it.

@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2853 September 15, 2022 12:59 Inactive
toEqual runs deep equality checking, however as we're only comparing strings, we don't need this ability.
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-2853 September 15, 2022 13:40 Inactive
@querkmachine querkmachine merged commit d4afba8 into main Sep 15, 2022
@querkmachine querkmachine deleted the kg-i18n-pluralisation-support branch September 15, 2022 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants