Using custom formatter:
import string class PluralFormatter(string.Formatter): def get_value(self, key, args, kwargs): if isinstance(key, int): return args[key] if key in kwargs: return kwargs[key] if '(' in key and key.endswith(')'): key, rest = key.split('(', 1) value = kwargs[key] suffix = rest.rstrip(')').split(',') if len(suffix) == 1: suffix.insert(0, '') return suffix[0] if value <= 1 else suffix[1] else: raise KeyError(key) data = {'tree': 1, 'bush': 2, 'flower': 3, 'cactus': 0} formatter = PluralFormatter() fmt = "{tree} tree{tree(s)}, {bush} bush{bush(es)}, {flower} flower{flower(s)}, {cactus} cact{cactus(i,us)}" print(formatter.format(fmt, **data))
Output:
1 tree, 2 bushes, 3 flowers, 0 cacti
UPDATE
If you're using Python 3.2+ (str.format_map
was added), you can use the idea of OP (see comment) that use customized dict.
class PluralDict(dict): def __missing__(self, key): if '(' in key and key.endswith(')'): key, rest = key.split('(', 1) value = super().__getitem__(key) suffix = rest.rstrip(')').split(',') if len(suffix) == 1: suffix.insert(0, '') return suffix[0] if value <= 1 else suffix[1] raise KeyError(key) data = PluralDict({'tree': 1, 'bush': 2, 'flower': 3, 'cactus': 0}) fmt = "{tree} tree{tree(s)}, {bush} bush{bush(es)}, {flower} flower{flower(s)}, {cactus} cact{cactus(i,us)}" print(fmt.format_map(data))
Output: same as above.