
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
eYy                 @   s   d Z ddlZddlZddlmZ ddlmZmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZmZmZmZ ddlmZmZmZmZ dddgZej dej!Z"dd Z#G dd de$Z%G dd de&Z'dZ(erdd Z)ne
Z)G dd de$Z*dS )z
    babel.messages.catalog
    ~~~~~~~~~~~~~~~~~~~~~~

    Data structures for message catalogs.

    :copyright: (c) 2013 by the Babel Team.
    :license: BSD, see LICENSE for more details.
    N)parse_header)datetimetime)get_close_matches)message_from_string)copy)__version__)Locale)format_datetime)
get_plural)odictdistinctLOCALTZFixedOffsetTimezone)string_typesnumber_typesPY2cmpMessageCatalogTranslationErrorz
    \%
        (?:\(([\w]*)\))?
        (
            [-#0\ +]?(?:\*|[\d]+)?
            (?:\.(?:\*|[\d]+))?
            [hlL]?
        )
        ([diouxXeEfFgGcrs%])
c             C   s   t jd| }tj|jdd}tj|}tj|}|jd}|d k	r|d |dd   }}|d d |dd   }}	t|d }
t|}t|	}|d	 }||7 }||
9 }t	|}|j
|d
}|S )Nz+^(?P<datetime>.*?)(?P<tzoffset>[+-]\d{4})?$r   z%Y-%m-%d %H:%Mtzoffsetr         1<   )tzinfo)rematchr   ZstrptimegroupZmktimer   Zfromtimestampintr   replace)valuer   ZttZtsZdtr   Zplus_minus_srestZhours_offset_sZmins_offset_sZ
plus_minusZhours_offsetZmins_offsetZnet_mins_offset r$   /usr/lib/python3.6/catalog.py_parse_datetime_header+   s"    


r&   c               @   s   e Zd ZdZdf f f f f ddfddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zd ddZedd Zedd Zedd ZdS )!r   z0Representation of a single message in a catalog. Nc
       
      C   s   || _ | r| jrd}|| _tt|| _t|| _|rL| jrL| jj	d n| jj
d tt|| _tt|| _t|tr|g| _n
t|| _|| _|	| _dS )a_  Create the message object.

        :param id: the message ID, or a ``(singular, plural)`` tuple for
                   pluralizable messages
        :param string: the translated message string, or a
                       ``(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 previous_id: the previous message ID, or a ``(singular, plural)``
                            tuple for pluralizable messages
        :param lineno: the line number on which the msgid line was found in the
                       PO file, if any
        :param context: the message context
        r'   zpython-formatN)r'   r'   )idpluralizablestringlistr   	locationssetflagspython_formatadddiscardauto_commentsuser_comments
isinstancer   previous_idlinenocontext)
selfr(   r*   r,   r.   r2   r3   r5   r6   r7   r$   r$   r%   __init__N   s     




zMessage.__init__c             C   s   dt | j| jt| jf S )Nz<%s %r (flags: %r)>)type__name__r(   r+   r.   )r8   r$   r$   r%   __repr__s   s    zMessage.__repr__c             C   s   dd }t || ||S )z0Compare Messages, taking into account plural idsc             S   s4   t | tr$| jr$| jd | jp dfS | j| jp0dfS )Nr   r'   )r4   r   r)   r(   r7   )objr$   r$   r%   values_to_comparey   s    z*Message.__cmp__.<locals>.values_to_compare)r   )r8   otherr>   r$   r$   r%   __cmp__w   s    zMessage.__cmp__c             C   s   | j |dkS )Nr   )r@   )r8   r?   r$   r$   r%   __gt__   s    zMessage.__gt__c             C   s   | j |dk S )Nr   )r@   )r8   r?   r$   r$   r%   __lt__   s    zMessage.__lt__c             C   s   | j |dkS )Nr   )r@   )r8   r?   r$   r$   r%   __ge__   s    zMessage.__ge__c             C   s   | j |dkS )Nr   )r@   )r8   r?   r$   r$   r%   __le__   s    zMessage.__le__c             C   s   | j |dkS )Nr   )r@   )r8   r?   r$   r$   r%   __eq__   s    zMessage.__eq__c             C   s   | j |dkS )Nr   )r@   )r8   r?   r$   r$   r%   __ne__   s    zMessage.__ne__c             C   s2   t tt| j| j| j| j| j| j| j	| j
| jf	 S )N)r   mapr   r(   r*   r,   r.   r2   r3   r5   r6   r7   )r8   r$   r$   r%   clone   s    zMessage.clonec             C   s^   ddl m} g }xH|D ]@}y|||  W q tk
rT } z|j| W Y dd}~X qX qW |S )a  Run various validation checks on the message.  Some validations
        are only performed if the catalog is provided.  This method returns
        a sequence of `TranslationError` objects.

        :rtype: ``iterator``
        :param catalog: A catalog instance that is passed to the checkers
        :see: `Catalog.check` for a way to perform checks for all messages
              in a catalog.
        r   )checkersN)Zbabel.messages.checkersrI   r   append)r8   catalogrI   errorsZcheckerer$   r$   r%   check   s    

 zMessage.checkc             C   s
   d| j kS )a   Whether the translation is fuzzy.

        >>> Message('foo').fuzzy
        False
        >>> msg = Message('foo', 'foo', flags=['fuzzy'])
        >>> msg.fuzzy
        True
        >>> msg
        <Message 'foo' (flags: ['fuzzy'])>

        :type:  `bool`fuzzy)r.   )r8   r$   r$   r%   rO      s    zMessage.fuzzyc             C   s   t | jttfS )zWhether the message is plurizable.

        >>> Message('foo').pluralizable
        False
        >>> Message(('foo', 'bar')).pluralizable
        True

        :type:  `bool`)r4   r(   r+   tuple)r8   r$   r$   r%   r)      s    
