U
    ânld�‘  ã                   @   s¾  d dl Z d dlZd dlZd dl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Zd dlmZ d dlmZmZmZmZmZmZmZmZ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( d dl)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ d dl0m1Z1m2Z2 d dl3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z; ddl<m=Z=m>Z> ddl?m=Z@ dd„ ZAdd„ ZBdd„ ZCdd„ ZDdd„ ZEd d!„ ZFd(d"d#„ZGd$d%„ ZHd&d'„ ZIdS ))é    N)Úwraps)Úunescape)Údefault_timer)Údatetime)Úget_supported_formats)
ÚabortÚ	BlueprintÚFlaskÚjsonifyÚrender_templateÚrequestÚResponseÚ	send_fileÚurl_forÚsession)Úswagger)Úget_swaggerui_blueprint)ÚSession)Útranslate_html)Úsecure_filename)ÚHTTPException)Ú	http_date)ÚBabel)Ú	schedulerÚfloodÚsecretÚremove_translated_filesÚsecurityÚstorage)Údetect_languagesÚimprove_translation_formatting)Ú_Ú_lazyÚget_available_localesÚget_available_locale_codesÚgettext_escapedÚgettext_htmlÚ	lazy_swagÚget_alternate_locale_linksé   )ÚDatabaseÚRemoteDatabase)r*   c               
   C   sB   z.t dƒ�} |  ¡  ¡ W  5 Q R £ W S Q R X W n   Y dS X d S )NZVERSIONú?)ÚopenÚreadÚstrip)Úf© r1   ú2/var/www/html/LibreTranslate/libretranslate/app.pyÚget_version!   s
    
$r3   c                  C   s,   t j t ¡ d¡} t j | ¡s(t  | ¡ | S )Nzlibretranslate-files-translate)ÚosÚpathÚjoinÚtempfileZ
gettempdirÚisdirÚmkdir)Z
upload_dirr1   r1   r2   Úget_upload_dir)   s    
r:   c                  C   s*   t jrtt ƒ} |  d¡}nt j d¡}|S )NÚapi_key©r   Úis_jsonÚget_json_dictÚgetÚvalues©ÚjsonÚakr1   r1   r2   Úget_req_api_key2   s
    rD   c                  C   s*   t jrtt ƒ} |  d¡}nt j d¡}|S )Nr   r<   rA   r1   r1   r2   Úget_req_secret;   s
    rE   c                 C   s&   |   ¡ }t|tƒs"tdtdƒd� |S )Né�  zInvalid JSON format©Údescription)Zget_jsonÚ
