diff --git a/fluent/migrate/transforms.py b/fluent/migrate/transforms.py index b747a128..8cd85102 100644 --- a/fluent/migrate/transforms.py +++ b/fluent/migrate/transforms.py @@ -236,6 +236,13 @@ def __call__(self, ctx): selector = evaluate(ctx, self.selector) variants = value.split(';') keys = ctx.plural_categories + + # A special case for languages with one plural category. We don't need + # to insert a SelectExpression at all for them. + if len(keys) == len(variants) == 1: + variant, = variants + return evaluate(ctx, self.foreach(variant)) + last_index = min(len(variants), len(keys)) - 1 def createVariant(zipped_enum): diff --git a/tests/migrate/test_plural.py b/tests/migrate/test_plural.py index 0fb21726..044dd074 100644 --- a/tests/migrate/test_plural.py +++ b/tests/migrate/test_plural.py @@ -15,7 +15,8 @@ class MockContext(unittest.TestCase): - # Static categories corresponding to en-US. + maxDiff = None + # Plural categories corresponding to English (en-US). plural_categories = ('one', 'other') def get_source(self, path, key): @@ -142,5 +143,81 @@ def test_plural_replace(self): ) +@unittest.skipUnless(PropertiesParser, 'compare-locales required') +class TestOneCategory(MockContext): + # Plural categories corresponding to Turkish (tr). + plural_categories = ('other',) + + def setUp(self): + self.strings = parse(PropertiesParser, ''' + deleteAll=#1 indirme silinsin mi? + ''') + + self.message = FTL.Message( + FTL.Identifier('delete-all'), + value=PLURALS( + 'test.properties', + 'deleteAll', + EXTERNAL_ARGUMENT('num'), + lambda text: REPLACE_IN_TEXT( + text, + { + '#1': EXTERNAL_ARGUMENT('num') + } + ) + ) + ) + + def test_no_select_expression(self): + self.assertEqual( + evaluate(self, self.message).to_json(), + ftl_message_to_json(''' + delete-all = { $num } indirme silinsin mi? + ''') + ) + + +@unittest.skipUnless(PropertiesParser, 'compare-locales required') +class TestManyCategories(MockContext): + # Plural categories corresponding to Polish (pl). + plural_categories = ('one', 'few', 'many', 'other') + + def setUp(self): + self.strings = parse(PropertiesParser, ''' + deleteAll=Usunąć plik?;Usunąć #1 pliki?;Usunąć #1 plików? + ''') + + self.message = FTL.Message( + FTL.Identifier('delete-all'), + value=PLURALS( + 'test.properties', + 'deleteAll', + EXTERNAL_ARGUMENT('num'), + lambda text: REPLACE_IN_TEXT( + text, + { + '#1': EXTERNAL_ARGUMENT('num') + } + ) + ) + ) + + def test_too_few_variants(self): + # StringBundle's plural rule #9 used for Polish has three categories + # which is one fewer than the CLDR's. The migrated string will not have + # the [other] variant and [many] will be marked as the default. + self.assertEqual( + evaluate(self, self.message).to_json(), + ftl_message_to_json(''' + delete-all = + { $num -> + [one] Usunąć plik? + [few] Usunąć { $num } pliki? + *[many] Usunąć { $num } plików? + } + ''') + ) + + if __name__ == '__main__': unittest.main()