
    1yi                       U d Z ddlmZ ddlZddl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 ddlmZ ddlmZ ddlmZmZ erddl m!Z! e"e#e"df   z  e$e"   z  Z%de&d<   g dZ'd"dZ( ejR                  dejT                        Z+d#dZ,d$dZ- G d d      Z. G d de/      Z0dZ1d%dZ2d&d'dZ3 G d  d!      Z4y)(z
babel.messages.catalog
~~~~~~~~~~~~~~~~~~~~~~

Data structures for message catalogs.

:copyright: (c) 2013-2026 by the Babel Team.
:license: BSD, see LICENSE for more details.
    )annotationsN)IterableIterator)copy)SequenceMatcher)message_from_string)nlargest)	Formatter)TYPE_CHECKING)__version__)LocaleUnknownLocaleError)format_datetime)
get_plural)LOCALTZ_cmp)	TypeAlias.r   
_MessageID)DEFAULT_HEADERPYTHON_FORMATCatalogMessageTranslationErrorc                   |dkD  st        d|      d|cxk  rdk  sn t        d|      g }t        d      }|j                  |        |D ]p  }|j                  |       |j	                         |k\  s(|j                         |k\  s<|j                         |k\  sP|j                  |j                         |f       r t        ||      }|D cg c]  \  }}|	 c}}S c c}}w )zA modified version of ``difflib.get_close_matches``.

    It just passes ``autojunk=False`` to the ``SequenceMatcher``, to work
    around https://github.com/python/cpython/issues/90825.
    r   zn must be > 0: g        g      ?zcutoff must be in [0.0, 1.0]: F)autojunk)	
ValueErrorr   set_seq2set_seq1real_quick_ratioquick_ratioratioappendr	   )wordpossibilitiesncutoffresultsxscores           X/var/www/html/content_weaver/venv/lib/python3.12/site-packages/babel/messages/catalog.pyget_close_matchesr,   +   s     q5?1%011&C9&DEEF'AJJt *	

1 F*6)	V#MM1779a.)* a F$%(%A%%%s   C$z
    \%
        (?:\(([\w]*)\))?
        (
            [-#0\ +]?(?:\*|[\d]+)?
            (?:\.(?:\*|[\d]+))?
            [hlL]?
        )
        ([diouxXeEfFgGcrs%])
c                    d| vryt               }	 d}|j                  |       D ]
  }|d   	d} 	 |S # t        $ r Y yw xY w)N{F   T)r
   parser   )stringfmtfield_name_seents       r+   _has_python_brace_formatr5   V   sc    
&
+C  6" 	'At"&	'   s   4 4 	A A c                   t        j                  d|       }t        j                  j                  |j	                  d      d      }|j	                  d      }||d   |dd  }}|d d |dd  }}t        | d      }t        |      }	t        |      }
|	d	z  }||
z  }||z  }t        j                  t        j                  |
      d|d      }|j                  |      }|S )Nz+^(?P<datetime>.*?)(?P<tzoffset>[+-]\d{4})?$datetimez%Y-%m-%d %H:%Mtzoffsetr   r/      1<   )minuteszEtc/GMTz+d)offsetnametzinfo)	rematchr7   strptimegroupinttimezone	timedeltareplace)valuerB   dtr8   plus_minus_sresthours_offset_smins_offset_s
