jenkins-bot has submitted this change and it was merged.
Change subject: [IMPROV] i18n: Replace all plural items at once ......................................................................
[IMPROV] i18n: Replace all plural items at once
Instead of generating one list of plural items and to substitute always the first occurrence it can actually iterate over the string using `re.sub` and dynamically replace it with a plural replacement.
It does verify that `nplurals` is 1 when the `plurals` is not callable. And if `nplurals` is 1 it verifies that that the value returned is 0.
Change-Id: Id72f7bd55ddd816f6d15ba69e9b8e936333625fd --- M pywikibot/i18n.py 1 file changed, 43 insertions(+), 22 deletions(-)
Approvals: John Vandenberg: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/i18n.py b/pywikibot/i18n.py index fe06672..58e23fd 100644 --- a/pywikibot/i18n.py +++ b/pywikibot/i18n.py @@ -338,31 +338,48 @@ @param message: the message to be replaced @type message: unicode string @param parameters: plural parameters passed from other methods - @type parameters: int, basestring, tuple, list, dict - + @type parameters: Mapping of str to int + @return: The message with the plural instances replaced + @rtype: str """ - plural_items = re.findall(PLURAL_PATTERN, message) + def static_plural_value(n): + return rule['plural'] + + def replace_plural(match): + selector = match.group(1) + variants = match.group(2) + num = parameters[selector] + if not isinstance(num, int): + issue_deprecation_warning( + 'type {0} for value {1} ({2})'.format(type(num), selector, num), + 'an int', 1) + num = int(num) + + index = plural_value(num) + if rule['nplurals'] == 1: + assert index == 0 + + plural_entries = variants.split('|') + if index >= len(plural_entries): + raise IndexError( + 'requested plural {0} for {1} but only {2} ("{3}") ' + 'provided'.format( + index, selector, len(plural_entries), + '", "'.join(plural_entries))) + return plural_entries[index] + assert isinstance(parameters, Mapping), \ 'parameters is not Mapping but {0}'.format(type(parameters)) - if plural_items: # we found PLURAL patterns, process it - for selector, variants in plural_items: - num = parameters[selector] - if not isinstance(num, int): - issue_deprecation_warning( - 'type {0} for value {1} ({2})'.format(type(num), selector, num), - 'an int', 1) - num = int(num) - # TODO: check against plural_rules[code]['nplurals'] - try: - index = plural_rules[code]['plural'](num) - except KeyError: - index = plural_rules['_default']['plural'](num) - except TypeError: - # we got an int, not a function - index = plural_rules[code]['plural'] - repl = variants.split('|')[index] - message = re.sub(PLURAL_PATTERN, repl, message, count=1) - return message + try: + rule = plural_rules[code] + except KeyError: + rule = plural_rules['_default'] + plural_value = rule['plural'] + if not callable(plural_value): + assert rule['nplurals'] == 1 + plural_value = static_plural_value + + return re.sub(PLURAL_PATTERN, replace_plural, message)
class _PluralMappingAlias(Mapping): @@ -430,6 +447,8 @@ @param fallback: Try an alternate language code. If it's iterable it'll also try those entries and choose the first match. @type fallback: boolean or iterable + @raise IndexError: If the language supports and requires more plurals than + defined for the given translation template. """ family = pywikibot.config.family # If a site is given instead of a code, use its language @@ -548,6 +567,8 @@ to the resulting string. If this is True the placeholders must be manually applied afterwards. @type only_plural: bool + @raise IndexError: If the language supports and requires more plurals than + defined for the given translation template. """ if not messages_available(): raise TranslationError(
pywikibot-commits@lists.wikimedia.org