zMessage.pluralizablec             C   s,   | j }t|ttfs|g}tdd |D S )zWhether the message contains Python-style parameters.

        >>> Message('foo %(name)s bar').python_format
        True
        >>> Message(('foo %(name)s', 'foo %(name)s')).python_format
        True

        :type:  `bool`c             s   s   | ]}t j|V  qd S )N)PYTHON_FORMATsearch).0r(   r$   r$   r%   	<genexpr>   s    z(Message.python_format.<locals>.<genexpr>)r(   r4   r+   rP   any)r8   Zidsr$   r$   r%   r/      s    
zMessage.python_format)N)r;   
__module____qualname____doc__r9   r<   r@   rA   rB   rC   rD   rE   rF   rH   rN   propertyrO   r)   r/   r$   r$   r$   r%   r   K   s    $
c               @   s   e Zd ZdZdS )r   z_Exception thrown by translation checkers when invalid message
    translations are encountered.N)r;   rV   rW   rX   r$   r$   r$   r%   r      s   z# Translations template for PROJECT.
# Copyright (C) YEAR ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#c             C   sH   t | jd}i }x0|j D ]$\}}|jd}|jd}|||< qW |S )Nutf8)r   encodeitemsdecode)Zheader_stringheadersZdecoded_headersnamer"   r$   r$   r%   _parse_header   s    

r`   c               @   s  e Zd ZdZddeddddddddddfddZdd Zdd	 Zeeed
dZ	dd Z
dd Zee
eddZedd Zedd Zedd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zdf f f f f ddfd%d&Zd'd( Zd2d)d*Zd3d+d,Zd4d.d/Zd5d0d1ZdS )6r   z$Representation of a message catalog.NTc             C   s   || _ |rtj|}|| _|| _t | _|p.d| _|p8d| _|pBd| _	|pLd| _
|
pVd| _|p`d| _|pjd| _|dkrtjt}nt|tr|j r|jtd	}|| _|	dkrd
}	nt|	tr|	j r|	jtd	}	|	| _|| _t | _d| _d| _dS )aD  Initialize the catalog object.

        :param locale: the locale identifier or `Locale` object, or `None`
                       if the catalog is not bound to a locale (which basically
                       means it's a template)
        :param domain: the message domain
        :param header_comment: the header comment as string, or `None` for the
                               default header
        :param project: the project's name
        :param version: the project's version
        :param copyright_holder: the copyright holder of the catalog
        :param msgid_bugs_address: the email address or URL to submit bug
                                   reports to
        :param creation_date: the date the catalog was created
        :param revision_date: the date the catalog was revised
        :param last_translator: the name and email of the last translator
        :param language_team: the name and email of the language team
        :param charset: the encoding to use in the output (defaults to utf-8)
        :param fuzzy: the fuzzy bit on the catalog header
        PROJECTVERSIONORGANIZATIONzEMAIL@ADDRESSzFULL NAME <EMAIL@ADDRESS>zLANGUAGE <LL@li.org>zutf-8N)r   zYEAR-MO-DA HO:MI+ZONE)domainr	   parselocale_header_commentr   	_messagesprojectversioncopyright_holdermsgid_bugs_addresslast_translatorlanguage_teamcharsetr   nowr   r4   r   r!   creation_daterevision_daterO   obsolete_num_plurals_plural_expr)r8   rf   rd   header_commentri   rj   rk   rl   rq   rr   rm   rn   ro   rO   r$   r$   r%   r9      s6    