plus_minushours_offsetmins_offsetnet_mins_offsets               r+   _parse_datetime_headerrS   i   s    HHCUKE				#	#EKK
$;=M	NB {{:&H%a[(12,d(,Ra$qr( L>+,
>*-( '+;&:% $$%%o>?2./
 ZZxZ(I    c                      e Zd ZdZ	 	 	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 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ZdddZedd       Zedd       Zedd       Zedd       Zy)r   z0Representation of a single message in a catalog.Nc
                   || _         |s| j                  rd}|| _        |rt        t        j                  |            ng | _        t        |      | _        |r(| j                  r| j                  j                  d       n| j                  j                  d       |r(| j                  r| j                  j                  d       n| j                  j                  d       |rt        t        j                  |            ng | _        |rt        t        j                  |            ng | _        |r*t        |t               r	|g| _        nt        |      | _        ng | _        || _        |	| _        y)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
        ) rW   zpython-formatzpython-brace-formatN)idpluralizabler1   listdictfromkeys	locationssetflagspython_formatadddiscardpython_brace_formatauto_commentsuser_comments
isinstancestrprevious_idlinenocontext)
selfrX   r1   r]   r_   rd   re   rh   ri   rj   s
             r+   __init__zMessage.__init__   s   8 $++F;DdmmI67"Z
$$$JJNN?+JJ/$**JJNN01JJ45CPT$--">?VXCPT$--">?VX+s+$/= #'#4 !DrT   c                z    dt        |       j                   d| j                  dt        | j                        dS )N< z	 (flags: z)>)type__name__rX   rZ   r_   rk   s    r+   __repr__zMessage.__repr__   s7    4:&&'q9T$**=M<PPRSSrT   c                8    d }t         ||        ||            S )z0Compare Messages, taking into account plural idsc                    t        | t              r+| j                  r| j                  d   | j                  xs dfS | j                  | j                  xs dfS )Nr   rW   )rf   r   rY   rX   rj   )objs    r+   values_to_comparez*Message.__cmp__.<locals>.values_to_compare   sH    #w'C,<,<vvay#++"333663;;,",,rT   )r   )rk   otherrw   s      r+   __cmp__zMessage.__cmp__   s"    	-
 %d+->u-EFFrT   c                *    | j                  |      dkD  S Nr   ry   rk   rx   s     r+   __gt__zMessage.__gt__       ||E"Q&&rT   c                *    | j                  |      dk  S r{   r|   r}   s     r+   __lt__zMessage.__lt__   r   rT   c                *    | j                  |      dk\  S r{   r|   r}   s     r+   __ge__zMessage.__ge__       ||E"a''rT   c                *    | j                  |      dk  S r{   r|   r}   s     r+   __le__zMessage.__le__   r   rT   c                *    | j                  |      dk(  S r{   r|   r}   s     r+   __eq__zMessage.__eq__   r   rT   c                *    | j                  |      dk7  S r{   r|   r}   s     r+   __ne__zMessage.__ne__   r   rT   c                X    t        |t              sJ | j                  |j                  k(  S )z[Checks whether messages are identical, taking into account all
        properties.
        )rf   r   __dict__r}   s     r+   is_identicalzMessage.is_identical   s'     %)))}}..rT   c                \   t        t        | j                        t        | j                        t        | j                        t        | j
                        t        | j                        t        | j                        t        | j                        | j                  | j                  	      S )N)	rX   r1   r]   r_   rd   re   rh   ri   rj   )r   r   rX   r1   r]   r_   rd   re   rh   ri   rj   rr   s    r+   clonezMessage.clone   sv    DGG}$4>>*tzz"t112t112T--.;;LL

 
	
rT   c                    ddl m} g }|D ]  }	  |||         |S # t        $ r}|j                  |       Y d}~0d}~ww xY w)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)babel.messages.checkersr   r   r"   )rk   catalogr   errorscheckeres         r+   checkzMessage.check   sR     	5)+ 	!G!&	!
  $ !a  !s   		A ;A c                    d| j                   v 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_   rr   s    r+   r   zMessage.fuzzy
  s     $**$$rT   c                B    t        | j                  t        t        f      S )zWhether the message is plurizable.

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

        :type:  `bool`)rf   rX   rZ   tuplerr   s    r+   rY   zMessage.pluralizable  s     $''D%=11rT   c                    | j                   }t        |t        t        f      r|D ]  }t        j                  |      s y yt        t        j                  |            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`TF)rX   rf   rZ   r   r   searchboolrk   idsrX   s      r+   r`   zMessage.python_format%  sV     ggcD%=)   ''+  M((-..rT   c                    | j                   }t        |t        t        f      r|D ]  }t	        |      s y yt	        |      S )zWhether the message contains Python f-string parameters.

        >>> Message('Hello, {name}!').python_brace_format
        True
        >>> Message(('One apple', '{count} apples')).python_brace_format
        True

        :type:  `bool`TF)rX   rf   rZ   r   r5   r   s      r+   rc   zMessage.python_brace_format7  sE     ggcD%=)  +B/  ',,rT   )rW    r   r   r   r   NN)rX   r   r1   _MessageID | Noner]   Iterable[tuple[str, int]]r_   Iterable[str]rd   r   re   r   rh   r   ri   
