a
    Dg?                     @   s6  d dl 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
 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 ZG dd de	j Z!G dd de	j"Z#G dd de	j"Z$dd Z%G dd dej&Z'G dd de$Z(d"ddZ)eed d! Z*dS )#    N)apps)settings)checks)
migrationsmodelstransaction)pre_save)receiver)translation)	force_str)gettext_lazy)ParentalKey)CopyForTranslationAction)get_content_languages&get_supported_content_language_variant)pre_validate_deletec                 C   s   t | tjr| jS | S d S N)
isinstancer   Modelpk)obj r   R/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/wagtail/models/i18n.pyr      s    r   c                   @   s   e Zd Zdd ZdS )LocaleManagerc                 C   s   | j t|dS )z5
        Gets a Locale from a language code.
        language_code)getr   )selfr   r   r   r   get_for_language   s    zLocaleManager.get_for_languageN)__name__
__module____qualname__r   r   r   r   r   r      s   r   c                       s   e Zd ZejdddZe Ze Z	G dd dZ
edd Zedd	 Zej fd
dZdd ZedddZdd Zeeef dddZedd Zedd Zedd Zedd ZeedddZeeddd Zeedd!d"Z  Z S )#Localed   T)
max_lengthuniquec                   @   s   e Zd ZdgZdS )zLocale.Metar   N)r   r    r!   Zorderingr   r   r   r   Meta3   s   r&   c                 C   s   | j tjS )z[
        Returns the default Locale based on the site's ``LANGUAGE_CODE`` setting.
        )objectsr   r   LANGUAGE_CODEclsr   r   r   get_default8   s    zLocale.get_defaultc              	   C   s8   z| j t W S  | jtfy2   |   Y S 0 dS )zd
        Returns the Locale that corresponds to the currently activated language in Django.
        N)r'   r   r
   get_languageDoesNotExistLookupErrorr+   r)   r   r   r   
get_active?   s    zLocale.get_activec                    s    t jt| d t j|i |S )N)senderinstance)r   sendr"   superdelete)r   argskwargs	__class__r   r   r4   I   s    zLocale.deletec                 C   s   | j t v S r   )r   r   r   r   r   r   language_code_is_validR   s    zLocale.language_code_is_valid)returnc                 C   sD   zt  | j W S  ty    Y n0 z| jW S  ty<   Y n0 | jS r   )r   r   KeyErrorlanguage_namer9   r   r   r   get_display_nameU   s    zLocale.get_display_namec                 C   s   t |  S r   )r   r>   r9   r   r   r   __str__a   s    zLocale.__str__c                 C   s   t | jS r   r
   Zget_language_infor   r9   r   r   r   _get_language_infod   s    zLocale._get_language_infoc                 C   s   t | jS r   r@   r9   r   r   r   language_infog   s    zLocale.language_infoc                 C   s
   | j d S )aQ  
        Uses data from ``django.conf.locale`` to return the language name in
        English. For example, if the object's ``language_code`` were ``"fr"``,
        the return value would be ``"French"``.

        Raises ``KeyError`` if ``django.conf.locale`` has no information
        for the object's ``language_code`` value.
        namerB   r9   r   r   r   r=   k   s    