zCatalog.__init__c             C   sv   | j }tjtjd}t| jdr.| jjd}|jd| jjd| j	jd|jd| j
}| jrr|jdd| jj }|S )	Nz%Ystrftimera   rb   YEARrc   zTranslations templatez%s translations)rg   r   rp   r   rw   hasattrrr   r!   ri   rj   rk   rf   Zenglish_name)r8   ZcommentZyearr$   r$   r%   _get_header_comment0  s    

zCatalog._get_header_commentc             C   s
   || _ d S )N)rg   )r8   r*   r$   r$   r%   _set_header_comment>  s    zCatalog._set_header_commenta      The header comment for the catalog.

    >>> catalog = Catalog(project='Foobar', version='1.0',
    ...                   copyright_holder='Foo Company')
    >>> print(catalog.header_comment) #doctest: +ELLIPSIS
    # Translations template for Foobar.
    # Copyright (C) ... Foo Company
    # This file is distributed under the same license as the Foobar project.
    # FIRST AUTHOR <EMAIL@ADDRESS>, ....
    #

    The header can also be set from a string. Any known upper-case variables
    will be replaced when the header is retrieved again:

    >>> catalog = Catalog(project='Foobar', version='1.0',
    ...                   copyright_holder='Foo Company')
    >>> catalog.header_comment = '''\
    ... # The POT for my really cool PROJECT project.
    ... # Copyright (C) 1990-2003 ORGANIZATION
    ... # This file is distributed under the same license as the PROJECT
    ... # project.
    ... #'''
    >>> print(catalog.header_comment)
    # The POT for my really cool Foobar project.
    # Copyright (C) 1990-2003 Foo Company
    # This file is distributed under the same license as the Foobar
    # project.
    #

    :type: `unicode`
    )docc             C   sT  g }|j dd| j| jf f |j d| jf |j dt| jdddf t| jtt	ft
 rx|j dt| jdddf n|j d| jf |j d	| jf | jd k	r|j d
t| jf | jd k	rd| jkr|j d| jjdt| jf n|j d| jf | jd k	r|j d| jf |j d |j dd| j f |j d |j ddt f |S )NzProject-Id-Versionz%s %szReport-Msgid-Bugs-TozPOT-Creation-Datezyyyy-MM-dd HH:mmZZen)rf   zPO-Revision-DatezLast-TranslatorZLanguageZLANGUAGEzLanguage-TeamzPlural-FormsMIME-Version1.0zContent-Typeztext/plain; charset=%sContent-Transfer-Encoding8bitzGenerated-Byz	Babel %s
)r}   r~   )r   r   )rJ   ri   rj   rl   r
   rq   r4   rr   r   time_r   rm   rf   strrn   r!   plural_formsro   rb   )r8   r^   r$   r$   r%   _get_mime_headersb  s8    


zCatalog._get_mime_headersc             C   s>  x6|D ],\}}|j  }|dkrL|jd}dj|d d | _|d | _q|dkr\|| _q|dkrl|| _q|dkr|jdd}tj	|| _
q|d	kr|| _q|d
krt|\}}d|kr|d j  | _q|dkrtd| \}}t|jdd| _|jdd| _q|dkrt|| _q|dkrd|krt|| _qW d S )Nzproject-id-version r   zreport-msgid-bugs-tozlast-translatorZlanguage-_zlanguage-teamzcontent-typero   zplural-formsz ;Znpluralsr   Zpluralz(n != 1)zpot-creation-datezpo-revision-daterx   r   )lowersplitjoinri   rj   rl   rm   r!   r	   re   rf   rn   r   ro   r    getrt   ru   r&   rq   rr   )r8   r^   r_   r"   partsZmimetypeZparamsr   r$   r$   r%   _set_mime_headers  s8    