int | Nonerj   
str | NonereturnNoner   rg   )rx   objectr   rE   )rx   r   r   r   )rx   r   r   r   )r   r   N)r   zCatalog | Noner   zlist[TranslationError])r   r   )rq   
__module____qualname____doc__rl   rs   ry   r~   r   r   r   r   r   r   r   r   propertyr   rY   r`   rc   r   rT   r+   r   r      s   :
 %'/1!')')"$!"44 "4 -	4
 4 %4 %4  4 4 4 
4lTG''((((/
( % % 	2 	2 / /" - -rT   r   c                      e Zd ZdZy)r   z_Exception thrown by translation checkers when invalid message
    translations are encountered.N)rq   r   r   r   r   rT   r+   r   r   J  s    %rT   r   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                X    ddl m}  |       }| |d<   t        |j                               S )Nr   )r   content-type)email.messager   r[   
get_params)rI   r   ms      r+   parse_separated_headerr   W  s'    %	AAnrT   c                    t        | t              r| S t        | t              r| j                  ||      S t        |       S r   )rf   rg   bytesdecode)r(   encodingr   s      r+   _force_textr   `  s5    !S!Uxx&))q6MrT   c                     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d$dZ e	ee      Z
 e	e      Zd%dZd&d	Z e	eed
      Zd'dZd(dZ e	ee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/	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d0dZd1dZd2d3dZd2d4dZ	 	 	 	 d5	 	 	 	 	 	 	 	 	 	 	 d6dZ d7dZ!	 d2	 	 	 	 	 d8dZ"d9d Z#y):r   z$Representation of a message catalog.NTc                t   || _         || _        || _        i | _        |xs d| _        |xs d| _        |xs d| _        |xs d| _        |
xs d| _        	 |xs d| _	        	 |xs d| _
        |$t        j                  j                  t              }n<t        |t        j                        r"|j                  s|j!                  t        	      }|| _        |	d
}	n<t        |	t        j                        r"|	j                  s|	j!                  t        	      }	|	| _        || _        i | _        d| _        d| _        y)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>utf-8Nr?   zYEAR-MO-DA HO:MI+ZONE)domainlocale_header_comment	_messagesprojectversioncopyright_holdermsgid_bugs_addresslast_translatorlanguage_teamcharsetr7   nowr   rf   r@   rH   creation_daterevision_dater   obsolete_num_plurals_plural_expr)rk   r   r   header_commentr   r   r   r   r   r   r   r   r   r   s                 r+   rl   zCatalog.__init__k  s0   H -?A+)+) 0 BN"4"G.M2M<*D.D:)' $--11':Mx'8'89-BVBV)111AM* 3Mx'8'89-BVBV)111AM*
 ?A  rT   c                4   |d | _         d | _        y t        |t              rt	        |      | _         || _        y t        |t              r,t	        |      | _         	 t        j
                  |      | _        y t        d|      # t        $ r
 d | _        Y y w xY w)NzD`locale` must be a Locale, a locale identifier string, or None; got )_locale_identifier_localerf   r   rg   r0   r   	TypeErrorrk   r   s     r+   _set_localezCatalog._set_locale  s    >&*D#DLff%&)&kD#!DLfc"&)&kD#$%||F3 RSYR\]
 	
	 & $#$s   B BBc                    | j                   S r   )r   rr   s    r+   _get_localezCatalog._get_locale  s    ||rT   c                    | j                   S r   )r   rr   s    r+   _get_locale_identifierzCatalog._get_locale_identifier  s    &&&rT   c                .   | j                   }t        j                  j                  t              j	                  d      }t        | j                  d      r| j                  j	                  d      }|j                  d| j                        j                  d| j                        j                  d|      j                  d| j                        }| j                  r| j                  j                  n| j                  }|r|j                  d| d      }|S )	Nz%Ystrftimer   r   YEARr   zTranslations templatez translations)r   r7   r   r   r   hasattrr   rH   r   r   r   r   english_namelocale_identifier)rk   commentyearlocale_names       r+   _get_header_commentzCatalog._get_header_comment  s    &&  $$W-66t<4%%z2%%..t4DOOIt||4WY-WVT"W^T%:%:;	 	 37++dkk..4CYCYoo&=+m?\]GrT   c                    || _         y r   )r   )rk   r1   s     r+   _set_header_commentzCatalog._set_header_comment  s
    %rT   a      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                   t        | j                  t        j                  t        j                  t        t
        f      rt        | j                  dd      }n| j                  }| j                  }| j                  r)d|v r%|j                  dt        | j                              }d| j                   d| j                   fd| j                  fdt        | j                  dd      fd	|fd
