o
    ej                     @   s  d Z ddl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 dd	lmZ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 ddlmZ ddl m!Z! eG dd dZ"dVdWddZ#G dd dZ$deeef fddZ%dee fddZ&dee fddZ'dd Z(edd Z)dee* fd d!Z+d"d# Z,d$d% Z-dXd'd(Z.dXd)d*Z/dXd+d,Z0	-	/dYd0e*fd1d2Z1d3d4 Z2de*fd5d6Z3dVde*fd7d8Z4	&	9dZde*fd:d;Z5dVde*fd<d=Z6dVde*fd>d?Z7G d@dA dAe8Z9dee fdBdCZ:de9fdDdEZ;de*fdFdGZ<e<Z=de*fdHdIZ>de*fdJdKZ?de*fdLdMZ@de!fdNdOZAde!fdPdQZBde!fdRdSZCde!fdTdUZDdS )[u   
    flask_babel
    ~~~~~~~~~~~

    Implements i18n/l10n support for Flask applications based on Babel.

    :copyright: (c) 2013 by Armin Ronacher, Daniel Neuhäuser.
    :license: BSD, see LICENSE for more details.
    N)	dataclass)SimpleNamespacedatetime)contextmanager)ListCallableOptionalUnion)TranslationsNullTranslations)current_appg)locked_cached_property)datesnumberssupportLocale)timezoneUTC)ImmutableDict)
LazyStringc                   @   sj   e Zd ZU dZeed< eed< eed< ee ed< ee ed< ded< d	Zee	 ed
< d	Z
ee	 ed< d	S )BabelConfigurationz-Application-specific configuration for Babel.default_localedefault_timezonedefault_domaindefault_directoriestranslation_directoriesBabelinstanceNlocale_selectortimezone_selector)__name__
__module____qualname____doc__str__annotations__r   r    r	   r   r!    r(   r(   DD:\Projects\ConvertPro\env\Lib\site-packages\flask_babel/__init__.pyr      s   
 r   returnc                 C   s"   | pt } t| dsi | _| jd S )N
extensionsbabel)r   hasattrr+   )appr(   r(   r)   	get_babel*   s   

r/   c                   @   s   e Zd ZdZeddddddddddddddddZdddZ			
		dddZdd Ze	de
fddZe	defddZe	defddZedd Zeddee fddZdS )r   zCentral controller class that can be used to configure how
    Flask-Babel behaves.  Each application that wants to use Flask-Babel
    has to create, or run :meth:`init_app` on, an instance of this class
    after the configuration was initialized.
    mediumN)timedater   z
time.shortztime.mediumz	time.fullz	time.longz
date.shortzdate.mediumz	date.fullz	date.longzdatetime.shortzdatetime.mediumzdatetime.fullzdatetime.longTc                 O   s4   || _ || _|dur| j|g|R i | dS dS )zCreates a new Babel instance.

        If an application is passed, it will be configured with the provided
        arguments. Otherwise, :meth:`init_app` can be used to configure the
        application later.
        N)_configure_jinjadate_formatsinit_app)selfr.   r4   Zconfigure_jinjaargskwargsr(   r(   r)   __init__J   s
   zBabel.__init__enmessagestranslationsr   c           	      C   s   t |dsi |_|jd|d}t|jd||jd||jd||t| ||| ||d|jd< | jd	u rA| j	
 | _| jro|jjjtttttttttd
	 |jd |jjdd dd ddd dd d d	S d	S )a]  
        Initializes the Babel instance for use with this specific application.

        :param app: The application to configure
        :param default_locale: The default locale to use for this application
        :param default_domain: The default domain to use for this application
        :param default_translation_directories: The default translation
                                                directories to use for this
                                                application
        :param default_timezone: The default timezone to use for this
                                 application
        :param locale_selector: The function to use to select the locale
                                for a request
        :param timezone_selector: The function to use to select the
                                  timezone for a request
        r+   ZBABEL_TRANSLATION_DIRECTORIES;ZBABEL_DEFAULT_LOCALEZBABEL_DEFAULT_TIMEZONEZBABEL_DOMAIN)r   r   r   r   r   r   r    r!   r,   N)	ZdatetimeformatZ