zCatalog._set_mime_headersa      The MIME headers of the catalog, used for the special ``msgid ""`` entry.

    The behavior of this property changes slightly depending on whether a locale
    is set or not, the latter indicating that the catalog is actually a template
    for actual translations.

    Here's an example of the output for such a catalog template:

    >>> from babel.dates import UTC
    >>> created = datetime(1990, 4, 1, 15, 30, tzinfo=UTC)
    >>> catalog = Catalog(project='Foobar', version='1.0',
    ...                   creation_date=created)
    >>> for name, value in catalog.mime_headers:
    ...     print('%s: %s' % (name, value))
    Project-Id-Version: Foobar 1.0
    Report-Msgid-Bugs-To: EMAIL@ADDRESS
    POT-Creation-Date: 1990-04-01 15:30+0000
    PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
    Last-Translator: FULL NAME <EMAIL@ADDRESS>
    Language-Team: LANGUAGE <LL@li.org>
    MIME-Version: 1.0
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: 8bit
    Generated-By: Babel ...

    And here's an example of the output when the locale is set:

    >>> revised = datetime(1990, 8, 3, 12, 0, tzinfo=UTC)
    >>> catalog = Catalog(locale='de_DE', project='Foobar', version='1.0',
    ...                   creation_date=created, revision_date=revised,
    ...                   last_translator='John Doe <jd@example.com>',
    ...                   language_team='de_DE <de@example.com>')
    >>> for name, value in catalog.mime_headers:
    ...     print('%s: %s' % (name, value))
    Project-Id-Version: Foobar 1.0
    Report-Msgid-Bugs-To: EMAIL@ADDRESS
    POT-Creation-Date: 1990-04-01 15:30+0000
    PO-Revision-Date: 1990-08-03 12:00+0000
    Last-Translator: John Doe <jd@example.com>
    Language: de_DE
    Language-Team: de_DE <de@example.com>
    Plural-Forms: nplurals=2; plural=(n != 1)
    MIME-Version: 1.0
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: 8bit
    Generated-By: Babel ...

    :type: `list`
    c             C   s.   | j dkr(d}| jr"t| jd }|| _ | j S )zThe number of plurals used by the catalog or locale.

        >>> Catalog(locale='en').num_plurals
        2
        >>> Catalog(locale='ga').num_plurals
        5

        :type: `int`Nr   r   )rt   rf   r   )r8   Znumr$   r$   r%   num_plurals  s    

zCatalog.num_pluralsc             C   s.   | j dkr(d}| jr"t| jd }|| _ | j S )a  The plural expression used by the catalog or locale.

        >>> Catalog(locale='en').plural_expr
        '(n != 1)'
        >>> Catalog(locale='ga').plural_expr
        '(n==1 ? 0 : n==2 ? 1 : n>=3 && n<=6 ? 2 : n>=7 && n<=10 ? 3 : 4)'

        :type: `string_types`Nz(n != 1)r   )ru   rf   r   )r8   exprr$   r$   r%   plural_expr  s    

zCatalog.plural_exprc             C   s   d| j | jf S )zReturn the plural forms declaration for the locale.

        >>> Catalog(locale='en').plural_forms
        'nplurals=2; plural=(n != 1)'
        >>> Catalog(locale='pt_BR').plural_forms
        'nplurals=2; plural=(n > 1)'

        :type: `str`znplurals=%s; plural=%s)r   r   )r8   r$   r$   r%   r     s    
