diff --git a/babel/messages/pofile.py b/babel/messages/pofile.py index e3b99e4b6..b002d2b1f 100644 --- a/babel/messages/pofile.py +++ b/babel/messages/pofile.py @@ -174,6 +174,8 @@ def __init__( self.counter = 0 self.offset = 0 self.abort_invalid = abort_invalid + # Identical message IDs share one string object while parsing. + self._msgids: dict[str, str] = {} self._reset_message_state() def _reset_message_state(self) -> None: @@ -210,6 +212,10 @@ def _add_message(self) -> None: else: msgid = self.messages[0].denormalize() string = self.translations[0][1].denormalize() + if isinstance(msgid, tuple): + msgid = tuple(self._msgids.setdefault(part, part) for part in msgid) + else: + msgid = self._msgids.setdefault(msgid, msgid) msgctxt = self.context.denormalize() if self.context else None message = Message( msgid, diff --git a/tests/messages/test_pofile_read.py b/tests/messages/test_pofile_read.py index d17f5d4af..973d78ba1 100644 --- a/tests/messages/test_pofile_read.py +++ b/tests/messages/test_pofile_read.py @@ -406,6 +406,36 @@ def test_with_context_two(): assert out_buf.getvalue().strip() == buf.getvalue().strip(), out_buf.getvalue() +def test_repeated_msgids_share_strings(): + buf = StringIO(r'''msgctxt "Menu" +msgid "Open" +msgstr "Ouvrir" + +msgctxt "Button" +msgid "Open" +msgstr "Ouvrir" + +msgctxt "Menu" +msgid "%d file" +msgid_plural "%d files" +msgstr[0] "%d fichier" +msgstr[1] "%d fichiers" + +msgctxt "Button" +msgid "%d file" +msgid_plural "%d files" +msgstr[0] "%d fichier" +msgstr[1] "%d fichiers" +''') + catalog = pofile.read_po(buf) + assert catalog.get('Open', context='Menu').id is catalog.get('Open', context='Button').id + menu_id = catalog.get('%d file', context='Menu').id + button_id = catalog.get('%d file', context='Button').id + assert menu_id == button_id == ('%d file', '%d files') + assert menu_id[0] is button_id[0] + assert menu_id[1] is button_id[1] + + def test_single_plural_form(): buf = StringIO(r'''msgid "foo" msgid_plural "foos"