dateformatZ
timeformatZtimedeltaformatZnumberformatZdecimalformatZcurrencyformatZpercentformatZscientificformatzjinja2.ext.i18nc                 S   s   t  | S Nget_translationsZugettext)sr(   r(   r)   <lambda>   s    z Babel.init_app.<locals>.<lambda>c                 S   s   t  | ||S r>   )r@   	ungettext)rA   pnr(   r(   r)   rB      s    Tc                 S   s   t  | |S r>   r@   Z	upgettext)crA   r(   r(   r)   rB      s    c                 S   s   t  | |||S r>   )r@   
unpgettext)rG   rA   rD   rE   r(   r(   r)   rB      s    )gettextngettextZnewstylepgettext	npgettext)r-   r+   configgetsplitr   list_resolve_directoriesr4   default_date_formatscopyr3   Z	jinja_envfiltersupdateformat_datetimeformat_dateformat_timeformat_timedeltaformat_numberformat_decimalformat_currencyformat_percentformat_scientificadd_extensionZinstall_gettext_callables)	r6   r.   r   r   Zdefault_translation_directoriesr   r    r!   directoriesr(   r(   r)   r5   X   sh   


!
zBabel.init_appc                 C   s   g }t  jD ]4}tj|sqt|D ]%}tj||d}tj|s%qtdd t|D r9|t	
| qq| j|vrF|| j |S )a>  Returns a list of all the locales translations exist for. The list
        returned will be filled with actual locale objects and not just strings.

        .. note::

            The default locale will always be returned, even if no translation
            files exist for it.

        .. versionadded:: 0.6
        LC_MESSAGESc                 s   s    | ]}| d V  qdS )z.moN)endswith).0xr(   r(   r)   	<genexpr>   s    z*Babel.list_translations.<locals>.<genexpr>)r/   r   ospathisdirlistdirjoinanyappendr   parser   )r6   resultdirnamefolderZ
locale_dirr(   r(   r)   list_translations   s   
zBabel.list_translationsr*   c                 C   s   t t jS )zeThe default locale from the configuration as an instance of a
        `babel.Locale` object.
        )r   rm   r/   r   r6   r(   r(   r)   r      s   zBabel.default_localec                 C   s   t t jS )zhThe default timezone from the configuration as an instance of a
        `pytz.timezone` object.
        )r   r/   r   rr   r(   r(   r)   r      s   zBabel.default_timezonec                 C   s   t  jS )z=The message domain for the translations as a string.
        )r/   r   rr   r(   r(   r)   domain   s   zBabel.domainc                 C   s   t | jdS )z1The message domain for the translations.
        )rs   )Domainrs   rr   r(   r(   r)   domain_instance   s   zBabel.domain_instancer`   c                 c   s>    | D ]}t j|r|V  q|d urt j|j|V  qd S r>   )rf   rg   isabsrj   	root_path)r`   r.   rg   r(   r(   r)   rQ      s   zBabel._resolve_directoriesNNT)r:   r;   r<   r   NNr>   )r"   r#   r$   r%   r   rR   r9   r5   rq   propertyr   r   r   r   r&   rs   r   ru   staticmethodr   rQ   r(   r(   r(   r)   r   1   sH    

W
r   c                   C   s
   t   S )zReturns the correct gettext translations that should be used for
    this request.  This will never fail and return a dummy translation
    object if used outside the request or if a translation cannot be found.
    )
get_domainr@   r(   r(   r(   r)   r@      s   
r@   c                  C   sn   t  } | du r	dS t| dd}|du r5t }|jdu r |jj}n| }|du r-|jj}nt|}|| _|S )zReturns the locale that should be used for this request as
    `babel.Locale` object.  This returns `None` if used outside a request.
    Nbabel_locale)	_get_current_contextgetattrr/   r    r   r   r   rm   r|   )ctxlocaler,   rvr(   r(   r)   
get_locale   s   



r   c                  C   sn   t  } t| dd}|du r5t }|jdu r|jj}n| }|du r'|jj}nt|tr0t|n|}|| _	|S )zReturns the timezone that should be used for this request as
    a `pytz.timezone` object.  This returns `None` if used outside a request.
    babel_tzinfoN)