| j                  fg}| j                  r&|j!                  dt        | j                        f       |j!                  d|f       | j"                  |j!                  d| j$                  f       |ddd| j&                   fdddt(         dfgz  }|S )Nzyyyy-MM-dd HH:mmZen)r   LANGUAGEzProject-Id-Versionro   zReport-Msgid-Bugs-TozPOT-Creation-DatezPO-Revision-DatezLast-TranslatorLanguagezLanguage-TeamzPlural-Forms)zMIME-Versionz1.0zContent-Typeztext/plain; charset=)zContent-Transfer-Encoding8bitzGenerated-ByzBabel 
)rf   r   r7   timerE   floatr   r   r   rH   rg   r   r   r   r   r   r"   r   plural_formsr   r   )rk   r   r   headerss       r+   _get_mime_headerszCatalog._get_mime_headers	  s   d((8+<+<hmmSRW*XY+""#M !..M**!!jM&A)11*c$BXBX>YZM "dll^1T\\N#CD#T%<%<= /$2D2DFYbf"gh/ 4 45*
 !!NNJD,B,B(CDE78;;"NNND,=,=>?#3DLL>BC1vgYb12	
 	
 rT   c                   |D ]~  \  }}t        |j                         | j                        }t        || j                        }|dk(  r5|j                  d      }dj	                  |d d       | _        |d   | _        }|dk(  r|| _        |dk(  r|| _        |dk(  r(|j                  dd	      }| j                  |xs d        |d
k(  r|| _        |dk(  r)t        |      }d|v s|d   j                         | _        |dk(  rGt        d|       }t        |j                  dd            | _        |j                  dd      | _        K|dk(  rt#        |      | _        b|dk(  sid|vsot#        |      | _         y )N)r   zproject-id-versionro   zreport-msgid-bugs-tozlast-translatorlanguage-_zlanguage-teamr   r   zplural-formsz ;npluralsr9   plural(n != 1)zpot-creation-datezpo-revision-dater   )r   lowerr   splitjoinr   r   r   r   rH   r   r   r   rE   getr   r   rS   r   r   )rk   r   r>   rI   partsparamss         r+   _set_mime_headerszCatalog._set_mime_headers+  sz   " !	GKD%tzz|dllCD=E++C("xxcr
3$Ry//*/'**',$#c3/
   $/(%*"'/6&#))#4#:#:#<DL'/"UG=$'

:q(A$B!$*JJx$D!,,%;E%B"++&)?)FD&C!	GrT   a      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
    >>> from datetime import datetime
    >>> 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                    | j                   -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`r9   r   )r   r   r   )rk   nums     r+   num_pluralszCatalog.num_plurals  sC     $C{{ -a0 #D   rT   c                    | j                   -d}| j                  rt        | j                        d   }|| _         | j                   S )aW  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)'
        >>> Catalog(locale='ding').plural_expr  # unknown locale
        '(n != 1)'

        :type: `str`r   r/   )r   r   r   )rk   exprs     r+   plural_exprzCatalog.plural_expr  sC     $D{{!$++.q1 $D   rT   c                <    d| j                    d| j                   d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=z	; plural=;)r	  r  rr   s    r+   r   zCatalog.plural_forms  s'     4++,Id6F6F5GqIIrT   c                <    | j                  |      | j                  v S )z?Return whether the catalog has a message with the specified ID._key_forr   rk   rX   s     r+   __contains__zCatalog.__contains__  s    }}R DNN22rT   c                ,    t        | j                        S )zeThe number of messages in the catalog.

        This does not include the special ``msgid ""`` entry.)lenr   rr   s    r+   __len__zCatalog.__len__  s     4>>""rT   c              #    K   g }| j                   D ]  \  }}|j                  | d|         t               }| j                  r|dhz  }t	        ddj                  |      |       | j                  D ]  }| j                  |     yw)zIterates through all the entries in the catalog, in the order they
        were added, yielding a `Message` object for every entry.

        :rtype: ``iterator``z: r   rW   r   r   N)mime_headersr"   r^   r   r   r  r   )rk   bufr>   rI   r_   keys         r+   __iter__zCatalog.__iter__  s     
 ,, 	+KD%JJ$r%)*	+::gYEb$))C.66>> 	&C..%%	&s   BBc                    d}| j                   rd| j                    }dt        |       j                   d| j                  | dS )NrW   ro   rn   >)r   rp   rq   r   r   s     r+   rs   zCatalog.__repr__  sF    ;;&F4:&&'qxqAArT   c                &    | j                  |       y)z)Delete the message with the specified ID.N)deleter  s     r+   __delitem__zCatalog.__delitem__  s    BrT   c                $    | j                  |      S )zUReturn the message with the specified ID.

        :param id: the message ID
        )r  r  s     r+   __getitem__zCatalog.__getitem__  s    
 xx|rT   c                L   t        |t              sJ d       | j                  ||j                        }| j                  j                  |      }|r|j                  r.|j                  s"|j                  |_        |j                  |_        t        t        j                  g |j                  |j                              |_        t        t        j                  g |j                  |j                              |_        t        t        j                  g |j                  |j                              |_        |xj                  |j                  z  c_        y|dk(  rat!        |j                        j#                         | _        dj'                  d |j                  D              | _        |j*                  | _        yt        |t        t,        f      r=t        |j                  t        t,        f      sJ dt/        |j                                || j                  |<   y)a  Add or update the message with the specified ID.

        >>> catalog = Catalog()
        >>> catalog['foo'] = Message('foo')
        >>> catalog['foo']
        <Message '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['foo'] = Message('foo', locations=[('main.py', 1)])
        >>> catalog['foo'].locations
        [('main.py', 1)]
        >>> catalog['foo'] = Message('foo', locations=[('utils.py', 5)])
        >>> catalog['foo'].locations
        [('main.py', 1), ('utils.py', 5)]

        :param id: the message ID
        :param message: the `Message` object
        zexpected a Message objectrW   r   c              3  B   K   | ]  }d | j                           yw)z# N)rstrip).0cs     r+   	<genexpr>z&Catalog.__setitem__.<locals>.<genexpr>  s     +]!bHOO,=+]s   zExpected sequence but got N)rf   r   r  rj   r   r  rY   rX   r1   rZ   r[   r\   r]   rd   re   r_   r   itemsr  r  r   r   r   rp   )rk   rX   messager  currents        r+   __setitem__zCatalog.__setitem__  s   , '7+H-HH+mmB0..$$S)##G,@,@$ZZ
!( $T]]3[W5F5F3[IZIZ3[%\ ]G$(7g9N9N7gQXQfQf7g)h$iG!$(7g9N9N7gQXQfQf7g)h$iG!MMW]]*M2X 3GNN C I I KD"&))+]wG\G\+]"]D DJ"tUm,!'..4-@ 0gnn1E0FG@ #*DNN3rT   c
                J    t        ||t        |      ||||||		      }
|
| |<   |
S )aq  Add or update the message with the specified ID.

        >>> catalog = Catalog()
        >>> catalog.add('foo')
        <Message ...>
        >>> catalog['foo']
        <Message '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
        )ri   rj   )r   rZ   )rk   rX   r1   r]   r_   rd   re   rh   ri   rj   r*  s              r+   ra   zCatalog.add  s>    J O

 RrT   c              #     K   | j                   j                         D ]  }|j                  |       }|s||f  yw)a\  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: ``generator`` of ``(message, errors)``
        )r   N)r   valuesr   )rk   r*  r   s      r+   r   zCatalog.checkB  sA      ~~,,. 	&G]]4]0Fvo%	&s   2>	>c                X    | 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
        )r   r  r  )rk   rX   rj   s      r+   r  zCatalog.getP  s$     ~~!!$--G"<==rT   c                `    | j                  ||      }|| j                  v r| j                  |= yy)zDelete the message with the specified ID and context.

        :param id: the message ID
        :param context: the message context, or ``None`` for no context
        Nr  rk   rX   rj   r  s       r+   r  zCatalog.deleteX  s1     mmB($.. s# !rT   c                
     j                   j                         i  _         i }|sPD ]K  }|s|   j                  s j                  |      }|   j                  }	||	f| j                  |      <   M t               	 	 	 	 	 	 	 	 d fd}
