
    Xh                       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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jV                  dejX                        Z-d#dZ.d$dZ/ G d d      Z0 G d de1      Z2dZ3d%dZ4d&d'dZ5 G d  d!      Z6y)(z
    babel.messages.catalog
    ~~~~~~~~~~~~~~~~~~~~~~

    Data structures for message catalogs.

    :copyright: (c) 2013-2025 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FixedOffsetTimezone_cmpdistinct)	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           J/var/www/html/myenv/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6)==?f$779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_formatr7   P   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d  }}t        | d      }t        |      }	t        |      }
|	d	z  }||
z  }||z  }t        |      }|j                  |
      }|S )Nz+^(?P<datetime>.*?)(?P<tzoffset>[+-]\d{4})?$datetimez%Y-%m-%d %H:%Mtzoffsetr   r1      1<   tzinfo)rematchr9   strptimegroupintr   replace)valuerA   dtr:   plus_minus_sresthours_offset_smins_offset_s
plus_minushours_offsetmins_offsetnet_mins_offsets               r-   _parse_datetime_headerrP   c   s    HHCUKE				#	#EKK
$;=M	NB {{:&H%a[(12,d(,Ra$qr( L>+,
>*-( '+;&:% '7 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
                x   || _         |s| j                  rd}|| _        t        t	        |            | _        t        |      | _        |r(| j                  r| j                  j                  d       n| j                  j                  d       |r(| j                  r| j                  j                  d       n| j                  j                  d       t        t	        |            | _        t        t	        |            | _        t        |t              r	|g| _        nt        |      | _        || _        |	| _        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
        ) rT   zpython-formatzpython-brace-formatN)idpluralizabler3   listr   	locationssetflagspython_formatadddiscardpython_brace_formatauto_commentsuser_comments
isinstancestrprevious_idlinenocontext)
selfrU   r3   rX   rZ   r_   r`   rc   rd   re   s
             r-   __init__zMessage.__init__   s    8 $++Fhy12Z
$$$JJNN?+JJ/$**JJNN01JJ45!(="9:!(="9:k3' +}D#K0DrQ   c                z    dt        |       j                   d| j                  dt        | j                        dS )N< z	 (flags: z)>)type__name__rU   rW   rZ   rf   s    r-   __repr__zMessage.__repr__   s7    4:&&'q9T$**=M<PPRSSrQ   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   rT   )ra   r   rV   rU   re   )objs    r-   values_to_comparez*Message.__cmp__.<locals>.values_to_compare   sH    #w'C,<,<vvay#++"333663;;,",,rQ   )r   )rf   otherrr   s      r-   __cmp__zMessage.__cmp__   s"    	- %d+->u-EFFrQ   c                *    | j                  |      dkD  S Nr   rt   rf   rs   s     r-   __gt__zMessage.__gt__       ||E"Q&&rQ   c                *    | j                  |      dk  S rv   rw   rx   s     r-   __lt__zMessage.__lt__   rz   rQ   c                *    | j                  |      dk\  S rv   rw   rx   s     r-   __ge__zMessage.__ge__       ||E"a''rQ   c                *    | j                  |      dk  S rv   rw   rx   s     r-   __le__zMessage.__le__   r   rQ   c                *    | j                  |      dk(  S rv   rw   rx   s     r-   __eq__zMessage.__eq__   r   rQ   c                *    | j                  |      dk7  S rv   rw   rx   s     r-   __ne__zMessage.__ne__   r   rQ   c                X    t        |t              sJ | j                  |j                  k(  S )z[Checks whether messages are identical, taking into account all
        properties.
        )ra   r   __dict__rx   s     r-   is_identicalzMessage.is_identical   s'     %)))}}..rQ   c                    t        t        t        | j                  | j                  | j
                  | j                  | j                  | j                  | j                  | j                  | j                  f	       S N)r   mapr   rU   r3   rX   rZ   r_   r`   rc   rd   re   rm   s    r-   clonezMessage.clone   s^    D477DKK#'::t/A/A#'#5#5t7G7G#';;#> ? @ 	@rQ   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$   )rf   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rZ   rm   s    r-   r   zMessage.fuzzy   s     $**$$rQ   c                B    t        | j                  t        t        f      S )zWhether the message is plurizable.

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

        :type:  `bool`)ra   rU   rW   tuplerm   s    r-   rV   zMessage.pluralizable  s     $''D%=11rQ   c                p    | j                   }t        |t        t        f      s|g}t	        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              3  F   K   | ]  }t         j                  |        y wr   )r   search.0rU   s     r-   	<genexpr>z(Message.python_format.<locals>.<genexpr>  s     :=''+:s   !rU   ra   rW   r   anyrf   idss     r-   r[   zMessage.python_format  s3     gg#e}-%C:c:::rQ   c                p    | j                   }t        |t        t        f      s|g}t	        d |D              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`c              3  2   K   | ]  }t        |        y wr   )r7   r   s     r-   r   z.Message.python_brace_format.<locals>.<genexpr>+  s     >B+B/>s   r   r   s     r-   r^   zMessage.python_brace_format  s3     gg#e}-%C>#>>>rQ   )rT    r   r   r   r   NN)rU   r   r3   _MessageID | NonerX   Iterable[tuple[str, int]]rZ   Iterable[str]r_   r   r`   r   rc   r   rd   
int | Nonere   
str | NonereturnNoner   rb   )rs   objectr   rD   )rs   r   r   bool)rs   r   r   r   )r   r   r   )r   zCatalog | Noner   zlist[TranslationError])r   r   )rl   
__module____qualname____doc__rg   rn   rt   ry   r|   r~   r   r   r   r   r   r   propertyr   rV   r[   r^   r   rQ   r-   r   r      s   :
 %'/1!')')"$!"11 "1 -	1
 1 %1 %1  1 1 1 