r}   r~   r/   r!   r   r   
isinstancer&   r   r   )r   tzinfor,   r   r(   r(   r)   get_timezone  s   


r   c                  C   s>   t  } dD ]}t| |rt| | qt| dr| j| _dS dS )a  Refreshes the cached timezones and locale information.  This can
    be used to switch a translation between a request and if you want
    the changes to take place immediately, not just with the next request::

        user.timezone = request.form['timezone']
        user.locale = request.form['locale']
        refresh()
        flash(gettext('Language was changed'))

    Without that refresh, the :func:`~flask.flash` function would probably
    return English text and a now German page.
    )r|   r   babel_translationsforced_babel_localeN)r}   r-   delattrr   r|   )r   keyr(   r(   r)   refresh%  s   


r   c                 c   s    t  }|du rdV  dS i }dD ]
}t||d||< qz)t| |_|j|_d|_dV  W t|dr5|`| D ]
\}}t	||| q9dS t|drM|`| D ]
\}}t	||| qQw )a  Temporarily overrides the currently selected locale.

    Sometimes it is useful to switch the current locale to different one, do
    some tasks and then revert back to the original one. For example, if the
    user uses German on the website, but you want to email them in English,
    you can use this function as a context manager::

        with force_locale('en_US'):
            send_email(gettext('Hello!'), ...)

    :param locale: The locale to temporary switch to (ex: 'en_US').
    N)r   r|   r   )
r}   r~   r   rm   r|   r   r   r-   itemssetattr)r   r   Z
orig_attrsr   valuer(   r(   r)   force_locale;  s.   

r   c                 C   sF   t  }|du r|jj|  }|dv r!|jjd| |f  }|dur!|}|S )zmA small helper for the datetime formatting functions.  Looks up
    format defaults for different kinds.
    N)Zshortr0   fulllongz%s.%s)r/   r   r4   )r   formatr,   r   r(   r(   r)   _get_format_  s   r   c                 C   s,   | j du r| jtd} t }|| |S )a2  Convert a datetime object to the user's timezone.  This automatically
    happens on all date formatting unless rebasing is disabled.  If you need
    to convert a :class:`datetime.datetime` object at any time to the user's
    timezone (as returned by :func:`get_timezone`) this function can be used.
    Nr   )r   replacer   r   	normalize