|D ]  }|j                  s j                  |j                  |j                        }|v r |
|||       E|sJt         j                  |      |j                         d      }|r|d   }||   \  }}|||f} |
|||       | |j                  <    D ]  }|s|vs
|    j                  |<    |r|j                   _        |r|j                   _        yy)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', 'blau', locations=[('main.py', 98)])
        <Message ...>
        >>> catalog.add('head', 'Kopf', locations=[('util.py', 33)])
        <Message ...>
        >>> catalog.add(('salad', 'salads'), ('Salat', '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
        'blau'
        >>> msg2.locations
        [('main.py', 100)]

        >>> msg3 = catalog['salad']
        >>> msg3.string
        ('Salat', '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
        :param update_header_comment: whether to copy the header comment from the template
        :param keep_user_comments: whether to keep user comments from the old catalog
        :param update_creation_date: whether to copy the creation date from the template
        c                p   | j                         } d}||k7  rpd}j                  |       j                  |      }|J t        |j                  t
              r|j                  g| _        n1t        |j                        | _        nj                  |d       }|J |j                  | _	        r9|j                  r-t        t        j                  |j                              | _
        t        | j                  t        t        f      rt        | j                  t        t        f      s;d}t        | j                  gdgt        | j                        dz
  z  z         | _	        nt        | j                        	j                  k7  rid}t        | j                  d t        |j                               | _	        n6t        | j                  t        t        f      rd}| j                  d   | _	        | xj                   |j                   z  c_        |r| xj                   dhz  c_        | 	| j                  <   y )NFTrW   r/   r   r   )r   ra   r  rf   rX   rg   rh   rZ   popr1   re   r[   r\   r   r  r	  r_   )