isinstanceÚdictr   r!   )r   Údr1   r1   r2   r>   E   s    
r>   c                  C   s6   t j d¡r(t j d¡d  d¡d } n
t jp0d} | S )NzX-Forwarded-Forr   ú,ú	127.0.0.1)r   ÚheadersZgetlistÚsplitZremote_addr)Úipr1   r1   r2   Úget_remote_addressL   s    
rQ   c                 C   s0   | }|r,t ƒ }|r,| |¡}|d k	r,|| }|S ©N)rD   Úlookup)Zdefault_limitÚapi_keys_dbZ
multiplierÚ	req_limitr;   Zdb_req_limitr1   r1   r2   Úget_req_limitsU   s    
rV   c                    sD   ˆdkrd‰‡ ‡fdd„}‡ ‡fdd„}|g}ˆdkr@|  |¡ |S )Néÿÿÿÿl   ÿåa$c                      s   dt ˆˆ ƒ S )Nz%s per minute©rV   r1   )rT   Údefault_req_limitr1   r2   Úminute_limitsh   s    z(get_routes_limits.<locals>.minute_limitsc                      s   dt ˆˆ dƒ S )Nz
%s per dayi   rX   r1   )rT   Údaily_req_limitr1   r2   Údaily_limitsk   s    z'get_routes_limits.<locals>.daily_limitsr   )Úappend)rY   r[   rT   rZ   r\   Úresr1   )rT   r[   rY   r2   Úget_routes_limitsc   s    
r_   c           "         s˜  ddl m} |ˆjˆjƒ ddlm} ˆjd ‰ˆjd }tdtƒ}t	 
ˆj¡ ˆjsbt 
tƒ ¡ |ƒ ‰i ‰ˆD ]}tdd„ |jD ƒƒˆ|j< qpˆjd	kr´td
tfd	tdƒdœƒ‰ntt‡fdd„ˆD ƒƒd ƒ‰ˆd kràˆd ‰tˆƒdkröˆd ‰nˆd ‰ˆjdk�r ‡
‡‡fdd„}|‰n6tt‡fdd„ˆD ƒƒd ƒ‰ˆd k�rJˆ‰‡fdd„‰g ‰tƒ D ]}|jD ]}ˆ |¡ �qj�q`d ‰ˆjdk�s¤ˆj�s¤ˆjdk�rød ‰ˆj�rÎˆj �rÄt!ˆj ƒ‰n
t"ˆj#ƒ‰ddl$m%}	 |	t&t'ˆjˆjˆƒˆj(d�}
nddl)m%}	 |	ƒ }
dt*j+ ,dd¡k�r(t- 
ˆ¡ t. 
ˆ¡ t/ 
ˆ¡ d ‰d ‰ˆj0�r"t*j+ ,d¡d k�r–t*j1 2t*j1 3dd¡¡}t*j1 4|¡�sŒt* 5|¡ |t*j+d< ddl6m7‰ m8}m9}m:‰m;‰m<‰	 | =d¡|
j>‡ ‡‡‡	‡fd d!„ƒƒ}|d"d#d$d%d&d'gƒ‰ˆ ?d(d)d*d¡ |d+d,d$d&d'gd-d.�‰ˆ ?d(d*d¡ ‡‡‡‡fd/d0„}| @d1¡d2d3„ ƒ}| @d4¡d5d6„ ƒ}| @d7¡d8d9„ ƒ}| @d:¡d;d<„ ƒ}| =d=¡|
j>‡‡‡
fd>d?„ƒƒ}| =d@¡|
j>‡fdAdB„ƒƒ}| ,dC¡|
j>‡‡fdDdE„ƒƒ}|jAdFdG„ ƒ}| Bd(¡|‡‡fdHdI„ƒƒ}| BdJ¡|‡‡‡fdKdL„ƒƒ}| ,dM¡tCdNœ‡fdOdP„ƒ}| BdQ¡|dRdS„ ƒƒ}| =dT¡|
j>‡‡‡‡fdUdV„ƒƒ}| BdW¡|‡fdXdY„ƒƒ}tDtƒ}dZ|jEd[< t*j1 3dd\¡|jEd]< tF|ƒ ˆjG�rÌd^|jEd_< ˆj�ræ|jH|ˆjd`� n
| H|¡ |
 I|¡ tJ|ƒ‰tKƒ ˆda db< dcˆda dd< | =|¡|