astimezone)r   r   r(   r(   r)   to_user_timezonem  s   
r   c                 C   s(   | j du rt | } | tjddS )zwConvert a datetime object to UTC and drop tzinfo.  This is the
    opposite operation to :func:`to_user_timezone`.
    Nr   )r   r   localizer   r   r   r   r(   r(   r)   to_utcy  s   
r   Tc                 C      t d|}ttj| ||S )a  Return a date formatted according to the given pattern.  If no
    :class:`~datetime.datetime` object is passed, the current time is
    assumed.  By default, rebasing happens, which causes the object to
    be converted to the user's timezone (as returned by
    :func:`to_user_timezone`).  This function formats both date and
    time.

    The format parameter can either be ``'short'``, ``'medium'``,
    ``'long'`` or ``'full'`` (in which case the language's default for
    that setting is used, or the default from the :attr:`Babel.date_formats`
    mapping is used) or a format string as documented by Babel.

    This function is also available in the template context as filter
    named `datetimeformat`.
    r   )r   _date_formatr   rV   )r   r   rebaser(   r(   r)   rV     s   
rV   c                 C   s0   |rt | trt| } td|}ttj| ||S )a  Return a date formatted according to the given pattern.  If no
    :class:`~datetime.datetime` or :class:`~datetime.date` object is passed,
    the current time is assumed.  By default, rebasing happens, which causes
    the object to be converted to the users's timezone (as returned by
    :func:`to_user_timezone`).  This function only formats the date part
    of a :class:`~datetime.datetime` object.

    The format parameter can either be ``'short'``, ``'medium'``,
    ``'long'`` or ``'full'`` (in which case the language's default for
    that setting is used, or the default from the :attr:`Babel.date_formats`
    mapping is used) or a format string as documented by Babel.

    This function is also available in the template context as filter
    named `dateformat`.
    r2   )r   r   r   r   r   r   rW   )r2   r   r   r(   r(   r)   rW     s   
rW   c                 C   r   )a  Return a time formatted according to the given pattern.  If no
    :class:`~datetime.datetime` object is passed, the current time is
    assumed.  By default, rebasing happens, which causes the object to
    be converted to the user's timezone (as returned by
    :func:`to_user_timezone`).  This function formats both date and time.

    The format parameter can either be ``'short'``, ``'medium'``,
    ``'long'`` or ``'full'`` (in which case the language's default for
    that setting is used, or the default from the :attr:`Babel.date_formats`
    mapping is used) or a format string as documented by Babel.

    This function is also available in the template context as filter
    named `timeformat`.
    r1   )r   r   r   rX   )r1   r   r   r(   r(   r)   rX     s   
rX   secondF333333?granularityc                 C   s,   t | trt |  } tj| |||t dS )zFormat the elapsed time from the given date to now or the given
    timedelta.

    This function is also available in the template context as filter
    named `timedeltaformat`.
    )	thresholdadd_directionr   )r   r   utcnowr   rY   r   )Zdatetime_or_timedeltar   r   r   r(   r(   r)   rY     s   
rY   c                 K   s8   t  }i }| tjur|rt |d< | ||fd|i|S )z&Internal helper that formats the date.r   r   )r   r   rW   r   )	formatterobjr   r   extrar   r(   r(   r)   r     s
   
r   c                 C   s   t  }tj| |dS )zReturn the given number formatted for the locale in request

    :param number: the number to format
    :return: the formatted number
    :rtype: unicode
    )r   r   r   r[   )numberr   r(   r(   r)   rZ     s   rZ   c                 C      t  }tj| ||dS )zReturn the given decimal number formatted for the locale in the request.

    :param number: the number to format
    :param format: the format to use
    :return: the formatted number
    :rtype: unicode
    r   r   r   r   r   r   r(   r(   r)   r[        r[   standardc                 C   s   t  }tj| |||||dS )u  Return the given number formatted for the locale in the request.

    :param number: the number to format
    :param currency: the currency code
    :param format: the format to use
    :param currency_digits: use the currency’s number of decimal digits
                            [default: True]
    :param format_type: the currency format type to use
                        [default: standard]
    :return: the formatted number
    :rtype: unicode
    )r   r   currency_digitsformat_type)r   r   r\   )r   currencyr   r   r   r   r(   r(   r)   r\     s   r\   c                 C   r   )zReturn formatted percent value for the locale in the request.

    :param number: the number to format
    :param format: the format to use
    :return: the formatted percent number
    :rtype: unicode
    r   )r   r   r]   r   r(   r(   r)   r]     r   r]   c                 C   r   )zReturn value formatted in scientific notation for the locale in request

    :param number: the number to format
    :param format: the format to use
    :return: the formatted percent number
    :rtype: unicode
    r   )r   r   r^   r   r(   r(   r)   r^     r   r^   c                   @   s~   e Zd ZdZdddZ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d Zdd Zdd ZdS )rt   a  Localization domain. By default, it will look for translations in the
    Flask application directory and "messages" domain - all message catalogs
    should be called ``messages.mo``.
    
    Additional domains are supported passing a list of domain names to the
    ``domain`` argument, but note that in this case they must match a list
    passed to ``translation_directories``, eg::

        Domain(
            translation_directories=[
                "/path/to/translations/with/messages/domain",
                "/another/path/to/translations/with/another/domain",
            ],
            domains=[
                "messages",
                "myapp",
            ]
        )
    Nr;   c                 C   s,   t |tr|g}|| _|d| _i | _d S )Nr=   )r   r&   _translation_directoriesrO   rs   cache)r6   r   rs   r(   r(   r)   r9   8  s
   

zDomain.__init__c                 C   s   d | j| jS )Nz<Domain({!r}, {!r})>)r   r   rs   rr   r(   r(   r)   __repr__A  s   zDomain.__repr__c                 C   s   | j d ur| j S t jS r>   )r   r/   r   rr   r(   r(   r)   r   G  s   
zDomain.translation_directoriesc                 C   s    t  }|du rtd| |_dS )z2Set this domain as default for the current requestNzNo request context)r}   RuntimeErrorbabel_domainr6   r   r(   r(   r)   
as_defaultM  s   
zDomain.as_defaultc                 C   s   | j S )z6Returns dictionary-like object for translation caching)r   r   r(   r(   r)   get_translations_cacheV  s   zDomain.get_translations_cachec           	   	   C   s   t  }|d u rt S | |}t }z|t|| jd f W S  tyk   t }t	| j
D ],\}}t| jdkr?| jd n| j| }tj||g|}|| t|dr[|j|_q/||t|| jd f< | Y S w )Nr      plural)r}   r   r   r   r   r&   rs   KeyErrorr   	enumerater   lenloadmerger-   r   )	r6   r   r   r   r<   indexro   rs   catalogr(   r(   r)   r@   Z  s4   



zDomain.get_translationsc                 K   s"   |   }||}|s|S || S )zTranslates a string with the current locale and passes in the
        given keyword arguments as mapping to a string formatting string.

        ::

            gettext(u'Hello World!')
            gettext(u'Hello %(name)s!', name='World')
        r?   )r6   string	variablestrA   r(   r(   r)   rI     s   	
zDomain.gettextc                 K   s2   | d| |  }||||}|s|S || S )a  Translates a string with the current locale and passes in the
        given keyword arguments as mapping to a string formatting string.
        The `num` parameter is used to dispatch between singular and various
        plural forms of the message.  It is available in the format string
        as ``%(num)d`` or ``%(num)s``.  The source language should be
        English or a similar language which only has one plural form.

        ::

            ngettext(u'%(num)d Apple', u'%(num)d Apples', num=len(apples))
        num)
