Pluralization and l10n
As wuchale
is not a library you import from, but a compile time tool, you can
tell it to look for patterns you write in the code to achieve pluralization and
localization. This is done using the patterns
.
ICU style pluralization and localization
Section titled “ICU style pluralization and localization”In this approach, the pluralization rule is mixed with the messages inside a single big string. While it may have it’s complexity, it can be used to construct complex combinations, even mixing with other data types like genders and dates.
To work with this approach, you have to select and install the localization
library of your choices, wuchale
doesn’t limit you to some, because it
doesn’t depend on any, it just transforms you code. For starters, here are some
suggestions:
- Intl MessageFormat: based on an ECMA-402 proposal
- messageformat: based on another ECMA-402 proposal
We will take the first one as an example.
First you have to configure the signature of your own reusable function in the config:
// ...adapters: js({ patterns: [ { name: "formatMsg", args: ["message", "other"], }, ],});//...
Then you create your reusable utility function with that name:
// where you get the locale, can be a reactive store or anythinglet currentLocale = "en";
export function formatMsg(msg, args) { return new IntlMessageFormat(msg, currentLocale).format(args);}
And then you can use it anywhere:
const msg = formatMsg( `{numPhotos, plural, =0 {You have no photos.} =1 {You have one photo.} other {You have # photos.} }`, { numPhotos: 1000 });
Then wuchale
will extract and transform it into:
const msg = formatMsg(_w_runtime_.t(0), { numPhotos: 1000 });
And you will find that big string in the PO file, and can translate it, changing the rules as you want.
msgid """\n""{numPhotos, plural,\n""=0 {You have no photos.}\n""=1 {You have one photo.}\n""other {You have # photos.}\n""}\n"""msgstr """\n""{numPhotos, plural,\n""=0 {You have no photos.}\n""=1 {You have one photo.}\n""other {You have # photos.}\n""}\n"""
PO style pluralization
Section titled “PO style pluralization”In this approach, the plural rule is written inside the PO file headers and the candidates are listed in each item. This approach is sufficient for most cases and it doesn’t require installing additional libraries.
The pattern for this is configured as default
.
You first define your own function that selects the correct message from provided candidates based on the number, replaces the placeholder if needed, and returns the final message. The only requirement is that the signature has to match that of the below example.
export function plural(num, candidates, rule = n => n === 1 ? 0 : 1) { const index = rule(num) return candidates[index].replace('#', num)}
Notice that this is still not about wuchale
, you are just defining a
convenient reusable function with pluggable selection rules.
To be more specific, the signature has to be:
function plural(num: number, candidates: string[], rule?: (n: number) => number): string
Now you use your function in your codebase:
<script> import {plural} from '/src/utils.js' let itemCount = 5</script>
<p>{plural(itemCount, ['One item', '# items'])}</p>
That’s it. wuchale
has enough information to take it from there.
How it works
Section titled “How it works”The first information it takes is from your locale
configuration in wuchale.config.js
. It takes
the number of plurals, nPlurals
and prepares the translation catalogs in this
way (e.g. Spanish, after translation):
msgid "One item"msgid_plural "# items"msgstr[0] "Un artículo"msgstr[1] "# artículos"
The next information it takes from the config is the plural
rule. It bundles that with the data when it compiles the catalogs.
export const c = [['Un artículo', '# artículos']]export const p = n => n == 1 ? 0 : 1
There are only two plural forms because Spanish has two. Some languages have
more, and they are supported too, it’s just a matter of having the correct
nPlurals
and explaining the rule using the plural
expression in the config
and wuchale
prepares the the catalogs and compiles them accordingly.
Then during transformation, your code gets updated to use the current locale’s data:
<script> import _w_rt_ from '../locales/loader.svelte.js' const _w_runtime_ = _w_rt_('main') import {plural} from '/src/utils.js' let itemCount = 5</script>
<p>{plural(itemCount, _w_runtime_.tp(0), _w_runtime_._.p)}</p>
That way, the function that you define doesn’t have to know about the number of
possible plural rules; it is provided the candidates and the selection rule
specific to the locale. It just have to select the candidate, do the necessary
modification (replacing #
for example) and return the resulting single
string.
You can configure wuchale
to work
with a function with a different name if you want.