1fTG''((((/@& % % 	2 	2 ; ; ? ?rQ   r   c                      e Zd ZdZy)r   z_Exception thrown by translation checkers when invalid message
    translations are encountered.N)rl   r   r   r   r   rQ   r-   r   r   .  s    %rQ   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   dict
get_params)rF   r   ms      r-   parse_separated_headerr   ;  s'    %	AAnrQ   c                    t        | t              r| S t        | t              r| j                  ||      S t        |       S r   )ra   rb   bytesdecode)r*   encodingr   s      r-   _force_textr   C  s5    !S!Uxx&))q6MrQ   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!d2d8d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charsetr9   nowr   ra   r?   rE   creation_daterevision_dater   obsolete_num_plurals_plural_expr)rf   r   r   header_commentr   r   r   r   r   r   r   r   r   r   s                 r-   rg   zCatalog.__init__N  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  rQ   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_localera   r   rb   r2   r   	TypeErrorrf   r   s     r-   _set_localezCatalog._set_locale  s    >&*D#DLff%&)&kD#!DLfc"&)&kD#$%||F3 ^_e^hijj	 & $#$s   B BBc                    | j                   S r   )r   rm   s    r-   _get_localezCatalog._get_locale  s    ||rQ   c                    | j                   S r   )r   rm   s    r-   _get_locale_identifierzCatalog._get_locale_identifier  s    &&&rQ   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   r9   r   r   r   hasattrr   rE   r   r   r   r   english_namelocale_identifier)rf   commentyearlocale_names       r-   _get_header_commentzCatalog._get_header_comment  s    &&  $$W-66t<4%%z2%%..t4D//)T\\:!')T\\:!'&$/!'.$2G2GH 	 48;;t{{//DDZDZoo&=+m?\]GrQ   c                    || _         y r   )r   )rf   r3   s     r-   _set_header_commentzCatalog._set_header_comment  s
    %rQ   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-Versionrj   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 
)ra   r   r9   timerD   floatr   r   r   rE   rb   r   r   r   r   r   r$   r   plural_formsr   r   )rf   r   r   headerss       r-   _get_mime_headerszCatalog._get_mime_headers  sz   d((8+<+<hmmSRW*XY+D,>,>@S\`aM ..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	
 	
 rQ   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-versionrj   zreport-msgid-bugs-tozlast-translatorlanguage-_zlanguage-teamr   r   zplural-formsz ;npluralsr;   plural(n != 1)zpot-creation-datezpo-revision-dater   )r   lowerr   splitjoinr   r   r   r   rE   r   r   r   rD   getr   r   rP   r   r   )rf   r   namerF   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rQ   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`r;   r   )r   r   r   )rf   nums     r-   num_pluralszCatalog.num_pluralsZ  sC     $C{{ -a0 #D   rQ   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  r1   )r   r   r   )rf   exprs     r-   plural_exprzCatalog.plural_exprk  sC     $D{{!$++.q1 $D   rQ   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  rm   s    r-   r   zCatalog.plural_forms~  s'     4++,Id6F6F5GqIIrQ   c                <    | j                  |      | j                  v S )z?Return whether the catalog has a message with the specified ID._key_forr   rf   rU   s     r-   __contains__zCatalog.__contains__  s    }}R DNN22rQ   c                ,    t        | j                        S )zeThe number of messages in the catalog.

        This does not include the special ``msgid ""`` entry.)lenr   rm   s    r-   __len__zCatalog.__len__  s     4>>""rQ   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   rT   r   r   N)mime_headersr$   rY   r   r   r  r   )rf   bufr  rF   rZ   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 )NrT   rj   ri   >)r   rk   rl   r   r   s     r-   rn   zCatalog.__repr__  sF    ;;&F4:&&'qxqAArQ   c                &    | j                  |       y)z)Delete the message with the specified ID.N)deleter  s     r-   __delitem__zCatalog.__delitem__  s    BrQ   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|rQ   c                B   t        |t              sJ d       | j                  ||j                        }| j                  j                  |      }|r|j                  r.|j                  s"|j                  |_        |j                  |_        t        t        |j                  |j                  z               |_        t        t        |j                  |j                  z               |_        t        t        |j                  |j                  z               |_        |xj                  |j                  z  c_        y|dk(  ryt        |j                        j!                         | _        dj%                  |j                  D cg c]  }d| j'                          c}      | _        |j*                  | _        yt        |t        t,        f      r=t        |j                  t        t,        f      sJ dt/        |j                                || j                  |<   yc c}w )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 objectrT   r   z# zExpected sequence but got N)ra   r   r  re   r   r  rV   rU   r3   rW   r   rX   r_   r`   rZ   r   itemsr  r  rstripr   r   r   rk   )rf   rU   messager  currentcs         r-   __setitem__zCatalog.__setitem__  s   , '7+H-HH+mmB0..$$S)##G,@,@$ZZ