j>‡fdedf„ƒƒ}dg|jEdh< didj„ ‰
tL|ˆ
dk�} |jMjNjOtPtQdl� tRˆ|ƒ}!ˆj�rŠ|jH|!ˆd`� n
| H|!¡ |S )mNr   )Úboot)Úload_languagesz/docsz/speczMain appc                 S   s   g | ]}|j j‘qS r1   )Zto_langÚcode©Ú.0Úlr1   r1   r2   Ú
<listcomp>‰   s     zcreate_app.<locals>.<listcomp>ÚautoÚobjzAuto Detect©rb   Únamec                    s   g | ]}|j ˆ jkr|‘qS r1   )rb   Úfrontend_language_sourcerc   ©Úargsr1   r2   rf   ’   s      é   r)   Úlocalec                     s2   ˆƒ ‰ t t‡ fdd„ˆD ƒƒd ƒ} | d kr.ˆ} | S )Nc                    s   g | ]}|j ˆ kr|‘qS r1   ©rb   rc   ©Úlocr1   r2   rf   ¢   s     
 z?create_app.<locals>.resolve_language_locale.<locals>.<listcomp>©ÚnextÚiter©Úlanguage_target)Ú
get_localeÚlanguage_target_fallbackÚ	languagesrq   r2   Úresolve_language_localeŸ   s     ÿz+create_app.<locals>.resolve_language_localec                    s   g | ]}|j ˆ jkr|‘qS r1   )rb   Úfrontend_language_targetrc   rl   r1   r2   rf   «   s      c                      s   ˆ S rR   r1   r1   rv   r1   r2   Ú<lambda>¯   ó    zcreate_app.<locals>.<lambda>)ÚLimiter)Zkey_funcZdefault_limitsZstorage_uriZgunicornZSERVER_SOFTWAREÚ ZPROMETHEUS_MULTIPROC_DIRZdbZ
prometheus)ÚCONTENT_TYPE_LATESTÚSummaryÚGaugeÚCollectorRegistryÚmultiprocessÚgenerate_latestz/metricsc                     sP   ˆj r0tj d¡} | dˆj  kr0tdtdƒd� ˆƒ }ˆ |¡ tˆ|ƒˆ d�S )NÚAuthorizationzBearer i‘  ZUnauthorizedrG   )Zmimetype)Zmetrics_auth_tokenr   rN   r?   r   r!   ZMultiProcessCollectorr   )ZauthorizationÚregistry)r�   r„   rm   r†   r…   r1   r2   Úprometheus_metricsá   s    
z&create_app.<locals>.prometheus_metricsZ,libretranslate_http_request_duration_secondszTime spent on requestZendpointÚstatusZ
request_ipr;   z
/translateéÈ   rM   Z&libretranslate_http_requests_in_flightzActive requestsZlivesum)Zmultiprocess_modec                    sB   t ˆ ƒ‡‡‡ fdd„ƒ‰ˆjr:t ˆƒ‡‡‡fdd„ƒ}|S ˆS d S )Nc                     sØ   t ƒ }t |¡r tdtdƒd� ˆjrÎtƒ }|rPˆ  |¡d krPtdtdƒd� n~d}ˆ  |¡d k}ˆjrˆ|rˆt	 
ˆjtj dd¡¡sˆd}ˆjr¢|r¢t tƒ ¡s¢d}|rÎtd	ƒ}ˆjrÂtd
ˆjd�}td|d� ˆ| |ŽS )Né“  z"Too many request limits violationsrG   zInvalid API keyFZOriginr€   Tz4Please contact the server operator to get an API keyzVisit %(url)s to get an API key)ZurlrF   )rQ   r   Z	is_bannedr   r!   Úapi_keysrD   rS   Úrequire_api_key_originÚreÚmatchr   rN   r?   Úrequire_api_key_secretr   Zsecret_matchrE   Úget_api_key_link)ÚaÚkwrP   rC   Zneed_keyZkey_missingrH   )rT   rm   r0   r1   r2   Úfuncô   sB    
þÿþÿ
þþz.create_app.<locals>.access_check.<locals>.funcc            	         s¬   t ƒ }d}tƒ }tƒ pd}ˆ tj||¡}zJz| 	¡  ˆ | |ŽW W ¢2S  t
k
rp } z|j}|‚W 5 d }~X Y nX W 5 tt ƒ | dƒ}ˆ tj|||¡ |¡ | ¡  X d S )Nr‹   r€   r   )r   rQ   rD   Úlabelsr   r5   ÚmaxZobserveZdecZincr   rb   )	r“   r”   Zstart_trŠ   rP   rC   ÚgZdurationÚe)r•   Úgauge_requestÚmeasure_requestr1   r2   Úmeasure_func  s    
z6create_app.<locals>.access_check.<locals>.measure_func)r   Úmetrics)r0   rœ   )rT   rm   rš   r›   )r0   r•   r2   Úaccess_checkó   s    'z create_app.<locals>.access_checkrF   c                 S   s   t dt| jƒiƒdfS )NÚerrorrF   ©r
   ÚstrrH   ©r™   r1   r1   r2   Úinvalid_api2  s    zcreate_app.<locals>.invalid_apiéô  c                 S   s   t dt| jƒiƒdfS )NrŸ   r¤   r    r¢   r1   r1   r2   Úserver_error6  s    z create_app.<locals>.server_erroré­  c                 S   s.   t  tƒ ¡ tdtdƒd t| jƒ iƒdfS )NrŸ   z	Slowdown:ú r¦   )r   ÚreportrQ   r
   r!   r¡   rH   r¢   r1   r1   r2   Úslow_down_error:  s    z#create_app.<locals>.slow_down_errorrŒ   c                 S   s   t dt| jƒiƒdfS )NrŸ   rŒ   r    r¢   r1   r1   r2   Údenied?  s    zcreate_app.<locals>.deniedú/c                     s„   ˆj rtdƒ tj d¡} | r:| tˆj ƒkr:tj| d� t	dˆj
ˆjˆjˆjtj d¡d k	tƒ ˆ dd„ tˆj ƒD ƒˆƒ tƒ d�S )	Né”  Úlang)Úpreferred_langz
index.htmlZLT_WEBc                 S   s"   g | ]}|d  t |d ƒdœ‘qS )rb   rj   ri   )r"   rc   r1   r1   r2   rf   V  s     z-create_app.<locals>.index.<locals>.<listcomp>)
ZgaIdÚfrontendTimeoutr�   r’   Zweb_versionÚversionZswagger_urlZavailable_localesZcurrent_localeZalternate_locales)Údisable_web_uir   r   rm   r?   r$   Údebugr   Úupdater   Zga_idÚfrontend_timeoutr�   r’   r4   Úenvironr3   r#   r(   )Zlangcode)ÚSWAGGER_URLrm   rx   r1   r2   ÚindexC  s$    õzcreate_app.<locals>.indexz
/js/app.jsc                     sr   ˆ j rtdƒ ttdˆ jˆ jˆ jr*t ¡ ndd�dd�} ˆ jrnt	t
 ¡ ƒ| jd< d| jd	< d
| jd< d| jd< | S )Nr¬   zapp.js.templater€   )Ú
url_prefixr’   Z
api_secretz%application/javascript; charset=utf-8)Zcontent_typezLast-ModifiedzIno-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0zCache-Controlzno-cacheZPragmaz-1ZExpires)r±   r   r   r   r¸   r’   r‘   r   Zget_current_secretr   r   ZnowrN   ©Zresponserl   r1   r2   Úappjs[  s    ýý


zcreate_app.<locals>.appjsz
/languagesc                      s   t ‡ fdd„ˆD ƒƒS )añ  
        Retrieve list of supported languages
        ---
        tags:
          - translate
        responses:
          200:
            description: List of languages
            schema:
              id: languages
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                    description: Language code
                  name:
                    type: string
                    description: Human-readable language name (in English)
                  targets:
                    type: array
                    items:
                      type: string
                    description: Supported target language codes
        c                    s*   g | ]"}|j t|jƒˆ  |j g ¡d œ‘qS ))rb   rj   Ztargets)rb   r"   rj   r?   rc   )Úlanguage_pairsr1   r2   rf   ‹  s     z-create_app.<locals>.langs.<locals>.<listcomp>)r
   r1   )r»   rz   r1   r2   Úlangsn  s    zcreate_app.<locals>.langsc                 S   sX   | j  dd¡ | j  dd¡ | j  dd¡ | j  dd¡ | j  d	d
¡ | j  dd¡ | S )NzAccess-Control-Allow-OriginÚ*zAccess-Control-Allow-HeaderszAuthorization, Content-TypezAccess-Control-Expose-Headersr‡   zAccess-Control-Allow-Methodsz	GET, POSTz Access-Control-Allow-CredentialsÚtruezAccess-Control-Max-Agei ^ )rN   Úaddr¹   r1   r1   r2   Úafter_requestŽ  s     ÿz!create_app.<locals>.after_requestc               
      sT  t jr8tt ƒ} |  d¡}|  d¡‰ |  d¡‰|  d¡}n0t j d¡}t j d¡‰ t j d¡‰t j d¡}|s€tdtddd�d� ˆ s˜tdtddd�d� ˆs°tdtddd�d� t|tƒ}|ròˆj	d	kròt
|ƒ}ˆj	|k ròtdtd
|ˆj	d�d� ˆjd	k�rD|�rtdd„ |D ƒƒ}nt
|ƒ}ˆj|k �rDtdtd
|ˆjd�d� ˆ dk�rÊg }|�r^|}n|g}t|ƒ}|D ]V}	t
|	ƒdk�rŒt|	ƒ}
n|}
| |
d ¡ ˆj�rpt|	|
ƒ td|
d d  ƒ �qpn&|�rä‡ fdd„|D ƒ}ndˆ dœg}‡fdd„|D ƒ}t|ƒD ],\}}|dk�r
tdtd|| d�d� �q
tt‡fdd„ˆD ƒƒdƒ}|dk�rrtdtdˆd�d� |�s|d}|dk�rštdtd|d�d� �zv|�rhg }t|ƒD ]Œ\}}||  |¡}|dk�rtdtdt|jƒ|jt|| jƒ|| jd �d� |d!k�rtt||ƒƒ}nt|| |¡ƒ}| t|ƒ¡ �q°ˆ dk�rXt||d"œƒW S td#|iƒW S n¨|d  |¡}|dk�r²tdtdt|jƒ|jt|d jƒ|d jd �d� |d!k�rÌtt||ƒƒ}nt|| |¡ƒ}ˆ dk�rþtt|ƒ|d d"œƒW S td#t|ƒiƒW S W n< tk
�rN } ztd$td%t|ƒd&�d� W 5 d}~X Y nX dS )'aâ
  
        Translate text from a language to another
        ---
        tags:
          - translate
        parameters:
          - in: formData
            name: q
            schema:
              oneOf:
                - type: string
                  example: Hello world!
                - type: array
                  example: ['Hello world!']
            required: true
            description: Text(s) to translate
          - in: formData
            name: source
            schema:
              type: string
              example: en
            required: true
            description: Source language code
          - in: formData
            name: target
            schema:
              type: string
              example: es
            required: true
            description: Target language code
          - in: formData
            name: format
            schema:
              type: string
              enum: [text, html]
              default: text
              example: text
            required: false
            description: >
              Format of source text:
               * `text` - Plain text
               * `html` - HTML markup
          - in: formData
            name: api_key
            schema:
              type: string
              example: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
            required: false
            description: API key
        responses:
          200:
            description: Translated text
            schema:
              id: translate
              type: object
              properties:
                translatedText:
                  oneOf:
                    - type: string
                    - type: array
                  description: Translated text(s)
          400:
            description: Invalid request
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
          500:
            description: Translation error
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
          429:
            description: Slow down
            schema:
              id: error-slow-down
              type: object
              properties:
                error:
                  type: string
                  description: Reason for slow down
          403:
            description: Banned
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
        ÚqÚsourceÚtargetÚformatrF   ú+Invalid request: missing %(name)s parameter©rj   rG   rW   zBInvalid request: request (%(size)s) exceeds text limit (%(limit)s))ÚsizeZlimitc                 S   s   g | ]}t |ƒ‘qS r1   )Úlen©rd   Útextr1   r1   r2   rf     s     z1create_app.<locals>.translate.<locals>.<listcomp>rg   é(   r   zAuto detected: %sÚlanguagec                    s   g | ]}d ˆ dœ‘qS )ç      Y@©Z
confidencerÌ   r1   rÉ   ©Úsource_langr1   r2   rf   >  s     rÍ   rÎ   c                    s(   g | ] ‰ t t‡ fd d„ˆD ƒƒdƒ‘qS )c                    s   g | ]}|j ˆ d  kr|‘qS )rÌ   rp   rc   rÏ   r1   r2   rf   B  s      z<create_app.<locals>.translate.<locals>.<listcomp>.<listcomp>Nrs   ©rd   ©rz   rÏ   r2   rf   B  s     Nú%(lang)s is not supported©r­   c                    s   g | ]}|j ˆ kr|‘qS r1   rp   rc   ©Útarget_langr1   r2   rf   H  s     
 rÊ   )rÊ   Úhtmlz"%(format)s format is not supported)rÄ   zV%(tname)s (%(tcode)s) is not available as a target language from %(sname)s (%(scode)s))ZtnameZtcodeZsnameZscoder×   )ÚtranslatedTextZdetectedLanguagerØ   r¤   zCannot translate text: %(text)s)rÊ   )r   r=   r>   r?   r@   r   r!   rI   ÚlistZbatch_limitrÈ   Ú
char_limitÚsumr   r]   r²   ÚprintÚ	enumeratert   ru   Úget_translationr"   rj   rb   r¡   r   r    Ú	translater   r
   Ú	Exception)rB   rÁ   Ztext_formatZbatchZ
batch_sizeÚcharsÚsource_langsZauto_detect_textsZoverall_candidatesZtext_to_checkZcandidate_langsÚ	src_langsÚidxr­   Útgt_langZresultsrÊ   Z
translatorZtranslated_textr™   )rm   rz   )rÐ   rÖ   r2   rß   š  sÌ    e




þþ






2

þÿ ÿÿ
2

þÿ ÿÿ
zcreate_app.<locals>.translatez/translate_filec               
      sè  ˆj rtdtdƒd� tj d¡} tj d¡‰ tjd }|sPtdtddd	�d� | shtdtddd	�d� ˆ s€tdtddd	�d� |jd
krštdtdƒd� tj	 
|j¡d ˆkrÀtdtdƒd� | g}‡fdd„|D ƒ}t|ƒD ](\}}|dkràtdtd|| d�d� qàtt‡ fdd„ˆD ƒƒdƒ}|dk�rDtdtdˆ d�d� zntt ¡ ƒd t|jƒ }tj	 tƒ |¡}| |¡ t |d  |¡|¡}	tj	 |	¡}
tdtd|
dd�iƒW S  tk
�râ } ztd|d� W 5 d}~X Y nX dS )aÙ  
        Translate file from a language to another
        ---
        tags:
          - translate
        consumes:
         - multipart/form-data
        parameters:
          - in: formData
            name: file
            type: file
            required: true
            description: File to translate
          - in: formData
            name: source
            schema:
              type: string
              example: en
            required: true
            description: Source language code
          - in: formData
            name: target
            schema:
              type: string
              example: es
            required: true
            description: Target language code
          - in: formData
            name: api_key
            schema:
              type: string
              example: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
            required: false
            description: API key
        responses:
          200:
            description: Translated file
            schema:
              id: translate-file
              type: object
              properties:
                translatedFileUrl:
                  type: string
                  description: Translated file url
          400:
            description: Invalid request
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
          500:
            description: Translation error
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
          429:
            description: Slow down
            schema:
              id: error-slow-down
              type: object
              properties:
                error:
                  type: string
                  description: Reason for slow down
          403:
            description: Banned
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
        rŒ   ú.Files translation are disabled on this server.rG   rÂ   rÃ   ÚfilerF   rÅ   rÆ   r€   zInvalid request: empty filer)   z*Invalid request: file format not supportedc                    s(   g | ] ‰ t t‡ fd d„ˆD ƒƒdƒ‘qS )c                    s   g | ]}|j ˆ kr|‘qS r1   rp   rc   rÏ   r1   r2   rf   ñ  s     
 zAcreate_app.<locals>.translate_file.<locals>.<listcomp>.<listcomp>Nrs   rÑ   rÒ   rÏ   r2   rf   ñ  s     z6create_app.<locals>.translate_file.<locals>.<listcomp>NrÓ   rÔ   c                    s   g | ]}|j ˆ kr|‘qS r1   rp   rc   rÕ   r1   r2   rf   ÷  s     
 Ú.r   ZtranslatedFileUrlzMain app.download_fileT)ÚfilenameZ	_externalr¤   )Údisable_files_translationr   r!   r   Zformr?   Úfilesré   r4   r5   ÚsplitextrÝ   rt   ru   r¡   ÚuuidZuuid4r   r6   r:   ZsaveÚargostranslatefilesÚtranslate_filerÞ   Úbasenamer
   r   rà   )rÐ   rç   râ   rã   rä   r­   rå   ré   ÚfilepathZtranslated_file_pathZtranslated_filenamer™   )rm   Ú%frontend_argos_supported_files_formatrz   rÕ   r2   rï   ˆ  sH    T



 ÿÿz"create_app.<locals>.translate_filez /download_file/<string:filename>)ré   c              	      sÒ   ˆ j rtdtdƒd� tj tƒ | ¡}z"t |tƒ ¡}tj 	|¡rF|}W n& tj
k
rn   tdtdƒd� Y nX t ¡ }t|dƒ�}| | ¡ ¡ W 5 Q R X | d¡ |  d¡}| d¡ d |¡}t|d|d	�S )
z,
        Download a translated file
        rF   ræ   rG   zInvalid filenameÚrbr   rè   T)Zas_attachmentZdownload_name)rê   r   r!   r4   r5   r6   r:   r   Zpath_traversal_checkÚisfileZSuspiciousFileOperationÚioÚBytesIOr-   Úwriter.   ÚseekrO   Úpopr   )ré   rñ   Zchecked_filepathZreturn_dataÚfoZdownload_filenamerl   r1   r2   Údownload_file  s"    



z!create_app.<locals>.download_filez/detectc                  S   sJ   t jrtt ƒ} |  d¡}nt j d¡}|s>tdtddd�d� tt|ƒƒS )a‚  
        Detect the language of a single text
        ---
        tags:
          - translate
        parameters:
          - in: formData
            name: q
            schema:
              type: string
              example: Hello world!
            required: true
            description: Text to detect
          - in: formData
            name: api_key
            schema:
              type: string
              example: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
            required: false
            description: API key
        responses:
          200:
            description: Detections
            schema:
              id: detections
              type: array
              items:
                type: object
                properties:
                  confidence:
                    type: number
                    format: float
                    minimum: 0
                    maximum: 1
                    description: Confidence value
                    example: 0.6
                  language:
                    type: string
                    description: Language code
                    example: en
          400:
            description: Invalid request
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
          500:
            description: Detection error
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
          429:
            description: Slow down
            schema:
              id: error-slow-down
              type: object
              properties:
                error:
                  type: string
                  description: Reason for slow down
          403:
            description: Banned
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
        rÁ   rF   rÅ   rÆ   rG   )	r   r=   r>   r?   r@   r   r!   r
   r   )rB   rÁ   r1   r1   r2   Údetect(  s    Pzcreate_app.<locals>.detectz/frontend/settingsc                     sd   ˆƒ } t ˆ jˆ jˆ jtˆ jo ˆ jƒˆ jˆ j ˆ jr6g nˆˆjt	ˆj
ƒdœ| jt	| j
ƒdœdœdœƒS )a¦  
        Retrieve frontend specific settings
        ---
        tags:
          - frontend
        responses:
          200:
            description: frontend settings
            schema:
              id: frontend-settings
              type: object
              properties:
                charLimit:
                  type: integer
                  description: Character input limit for this language (-1 indicates no limit)
                frontendTimeout:
                  type: integer
                  description: Frontend translation timeout
                apiKeys:
                  type: boolean
                  description: Whether the API key database is enabled.
                keyRequired:
                  type: boolean
                  description: Whether an API key is required.
                suggestions:
                  type: boolean
                  description: Whether submitting suggestions is enabled.
                supportedFilesFormat:
                  type: array
                  items:
                    type: string
                  description: Supported files format
                language:
                  type: object
                  properties:
                    source:
                      type: object
                      properties:
                        code:
                          type: string
                          description: Language code
                        name:
                          type: string
                          description: Human-readable language name (in English)
                    target:
                      type: object
                      properties:
                        code:
                          type: string
                          description: Language code
                        name:
                          type: string
                          description: Human-readable language name (in English)
        ri   )rÂ   rÃ   )Z	charLimitr¯   ZapiKeysZkeyRequiredÚsuggestionsZfilesTranslationZsupportedFilesFormatrÌ   )r
   rÚ   r´   r�   ÚboolrŽ   rý   rê   rb   r"   rj   rÕ   )rm   Úfrontend_argos_language_sourceÚfrontend_argos_language_targetrò   r1   r2   Úfrontend_settingsƒ  s$    9þþûøÿz%create_app.<locals>.frontend_settingsz/suggestc                     sÄ   ˆ j stdtdƒd� tj d¡} tj d¡}tj d¡}tj d¡}| s^tdtd	dd
�d� |svtdtd	dd
�d� |sŽtdtd	dd
�d� |s¦tdtd	dd
�d� tƒ  | |||¡ tddiƒS )uÕ  
        Submit a suggestion to improve a translation
        ---
        tags:
          - feedback
        parameters:
          - in: formData
            name: q
            schema:
              type: string
              example: Hello world!
            required: true
            description: Original text
          - in: formData
            name: s
            schema:
              type: string
              example: Â¡Hola mundo!
            required: true
            description: Suggested translation
          - in: formData
            name: source
            schema:
              type: string
              example: en
            required: true
            description: Language of original text
          - in: formData
            name: target
            schema:
              type: string
              example: es
            required: true
            description: Language of suggested translation
        responses:
          200:
            description: Success
            schema:
              id: suggest-response
              type: object
              properties:
                success:
                  type: boolean
                  description: Whether submission was successful
          403:
            description: Not authorized
            schema:
              id: error-response
              type: object
              properties:
                error:
                  type: string
                  description: Error message
        rŒ   z(Suggestions are disabled on this server.rG   rÁ   ÚsrÂ   rÃ   rF   rÅ   rÆ   ZsuccessT)	rý   r   r!   r   r@   r?   ÚSuggestionsDatabaser¿   r
   )rÁ   r  rÐ   rÖ   rl   r1   r2   ÚsuggestÔ  s     9zcreate_app.<locals>.suggestZ
filesystemZSESSION_TYPEZsessionsZSESSION_FILE_DIRTZTEMPLATES_AUTO_RELOAD)r¸   Úinfor°   ZLibreTranslateÚtitlec                      s   t tˆ ƒƒS rR   )r
   r'   r1   )Úswagr1   r2   Úspec4  s    zcreate_app.<locals>.specZlocalesZBABEL_TRANSLATION_DIRECTORIESc                  S   s4   t j d¡} | r| tƒ kr| S t dt j tƒ ¡¡S )NzX-Override-Accept-Languager®   )r   rN   r?   r$   r   Zaccept_languagesZ
best_match)Zoverride_langr1   r1   r2   rx   ;  s    zcreate_app.<locals>.get_locale)Zlocale_selector)Z_eZ_h)SZlibretranslate.initr`   Z	load_onlyZupdate_modelsÚlibretranslate.languagera   r¸   r   Ú__name__r   ZsetupZshared_storagerê   r   r:   ÚsortedZtranslations_fromrb   rk   ÚtypeÚobjectr!   rt   ru   rÈ   r|   r   Zsupported_file_extensionsr]   rU   r�   r[   Zapi_keys_remoter+   r*   Zapi_keys_db_pathZflask_limiterr   rQ   r_   Zreq_limit_storageZ
no_limiterr4   rµ   r?   r   r   r   r�   r5   Úabspathr6   r8   r9   Zprometheus_clientr�   r‚   rƒ   r„   r…   r†   ZrouteZexemptr–   ZerrorhandlerrÀ   Zpostr¡   r	   Zconfigr   r²   Zregister_blueprintZinit_appr   r3   r   Z	jinja_envÚglobalsr³   r%   r&   r   )"rm   r`   ra   ZAPI_URLZbpr­   r{   Zfile_formatZffr   ZlimiterZdefault_mp_dirr‚   rƒ   r‰   rž   r£   r¥   r©   rª   r·   rº   r¼   rÀ   rß   rï   rû   rü   r  r  Úappr  ZbabelZswaggerui_blueprintr1   )r�   r„   r¶   rT   rm   rÿ   r   rò   rš   r†   rx   r»   rw   ry   rz   r›   r…   r  r2   Ú
create_appv   s"   



  ÿþ
	 ÿ


 
  ÿû




 
?




 m YOK






r  )r)   )Jrõ   r4   r7   r�   rí   Ú	functoolsr   r×   r   Ztimeitr   r   rî   r   Zflaskr   r   r	   r
   r   r   r   r   r   r   Zflask_swaggerr   Zflask_swagger_uir   Zflask_sessionr   Ztranslatehtmlr   Zwerkzeug.utilsr   Zwerkzeug.exceptionsr   Zwerkzeug.httpr   Zflask_babelr   Úlibretranslater   r   r   r   r   r   r	  r   r    Zlibretranslate.localesr!   r"   r#   r$   r%   r&   r'   r(   r�   r*   r+   rý   r  r3   r:   rD   rE   r>   rQ   rV   r_   r  r1   r1   r1   r2   Ú<module>   sB   0 (		
	