r*  oldkeynewkeyr   oldmsgfuzzy_matcheskeep_user_commentsmessages	remainingrk   s
        r+   _mergezCatalog.update.<locals>._merge  s   
 mmoGE!!&)!f-)))fii-+199+G'*.vyy/G'"vt4)))#]]GN!f&:&:(,T]]6;O;O-P(Q%'**tUm4!'..4-@ E%* (RDC

Oa4G,HI&GN (D,<,<< E%*7>>:NC<N+O%PGNGNNT5M:!(!2MMV\\)M'*&DrT   r/   r   N)r*  r   r6  tuple[str, str] | strr7  r>  r   r   )r   r   r1   r  rj   _to_fuzzy_match_keyr^   rX   r,   keysr   r   r   )rk   templateno_fuzzy_matchingupdate_header_commentr:  update_creation_datefuzzy_candidatesmsgidr  ctxtr=  r*  matchesmodified_keyr7  newctxtr9  r;  r<  s   `   `           @@@r+   updatezCatalog.updateb  s   ~ >>MMO	  ! RXe_33--.C#E?22DGJDk$T%=%=c%BC	R
 '	''	')'	' *'	' 	'	' '	'R   	/GzzmmGJJ@(?7C-,"3 44S9,113#
 #+21:L.>|.LOFG&2)/"7FC8$'.D$+	/.  	8E E$>'0'7e$	8 ! #+"9"9D  !)!7!7D  rT   c                n    t        |t              r|d   }n|}|j                         j                         S )z?Converts a message key to a string suitable for fuzzy matching.r   )rf   r   r   strip)rk   r  matchkeys      r+   r?  zCatalog._to_fuzzy_match_key  s0    c5!1vHH~~%%''rT   c                L    |}t        |t        t        f      r|d   }|||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   )rf   rZ   r   r2  s       r+   r  zCatalog._key_for  s4     cD%=)Q%C.C
rT   c                b   t        |t              sJ | j                  j                         |j                  j                         z  D ];  }| j	                  |      }|j	                  |      }|||j                  |      r; y t        | j                        t        |j                        k(  S )z\Checks if catalogs are identical, taking into account messages and
        headers.
        F)rf   r   r   r@  r  r   r[   r  )rk   rx   r  	message_1	message_2s        r+   r   zCatalog.is_identical  s     %)))>>&&(5??+?+?+AA 	CI		#I I$5Y=S=ST]=^		
 D%%&$u/A/A*BBBrT   )r   Locale | str | Noner   r   r   r   r   r   r   r   r   r   r   r   r   zdatetime.datetime | str | Noner   z6datetime.datetime | datetime.time | float | str | Noner   r   r   r   r   r   r   r   r   r   )r   rS  r   r   )r   zLocale | None)r   r   r   )r1   r   r   r   )r   zlist[tuple[str, str]])r   zIterable[tuple[str, str]]r   r   )r   rE   )rX   r   r   r   )r   zIterator[Message])rX   r   r   r   )rX   r   r   r   )rX   r   r*  r   r   r   )Nr   r   r   r   r   NN)rX   r   r1   r   r]   r   r_   r   rd   r   re   r   rh   r   ri   r   rj   r   r   r   )r   z0Iterable[tuple[Message, list[TranslationError]]]r   )rX   r   rj   r   r   zMessage | None)rX   r   rj   r   r   r   )FFTT)rA  r   rB  r   rC  r   r:  r   rD  r   r   r   )r  r>  r   rg   )rX   r   rj   r   r   r>  )rx   r   r   r   )$rq   r   r   r   r   rl   r   r   r   r   r   r   r   r   r   r   r  r  r	  r  r   r  r  r  rs   r   r"  r,  ra   r   r  r  rK  r?  r  r   r   rT   r+   r   r   h  s   . '+!%3""'+)-8<PT&*$("D!#D! D! #	D!
 D! D! %D! 'D! 6D! ND! $D! "D! D! D! 
D!L
.' k;/F !78 & #NJ D"GH 26Lp ! !  ! !$ 	J 	J3#&B,*b %)/1!')')"$!"11 "1 -	1
 1 %1 %1  1 1 1 
1f&>$ #(&+#'%)Y8Y8  Y8  $	Y8
 !Y8 #Y8 
Y8v( #  
	 
CrT   r   )   g333333?)r1   rg   r   r   )rI   rg   r   zdatetime.datetime)rI   rg   r   zdict[str, str])r   strict)r(   zstr | bytesr   rg   r   rg   r   rg   )5r   
__future__r   r7   rA   collections.abcr   r   r   difflibr   emailr   heapqr	   r1   r
   typingr   babelr   r   
babel.corer   r   babel.datesr   babel.messages.pluralsr   
babel.utilr   r   typing_extensionsr   rg   r   rZ   r   __annotations____all__r,   compileVERBOSEr   r5   rS   r   	Exceptionr   r   r   r   r   r   rT   r+   <module>rg     s    #  	 .  # %     ( 1 ' - $+%S/1DI=J	=&8 

	 JJ&B}- }-@%y %
 w
C w
CrT   