!( $Xg.?.?.5.?.?/@ &A !BG$('2G2G292G2G3H *I %JG!$('2G2G292G2G3H *I %JG!MMW]]*M2X 3GNN C I I KD"&))H]H],^1r!X__->,^"_D DJ"tUm,!'..4-@ H0gnn1E0FGH@")DNN3 -_s   Hc
                J    t        ||t        |      ||||||		      }
|
| |<   |
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
        )rd   re   )r   rW   )rf   rU   r3   rX   rZ   r_   r`   rc   rd   re   r+  s              r-   r\   zCatalog.add  s7    J "fd9oum'V")+ RrQ   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   )rf   r+  r   s      r-   r   zCatalog.check  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  )rf   rU   re   s      r-   r  zCatalog.get  s$     ~~!!$--G"<==rQ   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  rf   rU   re   r  s       r-   r$  zCatalog.delete%  s1     mmB($.. s# !rQ   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', 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
        :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                D   | j                         } d}||k7  rpd}j                  |       j                  |      }|J t        |j                  t
              r|j                  g| _        n1t        |j                        | _        nj                  |d       }|J |j                  | _	        r#t        t        |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 )NFTrT   r1   r   r   )r   r\   r  ra   rU   rb   rc   rW   popr3   r   r`   r   r  r  rZ   )
