Custom selectors
It is possible to write a custom selector to be used with the .match
statement.
Here's a simple implementation of the :integer selector:
def integer_selector(
value: Any, # The value passed to the selector while formatting the message
*,
locale: Locale, # Babel locale
options: dict[str, Any], # Selector options
keys: list[str] # Variant keys to be filtered out
) -> list[str]:
select = options.get("select", "plural")
exact_keys = [value] if value in keys else []
if select == "exact":
return exact_keys
if select == "plural":
form = locale.plural_form(value)
if select == "ordinal":
form = locale.ordinal_form(value)
return exact_keys + keyword_keys
format_message("""\
.match {$count :integer select=plural}
1 {{You have one notification.}}
one {{You have {$count} notification.}}
* {{You have {$count} notifications.}}""",
{"count": 1},
selectors={"integer": integer_selector}
)
# -> You have one notification.
A selector function must take exactly 3 arguments:
value: the value passed to the formatter when formattinglocale: the current locale as ababel.Localeinstanceoptions: a dictionary containing all the options passed to the formatter.keys: The key from each variant of the match statement.
For example, for this message:
.match {$count :integer select=plural}
1 {{You have one notification.}}
one {{You have {$count} notification.}}
* {{You have ???}}
The selector would receive as arguments:
value=2locale=babel.Locale("en_US")options={"select": "plural"}keys=["1", "one"]
The return value is another list of keys which is a subset of the passed keys.
Only those keys that match the selector shall be kept. If no keys match the
selector, an empty list should be returned. The keys are returned in
preferential order. key[0] should be prefered over key[1] and so on.
Specifically for number and integer selector exact matches (1, 2, ..) are to be prefered over
keyword matches (one, few, many, ..).