zCatalog.plural_formsc             C   s   | j || jkS )z?Return whether the catalog has a message with the specified ID.)_key_forrh   )r8   r(   r$   r$   r%   __contains__  s    zCatalog.__contains__c             C   s
   t | jS )zeThe number of messages in the catalog.

        This does not include the special ``msgid ""`` entry.)lenrh   )r8   r$   r$   r%   __len__  s    zCatalog.__len__c             c   sz   g }x$| j D ]\}}|jd||f  qW t }| jrD|tdgO }tddj||dV  x| jD ]}| j| V  qbW dS )zIterates through all the entries in the catalog, in the order they
        were added, yielding a `Message` object for every entry.

        :rtype: ``iterator``z%s: %srO   r'   
)r.   N)mime_headersrJ   r-   rO   r   r   rh   )r8   Zbufr_   r"   r.   keyr$   r$   r%   __iter__  s    zCatalog.__iter__c             C   s*   d}| j rd| j  }dt| j| j|f S )Nr'   z %sz	<%s %r%s>)rf   r:   r;   rd   )r8   rf   r$   r$   r%   r<     s    
zCatalog.__repr__c             C   s   | j | dS )z)Delete the message with the specified ID.N)delete)r8   r(   r$   r$   r%   __delitem__!  s    zCatalog.__delitem__c             C   s
   | j |S )zUReturn the message with the specified ID.

        :param id: the message ID
        )r   )r8   r(   r$   r$   r%   __getitem__%  s    zCatalog.__getitem__c             C   s"  t |tstd| j||j}| jj|}|r|jrN|j rN|j|_|j	|_	t
t|j|j |_t
t|j|j |_t
t|j|j |_| j|jO  _|}nx|dkrt|j	j | _djdd |jD | _|j| _n>t |t
tfrt |j	t
tfstdt|j	 || j|< dS )a  Add or update the message with the specified ID.

        >>> catalog = Catalog()
        >>> catalog[u'foo'] = Message(u'foo')
        >>> catalog[u'foo']
        <Message u'foo' (flags: [])>

        If a message with that ID is already in the catalog, it is updated
        to include the locations and flags of the new message.

        >>> catalog = Catalog()
        >>> catalog[u'foo'] = Message(u'foo', locations=[('main.py', 1)])
        >>> catalog[u'foo'].locations
        [('main.py', 1)]
        >>> catalog[u'foo'] = Message(u'foo', locations=[('utils.py', 5)])
        >>> catalog[u'foo'].locations
        [('main.py', 1), ('utils.py', 5)]

        :param id: the message ID
        :param message: the `Message` object
        zexpected a Message objectr'   r   c             S   s   g | ]}d | j  qS )z# %s)rstrip)rS   cr$   r$   r%   
<listcomp>U  s    z'Catalog.__setitem__.<locals>.<listcomp>zExpected sequence but got %sN)r4   r   AssertionErrorr   r7   rh   r   r)   r(   r*   r+   r   r,   r2   r3   r.   r`   r\   r   r   rv   rO   rP   r:   )r8   r(   messager   Zcurrentr$   r$   r%   __setitem__,  s0    

zCatalog.__setitem__c
             C   s*   t ||t|||||||	d	}
|
| |< |
S )at  Add or update the message with the specified ID.

        >>> catalog = Catalog()
        >>> catalog.add(u'foo')
        <Message ...>
        >>> catalog[u'foo']
        <Message u'foo' (flags: [])>

        This method simply constructs a `Message` object with the given
        arguments and invokes `__setitem__` with that object.

        :param id: the message ID, or a ``(singular, plural)`` tuple for
                   pluralizable messages
        :param string: the translated message string, or a
                       ``(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 previous_id: the previous message ID, or a ``(singular, plural)``
                            tuple for pluralizable messages
        :param lineno: the line number on which the msgid line was found in the
                       PO file, if any
        :param context: the message context
        )r6   r7   )r   r+   )r8   r(   r*   r,   r.   r2   r3   r5   r6   r7   r   r$   r$   r%   r0   ^  s
    zCatalog.addc             c   s2   x,| j j D ]}|j| d}|r||fV  qW dS )aB  Run various validation checks on the translations in the catalog.

        For every message which fails validation, this method yield a
        ``(message, errors)`` tuple, where ``message`` is the `Message` object
        and ``errors`` is a sequence of `TranslationError` objects.

        :rtype: ``iterator``
        )rK   N)rh   valuesrN   )r8   r   rL   r$   r$   r%   rN     s    	zCatalog.checkc             C   s   | j j| j||S )zReturn the message with the specified ID and context.

        :param id: the message ID
        :param context: the message context, or ``None`` for no context
        )rh   r   r   )r8   r(   r7   r$   r$   r%   r     s    zCatalog.getc             C   s"   | j ||}|| jkr| j|= dS )zDelete the message with the specified ID and context.

        :param id: the message ID
        :param context: the message context, or ``None`` for no context
        N)r   rh   )r8   r(   r7   r   r$   r$   r%   r     s    
zCatalog.deleteFc                sD  j j t _ g }|s6tfddD }t   fdd}x|D ]}|jrTj|j|j}|kr|||| qT|dkrt|t	r|d }n|}t
|j j |j d}	|	r|	d }
||
 }|dk	r|
