Skip to content

Commit

Permalink
CommentHandling: add support for reading #|
Browse files Browse the repository at this point in the history
- write obsolete entries entirely
- add support for reading "previous" (#| ) comments
  • Loading branch information
Jakob Probst committed Oct 15, 2020
1 parent 78c4282 commit 3aa7ee0
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 171 deletions.
76 changes: 36 additions & 40 deletions babel/messages/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,22 @@

import re
import time

from cgi import parse_header
from collections import OrderedDict
from copy import copy
from datetime import datetime, time as time_
from difflib import get_close_matches
from email import message_from_string
from copy import copy

from babel import __version__ as VERSION
from babel._compat import string_types, number_types, PY2, cmp, text_type, force_text
from babel.core import Locale, UnknownLocaleError
from babel.dates import format_datetime
from babel.messages.plurals import get_plural
from babel.util import distinct, LOCALTZ, FixedOffsetTimezone
from babel._compat import string_types, number_types, PY2, cmp, text_type, force_text

__all__ = ['Message', 'Catalog', 'TranslationError']


PYTHON_FORMAT = re.compile(r'''
\%
(?:\(([\w]*)\))?
Expand Down Expand Up @@ -76,8 +74,8 @@ def _parse_datetime_header(value):
class Message(object):
"""Representation of a single message in a catalog."""

def __init__(self, id, string=u'', locations=(), flags=(), auto_comments=(),
user_comments=(), previous_id=(), lineno=None, context=None):
def __init__(self, id, string=u'', locations=(), flags=(), extracted_comments=(),
translator_comments=(), previous_id=(), previous_context=None, lineno=None, context=None):
"""Create the message object.
:param id: the message ID, or a ``(singular, plural)`` tuple for
Expand All @@ -86,10 +84,11 @@ def __init__(self, id, string=u'', locations=(), flags=(), auto_comments=(),
``(singular, plural)`` tuple for pluralizable messages
:param locations: a sequence of ``(filename, lineno)`` tuples
:param flags: a set or sequence of flags
:param auto_comments: a sequence of automatic comments for the message
:param user_comments: a sequence of user comments for the message
:param extracted_comments: a sequence of extracted comments for the message
:param translator_comments: a sequence of translator comments for the message
:param previous_id: the previous message ID, or a ``(singular, plural)``
tuple for pluralizable messages
:param previous_context: the previous message context
:param lineno: the line number on which the msgid line was found in the
PO file, if any
:param context: the message context
Expand All @@ -104,12 +103,10 @@ def __init__(self, id, string=u'', locations=(), flags=(), auto_comments=(),
self.flags.add('python-format')
else:
self.flags.discard('python-format')
self.auto_comments = list(distinct(auto_comments))
self.user_comments = list(distinct(user_comments))
if isinstance(previous_id, string_types):
self.previous_id = [previous_id]
else:
self.previous_id = list(previous_id)
self.extracted_comments = list(distinct(extracted_comments))
self.translator_comments = list(distinct(translator_comments))
self.previous_id = previous_id
self.previous_context = previous_context
self.lineno = lineno
self.context = context

Expand All @@ -119,10 +116,12 @@ def __repr__(self):

def __cmp__(self, other):
"""Compare Messages, taking into account plural ids"""

def values_to_compare(obj):
if isinstance(obj, Message) and obj.pluralizable:
return obj.id[0], obj.context or ''
return obj.id, obj.context or ''

return cmp(values_to_compare(self), values_to_compare(other))

def __gt__(self, other):
Expand All @@ -145,9 +144,10 @@ def __ne__(self, other):

def clone(self):
return Message(*map(copy, (self.id, self.string, self.locations,
self.flags, self.auto_comments,
self.user_comments, self.previous_id,
self.lineno, self.context)))
self.flags, self.extracted_comments,
self.translator_comments, self.previous_id,
self.previous_context, self.lineno,
self.context)))

def check(self, catalog=None):
"""Run various validation checks on the message. Some validations
Expand Down Expand Up @@ -223,7 +223,6 @@ class TranslationError(Exception):
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#"""


if PY2:
def _parse_header(header_string):
# message_from_string only works for str, not for unicode
Expand Down Expand Up @@ -336,9 +335,9 @@ def _get_header_comment(self):
if hasattr(self.revision_date, 'strftime'):
year = self.revision_date.strftime('%Y')
comment = comment.replace('PROJECT', self.project) \
.replace('VERSION', self.version) \
.replace('YEAR', year) \
.replace('ORGANIZATION', self.copyright_holder)
.replace('VERSION', self.version) \
.replace('YEAR', year) \
.replace('ORGANIZATION', self.copyright_holder)
locale_name = (self.locale.english_name if self.locale else self.locale_identifier)
if locale_name:
comment = comment.replace('Translations template', '%s translations' % locale_name)
Expand Down Expand Up @@ -617,26 +616,26 @@ def __setitem__(self, id, message):
current.string = message.string
current.locations = list(distinct(current.locations +
message.locations))
current.auto_comments = list(distinct(current.auto_comments +
message.auto_comments))
current.user_comments = list(distinct(current.user_comments +
message.user_comments))
current.extracted_comments = list(distinct(current.extracted_comments +
message.extracted_comments))
current.translator_comments = list(distinct(current.translator_comments +
message.translator_comments))
current.flags |= message.flags
message = current
elif id == '':
# special treatment for the header message
self.mime_headers = _parse_header(message.string).items()
self.header_comment = '\n'.join([('# %s' % c).rstrip() for c
in message.user_comments])
in message.translator_comments])
self.fuzzy = message.fuzzy
else:
if isinstance(id, (list, tuple)):
assert isinstance(message.string, (list, tuple)), \
'Expected sequence but got %s' % type(message.string)
self._messages[key] = message

def add(self, id, string=None, locations=(), flags=(), auto_comments=(),
user_comments=(), previous_id=(), lineno=None, context=None):
def add(self, id, string=None, locations=(), flags=(), extracted_comments=(),
translator_comments=(), previous_id=(), previous_context=None, lineno=None, context=None):
"""Add or update the message with the specified ID.
>>> catalog = Catalog()
Expand All @@ -654,17 +653,17 @@ def add(self, id, string=None, locations=(), flags=(), auto_comments=(),
``(singular, plural)`` tuple for pluralizable messages
:param locations: a sequence of ``(filename, lineno)`` tuples
:param flags: a set or sequence of flags
:param auto_comments: a sequence of automatic comments
:param user_comments: a sequence of user comments
:param extracted_comments: a sequence of extracted comments
:param translator_comments: a sequence of translater comments
:param previous_id: the previous message ID, or a ``(singular, plural)``
tuple for pluralizable messages
:param previous_context: the previous message context
:param lineno: the line number on which the msgid line was found in the
PO file, if any
:param context: the message context
"""
message = Message(id, string, list(locations), flags, auto_comments,
user_comments, previous_id, lineno=lineno,
context=context)
message = Message(id, string, list(locations), flags, extracted_comments,
translator_comments, previous_id, previous_context, lineno, context)
self[id] = message
return message

Expand Down Expand Up @@ -700,7 +699,7 @@ def delete(self, id, context=None):
if key in self._messages:
del self._messages[key]

def update(self, template, no_fuzzy_matching=False, update_header_comment=False, keep_user_comments=True):
def update(self, template, no_fuzzy_matching=False, update_header_comment=False, keep_translator_comments=True):
"""Update the catalog based on the given template catalog.
>>> from babel.messages import Catalog
Expand Down Expand Up @@ -773,16 +772,13 @@ def _merge(message, oldkey, newkey):
fuzzy = True
fuzzy_matches.add(oldkey)
oldmsg = messages.get(oldkey)
if isinstance(oldmsg.id, string_types):
message.previous_id = [oldmsg.id]
else:
message.previous_id = list(oldmsg.id)
message.previous_id = oldmsg.id
else:
oldmsg = remaining.pop(oldkey, None)
message.string = oldmsg.string

if keep_user_comments:
message.user_comments = list(distinct(oldmsg.user_comments))
if keep_translator_comments:
message.translator_comments = list(distinct(oldmsg.translator_comments))

if isinstance(message.id, (list, tuple)):
if not isinstance(message.string, (list, tuple)):
Expand Down
2 changes: 1 addition & 1 deletion babel/messages/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ def callback(filename, method, options):
filepath = os.path.normpath(os.path.join(path, filename))

catalog.add(message, None, [(filepath, lineno)],
auto_comments=comments, context=context)
extracted_comments=comments, context=context)

self.log.info('writing PO template file to %s', self.output_file)
write_po(outfile, catalog, width=self.width,
Expand Down
Loading

0 comments on commit 3aa7ee0

Please sign in to comment.