setdefaultr@   rC   )r6   singularr   r   r   r   rA   r(   r(   r)   rJ     s   zDomain.ngettextc                 K   s$   |   }|||}|s|S || S )zPLike :func:`gettext` but with a context.

        .. versionadded:: 0.7
        rF   )r6   contextr   r   r   rA   r(   r(   r)   rK     s   zDomain.pgettextc                 K   s4   | d| |  }|||||}|s|S || S )zQLike :func:`ngettext` but with a context.

        .. versionadded:: 0.7
        r   )r   r@   rH   )r6   r   r   r   r   r   r   rA   r(   r(   r)   rL     s   zDomain.npgettextc                 K   s   t | j|fi |S )a-  Like :func:`gettext` but the string returned is lazy which means
        it will be translated when it is used as an actual string.

        Example::

            hello = lazy_gettext(u'Hello World')

            @app.route('/')
            def index():
                return unicode(hello)
        r   rI   )r6   r   r   r(   r(   r)   lazy_gettext  s   zDomain.lazy_gettextc                 K   s   t | j|||fi |S )a  Like :func:`ngettext` but the string returned is lazy which means
        it will be translated when it is used as an actual string.

        Example::

            apples = lazy_ngettext(
                u'%(num)d Apple',
                u'%(num)d Apples',
                num=len(apples)
            )

            @app.route('/')
            def index():
                return unicode(apples)
        r   rJ   )r6   r   r   r   r   r(   r(   r)   lazy_ngettext  s   zDomain.lazy_ngettextc                 K   s   t | j||fi |S )zLike :func:`pgettext` but the string returned is lazy which means
        it will be translated when it is used as an actual string.

        .. versionadded:: 0.7
        r   rK   )r6   r   r   r   r(   r(   r)   lazy_pgettext  s   zDomain.lazy_pgettext)Nr;   )r"   r#   r$   r%   r9   r   ry   r   r   r   r@   rI   rJ   rK   rL   r   r   r   r(   r(   r(   r)   rt   #  s     
	
	%	
rt   c                   C   s    t sd S tt dst t _t jS )N_flask_babel)r   r-   r   r   r(   r(   r(   r)   r}     s
   
r}   c                  C   sB   t  } | d u r
t S z| jW S  ty   Y nw t jj| _| jS r>   )r}   rt   r   AttributeErrorr/   r   ru   )r   r(   r(   r)   r{     s   r{   c                  O      t  j| i |S r>   )r{   rI   r7   r8   r(   r(   r)   rI        rI   c                  O   r   r>   )r{   rJ   r   r(   r(   r)   rJ     r   rJ   c                  O   r   r>   )r{   rK   r   r(   r(   r)   rK     r   rK   c                  O   r   r>   )r{   rL   r   r(   r(   r)   rL     r   rL   c                  O      t tg| R i |S r>   r   r   r(   r(   r)   r        r   c                  O   r   r>   r   r   r(   r(   r)   r   
  r   r   c                  O   r   r>   r   r   r(   r(   r)   r     r   r   c                  O   r   r>   )r   rL   r   r(   r(   r)   lazy_npgettext  r   r   r>   )r*   r   rx   )r   Fr   )NTr   )Er%   rf   dataclassesr   typesr   r   
contextlibr   typingr   r   r	   r
   Zbabel.supportr   r   Zflaskr   r   Zflask.helpersr   r,   r   r   r   r   Zpytzr   r   Zwerkzeug.datastructuresr   Zflask_babel.speaklaterr   r   r/   r   r@   r   r   r   r   r&   r   r   r   rV   rW   rX   rY   r   rZ   r[   r\   r]   r^   objectrt   r}   r{   rI   _rJ   rK   rL   r   r   r   r   r(   r(   r(   r)   <module>   sr    	 A
#
	

	
 7