zLocale.language_namec                 C   s
   | j d S )u`  
        Uses data from ``django.conf.locale`` to return the language name in
        the language itself. For example, if the ``language_code`` were
        ``"fr"`` (French), the return value would be ``"français"``.

        Raises ``KeyError`` if ``django.conf.locale`` has no information
        for the object's ``language_code`` value.
        Z
name_localrD   r9   r   r   r   language_name_localw   s    
zLocale.language_name_localc                 C   s   t | jS )a  
        Uses data from ``django.conf.locale`` to return the language name in
        the currently active language. For example, if ``language_code`` were
        ``"fr"`` (French), and the active language were ``"da"`` (Danish), the
        return value would be ``"Fransk"``.

        Raises ``KeyError`` if ``django.conf.locale`` has no information
        for the object's ``language_code`` value.

        )r
   gettextr=   r9   r   r   r   language_name_localized   s    zLocale.language_name_localizedc                 C   s   | j tjv S )zV
        Returns a boolean indicating whether the language is bi-directional.
        )r   r   ZLANGUAGES_BIDIr9   r   r   r   is_bidi   s    zLocale.is_bidic                 C   s,   z| j ttjkW S  ty&   Y dS 0 dS )zY
        Returns a boolean indicating whether this object is the default locale.
        FN)r   r   r   r(   r.   r9   r   r   r   
is_default   s    zLocale.is_defaultc                 C   s2   z| j tt kW S  ty,   | j Y S 0 dS )zb
        Returns a boolean indicating whether this object is the currently active locale.
        N)r   r   r
   r,   r.   rI   r9   r   r   r   	is_active   s    zLocale.is_active)!r   r    r!   r   Z	CharFieldr   r   r'   ManagerZall_objectsr&   classmethodr+   r/   r   Zatomicr4   r:   strr>   r?   dictrA   propertyrB   r=   rE   rG   boolrH   rI   rJ   __classcell__r   r   r7   r   r"   '   s8   

	



r"   c                       s   e Zd ZejejddZeje	ej
ddeddZde_G dd dZe fd	d
Zedd Zedd ZdddZdd Zdd Zdd ZdddZdd Zedd Z  ZS ) TranslatableMixinF)defaulteditable+locale)	on_deleterelated_namerT   Zverbose_nameTc                   @   s   e Zd ZdZdgZdS )zTranslatableMixin.MetaTtranslation_keyrV   N)r   r    r!   abstractunique_togetherr   r   r   r   r&      s   r&   c              	      s   t  jf i |}|  | u }|s&|S d t fdd| jjD } | jjv }|s|s|tj	d| jj
 f d | jj| jj| jf | dd |r|r|tj	d| jj
 f d	| dd |S )
NrY   c                 3   s,   | ]$}t |tjo"t|jt kV  qd S r   )r   r   ZUniqueConstraintsetfields).0
constraintZunique_constraint_fieldsr   r   	<genexpr>   s   z*TranslatableMixin.check.<locals>.<genexpr>z4%s is missing a UniqueConstraint for the fields: %s.zjAdd models.UniqueConstraint(fields=%s, name='unique_translation_key_locale_%s_%s') to %s.Meta.constraints.zwagtailcore.E003)hintr   idzE%s should not have both UniqueConstraint and unique_together for: %s.z4Remove unique_together in favor of UniqueConstraint.)r3   checkget_translation_modelany_metaconstraintsr\   appendr   ErrorlabelZ	app_labelZ
model_namer   )r*   r6   errorsZis_translation_modelZhas_unique_constraintZhas_unique_togetherr7   ra   r   re      sL    
	

zTranslatableMixin.checkc                 C   s*   ddl m} | j}t| |r&|js&| S |S )a3  
        Finds the translation in the current active language.

        If there is no translation in the active language, self is returned.

        Note: This will not return the translation if it is in draft.
        If you want to include drafts, use the ``.localized_draft`` attribute instead.
        r   )DraftStateMixin)Zwagtail.modelsrn   localized_draftr   Zlive)r   rn   	localizedr   r   r   rp      s
    
zTranslatableMixin.localizedc              	   C   sX   t tdds| S zt }W n ttjfy8   |  Y S 0 |j| jkrJ| S | |pV| S )a  
        Finds the translation in the current active language.

        If there is no translation in the active language, self is returned.

        Note: This will return translations that are in draft. If you want to exclude
        these, use the ``.localized`` attribute.
        ZWAGTAIL_I18N_ENABLEDF)	getattrr   r"   r/   r.   r-   rd   	locale_idget_translation_or_noner   rV   r   r   r   ro     s    

z!TranslatableMixin.localized_draftc                 C   s,   | j jj| jd}|du r(|j| jd}|S )zR
        Returns a queryset containing the translations of this instance.
        )rZ   Frd   )r8   r'   filterrZ   excluderd   )r   	inclusiveZtranslationsr   r   r   get_translations  s    z"TranslatableMixin.get_translationsc                 C   s   | j ddjt|dS )z
        Finds the translation in the specified locale.

        If there is no translation in that locale, this raises a ``model.DoesNotExist`` exception.
        Trx   rr   )ry   r   r   rt   r   r   r   get_translation,  s    z!TranslatableMixin.get_translationc                 C   s*   z|  |W S  | jjy$   Y dS 0 dS )z
        Finds the translation in the specified locale.

        If there is no translation in that locale, this returns ``None``.
        N)r|   r8   r-   rt   r   r   r   rs   4  s    z)TranslatableMixin.get_translation_or_nonec                 C   s   | j ddjt|d S )zO
        Returns True if a translation exists in the specified locale.
        Trz   r{   )ry   rv   r   existsrt   r   r   r   has_translation?  s    z!TranslatableMixin.has_translationNc                 C   s   t | ||d S )z~
        Creates a copy of this instance with the specified locale.

        Note that the copy is initially unsaved.
        )exclude_fields)r   execute)r   rV   r   r   r   r   copy_for_translationG  s
    z&TranslatableMixin.copy_for_translationc                 C   sN   dd | j  D }|rF|d | }|d jj dj|djS t	
 S )z}
        Finds the default locale to use for this object.

        This will be called just before the initial save.
        c                 S   s&   g | ]}t |trt|jtr|qS r   )r   r   
issubclassrelated_modelrR   )r_   fieldr   r   r   
<listcomp>[  s   
z8TranslatableMixin.get_default_locale.<locals>.<listcomp>r   rV   ru   )rh   Z
get_fieldsZvalue_from_objectr   r'   deferZselect_relatedr   rV   r"   r+   )r   Zparental_keysZ	parent_idr   r   r   get_default_localeS  s    z$TranslatableMixin.get_default_localec                 C   s   | j djS )aX  
        Returns this model's "Translation model".

        The "Translation model" is the model that has the ``locale`` and
        ``translation_key`` fields.
        Typically this would be the current model, but it may be a
        super-class if multi-table inheritance is in use (as is the case
        for ``wagtailcore.Page``).
        rV   )rh   	get_fieldmodelr)   r   r   r   rf   n  s    z'TranslatableMixin.get_translation_model)F)N)r   r    r!   r   	UUIDFielduuiduuid4rZ   
ForeignKeyr"   PROTECT_rV   Zwagtail_reference_index_ignorer&   rL   re   rO   rp   ro   ry   r|   rs   r~   r   r   rf   rQ   r   r   r7   r   rR      s0   5



rR   c                 C   s@   | j jdd  D ]$}t |_||_|jddgd qdS )a(  
    This function populates the "translation_key", and "locale" fields on model instances that were created
    before wagtail-localize was added to the site.

    This can be called from a data migration, or instead you could use the "bootstrap_translatable_models"
    management command.
    T)Ztranslation_key__isnullrZ   rV   )Zupdate_fieldsN)	r'   rv   r   iteratorr   r   rZ   rV   save)r   rV   r1   r   r   r   bootstrap_translatable_model|  s
    	
r   c                       s   e Zd Zd fdd	Z  ZS )BootstrapTranslatableModelNc                    s:    d u rt tj  fdd}dd }t || d S )Nc                    s0   |  }|  d}|jj d}t|| d S )Nzwagtailcore.Localer   )Z	get_modelr'   r   r   )r   schema_editorr   r"   rV   r   model_stringr   r   forwards  s    

z5BootstrapTranslatableModel.__init__.<locals>.forwardsc                 S   s   d S r   r   )r   r   r   r   r   	backwards  s    z6BootstrapTranslatableModel.__init__.<locals>.backwards)r   r   r(   r3   __init__)r   r   r   r   r   r7   r   r   r     s    z#BootstrapTranslatableModel.__init__)N)r   r    r!   r   rQ   r   r   r7   r   r     s   r   c                       sV   e Zd ZdZejdddZejeej	ddddZ
e fddZG d	d
 d
Z  ZS )BootstrapTranslatableMixina  
    A version of TranslatableMixin without uniqueness constraints.

    This is to make it easy to transition existing models to being translatable.

    The process is as follows:
     - Add BootstrapTranslatableMixin to the model
     - Run makemigrations
     - Create a data migration for each app, then use the BootstrapTranslatableModel operation in
       wagtail.models on each model in that app
     - Change BootstrapTranslatableMixin to TranslatableMixin
     - Run makemigrations again
     - Migrate!
    TF)nullrT   rU   )rW   r   rX   rT   c                    s   t t| jf i |S r   )r3   rR   re   )r*   r6   r7   r   r   re     s    z BootstrapTranslatableMixin.checkc                   @   s   e Zd ZdZdS )zBootstrapTranslatableMixin.MetaTN)r   r    r!   r[   r   r   r   r   r&     s   r&   )r   r    r!   __doc__r   r   rZ   r   r"   r   rV   rL   re   r&   rQ   r   r   r7   r   r     s   r   Fc                    sN   dd t  D }| du rJt  |D ]} |  q$ fdd|D }|S )z
    Returns a list of all concrete models that inherit from TranslatableMixin.
    By default, this only includes models that are direct children of TranslatableMixin,
    to get all models, set the include_subclasses attribute to True.
    c                 S   s"   g | ]}t |tr|jjs|qS r   )r   rR   rh   r[   r_   r   r   r   r   r     s   z+get_translatable_models.<locals>.<listcomp>Fc                    s   g | ]}| v r|qS r   r   r   Zroot_translatable_modelsr   r   r     s   )r   Z
get_modelsr]   addrf   )Zinclude_subclassesZtranslatable_modelsr   r   r   r   get_translatable_models  s    
r   c                 K   s@   t |tsd S |jd urd S |d r2t |_d S | |_d S )Nraw)r   rR   rr   r"   r+   rV   r   )r0   r1   r6   r   r   r   set_locale_on_new_instance  s    


r   )F)+r   Zdjango.appsr   Zdjango.confr   Zdjango.corer   Z	django.dbr   r   r   Zdjango.db.models.signalsr   Zdjango.dispatchr	   Zdjango.utilsr
   Zdjango.utils.encodingr   Zdjango.utils.translationr   r   Zmodelcluster.fieldsr   Z$wagtail.actions.copy_for_translationr   Zwagtail.coreutilsr   r   Zwagtail.signalsr   r   rK   r   r   r"   rR   r   Z	RunPythonr   r   r   r   r   r   r   r   <module>   s2   
  L