|f}
|||
| qT||j< qTW x,D ]$}|s| kr| j|< qW |r8|j_|j_dS )	a  Update the catalog based on the given template catalog.

        >>> from babel.messages import Catalog
        >>> template = Catalog()
        >>> template.add('green', locations=[('main.py', 99)])
        <Message ...>
        >>> template.add('blue', locations=[('main.py', 100)])
        <Message ...>
        >>> template.add(('salad', 'salads'), locations=[('util.py', 42)])
        <Message ...>
        >>> catalog = Catalog(locale='de_DE')
        >>> catalog.add('blue', u'blau', locations=[('main.py', 98)])
        <Message ...>
        >>> catalog.add('head', u'Kopf', locations=[('util.py', 33)])
        <Message ...>
        >>> catalog.add(('salad', 'salads'), (u'Salat', u'Salate'),
        ...             locations=[('util.py', 38)])
        <Message ...>

        >>> catalog.update(template)
        >>> len(catalog)
        3

        >>> msg1 = catalog['green']
        >>> msg1.string
        >>> msg1.locations
        [('main.py', 99)]

        >>> msg2 = catalog['blue']
        >>> msg2.string
        u'blau'
        >>> msg2.locations
        [('main.py', 100)]

        >>> msg3 = catalog['salad']
        >>> msg3.string
        (u'Salat', u'Salate')
        >>> msg3.locations
        [('util.py', 42)]

        Messages that are in the catalog but not in the template are removed
        from the main collection, but can still be accessed via the `obsolete`
        member:

        >>> 'head' in catalog
        False
        >>> list(catalog.obsolete.values())
        [<Message 'head' (flags: [])>]

        :param template: the reference catalog, usually read from a POT file
        :param no_fuzzy_matching: whether to use fuzzy matching of message IDs
        c                s.   g | ]&}|r | j rj| | jfqS r$   )r*   r   r7   )rS   msgid)messagesr8   r$   r%   r     s   z"Catalog.update.<locals>.<listcomp>c                s8  | j  } d}||krRd} j| j|}t|jtrD|jg| _q^t|j| _nj|d }|j	| _	t| jtt
frt| j	tt
fsd}t
| j	gdgt| jd   | _	n.t| j	jkrd}t
| j	d t|j	 | _	n"t| j	tt
fr d}| j	d | _	|  j|jO  _|r*|  jtdgO  _| | j< d S )NFTr'   r   r   rO   )rH   r0   r   r4   r(   r   r5   r+   popr*   rP   r   r   r.   r-   )r   ZoldkeynewkeyrO   Zoldmsg)fuzzy_matchesr   	remainingr8   r$   r%   _merge  s4    

"zCatalog.update.<locals>._mergeFr   r   N)rh   r   r   dictr-   r(   r   r7   r4   rP   r   r   stripkeysrs   rv   rq   )r8   templateZno_fuzzy_matchingZupdate_header_commentZfuzzy_candidatesr   r   r   ZmatchkeyZmatchesr   Znewctxtr   r$   )r   r   r   r8   r%   update  sF    5




zCatalog.updatec             C   s.   |}t |ttfr|d }|dk	r*||f}|S )zThe key for a message is just the singular ID even for pluralizable
        messages, but is a ``(msgid, msgctxt)`` tuple for context-specific
        messages.
        r   N)r4   r+   rP   )r8   r(   r7   r   r$   r$   r%   r   %  s    zCatalog._key_for)N)N)FF)N)r;   rV   rW   rX   DEFAULT_HEADERr9   rz   r{   rY   rv   r   r   r   r   r   r   r   r   r   r<   r   r   r   r0   rN   r   r   r   r   r$   r$   r$   r%   r      s@   8 12 



 )+rX   r   r   Zcgir   r   r   Zdifflibr   Zemailr   r   Zbabelr   rb   Z
babel.corer	   Zbabel.datesr
   Zbabel.messages.pluralsr   Z
babel.utilr   r   r   r   Zbabel._compatr   r   r   r   __all__compileVERBOSErQ   r&   objectr   	Exceptionr   r   r`   r   r$   r$   r$   r%   <module>
   s2   
	
  