r+  oldkeynewkeyr   oldmsgfuzzy_matcheskeep_user_commentsmessages	remainingrf   s
        r-   _mergezCatalog.update.<locals>._merge|  s   mmoGE!!&)!f-)))fii-+199+G'*.vyy/G'"vt4)))#]]GN!(,Xf6J6J-K(L%'**tUm4!'..4-@ E%* (RDC

Oa4G,HI&GN (D,<,<< E%*7>>:M3v}};M+N%OGNGNNT5M:!(!2MMV\\)M'*&DrQ   r1   r   N)r+  r   r8  tuple[str, str] | strr9  r@  r   r   )r   r   r3   r  re   _to_fuzzy_match_keyrY   rU   r.   keysr   r   r   )rf   templateno_fuzzy_matchingupdate_header_commentr<  update_creation_datefuzzy_candidatesmsgidr  ctxtr?  r+  matchesmodified_keyr9  newctxtr;  r=  r>  s   `   `           @@@r-   updatezCatalog.update/  s   ~ >>MMO	  ! RXe_33--.C#E?22DGJDk$T%=%=c%BC	R
 #	' #	'J   	/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  rQ   c                n    t        |t              r|d   }n|}|j                         j                         S )z?Converts a message key to a string suitable for fuzzy matching.r   )ra   r   r  strip)rf   r  matchkeys      r-   rA  zCatalog._to_fuzzy_match_key  s0    c5!1vHH~~%%''rQ   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   )ra   rW   r   r4  s       r-   r  zCatalog._key_for  s4    
 cD%=)Q%C.C
rQ   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)ra   r   r   rB  r  r   r   r  )rf   rs   r  	message_1	message_2s        r-   r   zCatalog.is_identical  s     %)))>>&&(5??+?+?+AA 	CI		#I!$ --i8	 D%%&$u/A/A*BBBrQ   )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   rU  r   r   )r   zLocale | None)r   r   r   )r3   r   r   r   )r   zlist[tuple[str, str]])r   zIterable[tuple[str, str]]r   r   )r   rD   )rU   r   r   r   )r   zIterator[Message])rU   r   r   r   )rU   r   r   r   )rU   r   r+  r   r   r   )Nr   r   r   r   r   NN)rU   r   r3   r   rX   r   rZ   r   r_   r   r`   r   rc   r   rd   r   re   r   r   r   )r   z0Iterable[tuple[Message, list[TranslationError]]]r   )rU   r   re   r   r   zMessage | None)rU   r   re   r   r   r   )FFTT)rC  r   rD  r   rE  r   r<  r   rF  r   r   r   )r  r@  r   rb   )rU   r   re   r   r   r@  )rs   r   r   r   )$rl   r   r   r   r   rg   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r   r  r  r   rn   r%  r'  r.  r\   r   r  r$  rM  rA  r  r   r   rQ   r-   r   r   K  s   . '+!%3""'+)-8<PT&*$("D!#D! D! #	D!
 D! D! %D! 'D! 6D! ND! $D! "D! D! D! 
D!Lk*' k;/F !78& 13F M 	NB<"GH -/@ 2G 2	Lh ! !  ! !$ 	J 	J3#&B.*f %)/1!')')"$!")) ") -	)
 ) %) %)  ) ) ) 
)V&>$ #(&+#'%)U8U8  U8  $	U8
 !U8 #U8 
U8n(
CrQ   r   )   g333333?)r3   rb   r   r   )rF   rb   r   zdatetime.datetime)rF   rb   r   zdict[str, str])r   strict)r*   zstr | bytesr   rb   r   rb   r   rb   )7r   
__future__r   r9   r@   collections.abcr   r   r   difflibr   emailr   heapqr	   r3   r
   typingr   babelr   r   
babel.corer   r   babel.datesr   babel.messages.pluralsr   
babel.utilr   r   r   r   typing_extensionsr   rb   r   rW   r   __annotations____all__r.   compileVERBOSEr   r7   rP   r   	Exceptionr   r   r   r   r   r   rQ   r-   <module>ri     s    #  	 .  # %     ( 1 ' - C C+%S/1DI=J	=&4 

 	 ZZ	&<j? j?Z%y %
 ]
C ]
CrQ   