Compare commits

..

No commits in common. "master" and "v0.10.2" have entirely different histories.

14 changed files with 42 additions and 452 deletions

View file

@ -1,45 +1,34 @@
language: python
python:
- "3.8"
- "3.6"
env:
- WAGTAIL="wagtail>=2.7,<2.8" DB=sqlite
- WAGTAIL="wagtail>=2.4,<2.5" DB=sqlite
matrix:
include:
# Latest Wagtail version
- env: WAGTAIL="wagtail>=2.7,<2.8" DB=postgres
- env: WAGTAIL="wagtail>=2.7,<2.8" DB=mysql
- python: "3.8"
- python: "3.7"
- env: WAGTAIL="wagtail>=2.4,<2.5" DB=sqlite
- env: WAGTAIL="wagtail>=2.4,<2.5" DB=postgres
- env: WAGTAIL="wagtail>=2.4,<2.5" DB=mysql
- python: "3.6"
- python: "3.5"
- python: "3.4"
# Past Wagtail versions
- python: "3.7"
env: WAGTAIL="wagtail>=2.6,<2.7"
- python: "3.7"
env: WAGTAIL="wagtail>=2.5,<2.6"
- python: "3.4" # Wagtail 2.5 was the last to support python 3.4
env: WAGTAIL="wagtail>=2.5,<2.6"
- python: "3.7"
env: WAGTAIL="wagtail>=2.4,<2.5"
- python: "3.7"
- python: "3.6"
env: WAGTAIL="wagtail>=2.3,<2.4"
- python: "3.7"
- python: "3.6"
env: WAGTAIL="wagtail>=2.2,<2.3"
- python: "3.7"
- python: "3.6"
env: WAGTAIL="wagtail>=2.1,<2.2"
- python: "3.7"
- python: "3.6"
env: WAGTAIL="wagtail>=2.0,<2.1"
- python: "2.7" # Wagtail 1.13 was the latest tested against 2.7
env: WAGTAIL="wagtail>=1.13,<1.14"
- python: "3.7"
- python: "3.6"
env: WAGTAIL="wagtail>=1.13,<1.14"
- python: "2.7"
env: WAGTAIL="wagtail>=1.12,<1.13"
- python: "3.7"
- python: "3.6"
env: WAGTAIL="wagtail>=1.12,<1.13"
services:
- mysql
- postgresql
addons:
postgresql: "9.4"
before_script:
@ -48,7 +37,7 @@ before_script:
install:
- pip install --upgrade -q pip setuptools
- if [[ $DB == mysql ]] && [[ ${TRAVIS_PYTHON_VERSION:0:1} == "2" ]]; then pip install -q mysql-python; elif [[ $DB == mysql ]] && [[ ${TRAVIS_PYTHON_VERSION:0:1} == "3" ]]; then pip install -q mysqlclient; fi
- if [[ $DB == postgres ]]; then pip install -q 'psycopg2-binary'; fi
- if [[ $DB == postgres ]]; then pip install -q 'psycopg2-binary<2.8'; fi
- pip install $WAGTAIL
- pip install -e .
script:

View file

@ -22,7 +22,6 @@ Contributors
* Raphael Grill
* Tom Dyson
* Tim Tan
* Benedikt Willi
.. _Django-modeltranslation: https://github.com/deschler/django-modeltranslation

View file

@ -3,6 +3,5 @@ recursive-include docs *.rst conf.py Makefile make.bat
recursive-include wagtail_modeltranslation/static *
recursive-include wagtail_modeltranslation/management *
recursive-include wagtail_modeltranslation/templatetags *
recursive-include wagtail_modeltranslation/templates *
global-exclude *.pyc
global-exclude *.DS_Store

View file

@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: wagtail-modeltranslation
Version: 0.10.6
Version: 0.10.1
Summary: Translates Wagtail CMS models using a registration approach.
Home-page: https://github.com/infoportugal/wagtail-modeltranslation
Author: InfoPortugal S.A.

View file

@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.10.6
current_version = 0.10.2
commit = True
tag = True

View file

@ -44,8 +44,7 @@ setup(
'wagtail_modeltranslation.migrate.management',
'wagtail_modeltranslation.migrate.management.commands'],
package_data={'wagtail_modeltranslation': ['static/wagtail_modeltranslation/css/*.css',
'static/wagtail_modeltranslation/js/*.js',
'templates/*.html']},
'static/wagtail_modeltranslation/js/*.js']},
install_requires=['wagtail>=1.12', 'django-modeltranslation>=0.13'],
classifiers=[
'Programming Language :: Python',
@ -55,7 +54,6 @@ setup(
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Operating System :: OS Independent',
'Environment :: Web Environment',
'Intended Audience :: Developers',

67
tox.ini
View file

@ -1,17 +1,5 @@
[tox]
envlist =
py38-2.7.X,
py37-2.7.X,
py36-2.7.X,
py35-2.7.X,
py34-2.7.X,
py37-2.6.X,
py36-2.6.X,
py35-2.6.X,
py37-2.5.X,
py36-2.5.X,
py35-2.5.X,
py34-2.5.X,
py37-2.4.X,
py36-2.4.X,
py35-2.4.X,
@ -41,61 +29,6 @@ envlist =
commands =
{envpython} runtests.py
[testenv:py38-2.7.X]
basepython = python3.8
deps =
wagtail>=2.7,<2.8
[testenv:py37-2.7.X]
basepython = python3.7
deps =
wagtail>=2.7,<2.8
[testenv:py36-2.7.X]
basepython = python3.6
deps =
wagtail>=2.7,<2.8
[testenv:py35-2.7.X]
basepython = python3.5
deps =
wagtail>=2.7,<2.8
[testenv:py37-2.6.X]
basepython = python3.7
deps =
wagtail>=2.6,<2.7
[testenv:py36-2.6.X]
basepython = python3.6
deps =
wagtail>=2.6,<2.7
[testenv:py35-2.6.X]
basepython = python3.5
deps =
wagtail>=2.6,<2.7
[testenv:py37-2.5.X]
basepython = python3.7
deps =
wagtail>=2.5,<2.6
[testenv:py36-2.5.X]
basepython = python3.6
deps =
wagtail>=2.5,<2.6
[testenv:py35-2.5.X]
basepython = python3.5
deps =
wagtail>=2.5,<2.6
[testenv:py34-2.5.X]
basepython = python3.4
deps =
wagtail>=2.5,<2.6
[testenv:py37-2.4.X]
basepython = python3.7
deps =

View file

@ -1,3 +1,3 @@
# coding: utf-8
__version__ = '0.10.6'
__version__ = '0.10.2'
default_app_config = 'wagtail_modeltranslation.apps.ModeltranslationConfig'

View file

@ -45,7 +45,6 @@ except ImportError:
from wagtail.wagtailsnippets.views.snippets import SNIPPET_EDIT_HANDLERS
from wagtail_modeltranslation.settings import CUSTOM_SIMPLE_PANELS, CUSTOM_COMPOSED_PANELS, TRANSLATE_SLUGS
from wagtail_modeltranslation.utils import compare_class_tree_depth
from wagtail import VERSION
logger = logging.getLogger('wagtail.core')
@ -141,11 +140,8 @@ class WagtailTranslator(object):
translation_registered_fields = translator.get_options_for_model(model).fields
panels = filter(lambda field: field.field_name not in translation_registered_fields, panels)
edit_handler = ObjectList(panels)
if VERSION < (2, 5):
SNIPPET_EDIT_HANDLERS[model] = edit_handler.bind_to_model(model)
else:
SNIPPET_EDIT_HANDLERS[model] = edit_handler.bind_to(model=model)
SNIPPET_EDIT_HANDLERS[model] = edit_handler.bind_to_model(model)
def _patch_panels(self, panels_list, related_model=None):
"""

View file

@ -1,107 +0,0 @@
# coding: utf-8
from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
try:
from wagtail.core.models import Page
from wagtail.admin import widgets
from wagtail.admin.forms.pages import CopyForm
except ImportError:
from wagtail.wagtailcore.models import Page
from wagtail.wagtailadmin import widgets
from wagtail.wagtailadmin.forms import CopyForm
class PatchedCopyForm(CopyForm):
def __init__(self, *args, **kwargs):
# CopyPage must be passed a 'page' kwarg indicating the page to be copied
self.page = kwargs.pop('page')
self.user = kwargs.pop('user', None)
can_publish = kwargs.pop('can_publish')
super(CopyForm, self).__init__(*args, **kwargs)
#self.fields['new_title'] = forms.CharField(initial=self.page.title, label=_("New title"))
for code, name in settings.LANGUAGES:
locale_title = "new_title_{}".format(code)
locale_label = "{} [{}]".format(_("New title"), code)
self.fields[locale_title] = forms.CharField(initial=self.page.title, label=locale_label)
#self.fields['new_slug'] = forms.SlugField(initial=self.page.slug, label=_("New slug"))
for code, name in settings.LANGUAGES:
locale_title = "new_slug_{}".format(code)
locale_label = "{} [{}]".format(_("New slug"), code)
self.fields[locale_title] = forms.SlugField(initial=self.page.slug, label=locale_label)
self.fields['new_parent_page'] = forms.ModelChoiceField(
initial=self.page.get_parent(),
queryset=Page.objects.all(),
widget=widgets.AdminPageChooser(can_choose_root=True, user_perms='copy_to'),
label=_("New parent page"),
help_text=_("This copy will be a child of this given parent page.")
)
pages_to_copy = self.page.get_descendants(inclusive=True)
subpage_count = pages_to_copy.count() - 1
if subpage_count > 0:
self.fields['copy_subpages'] = forms.BooleanField(
required=False, initial=True, label=_("Copy subpages"),
help_text=ungettext(
"This will copy %(count)s subpage.",
"This will copy %(count)s subpages.",
subpage_count) % {'count': subpage_count})
if can_publish:
pages_to_publish_count = pages_to_copy.live().count()
if pages_to_publish_count > 0:
# In the specific case that there are no subpages, customise the field label and help text
if subpage_count == 0:
label = _("Publish copied page")
help_text = _("This page is live. Would you like to publish its copy as well?")
else:
label = _("Publish copies")
help_text = ungettext(
"%(count)s of the pages being copied is live. Would you like to publish its copy?",
"%(count)s of the pages being copied are live. Would you like to publish their copies?",
pages_to_publish_count) % {'count': pages_to_publish_count}
self.fields['publish_copies'] = forms.BooleanField(
required=False, initial=True, label=label, help_text=help_text
)
def clean(self):
cleaned_data = super(CopyForm, self).clean()
# Make sure the slug isn't already in use
# slug = cleaned_data.get('new_slug')
# New parent page given in form or parent of source, if parent_page is empty
parent_page = cleaned_data.get('new_parent_page') or self.page.get_parent()
# check if user is allowed to create a page at given location.
if not parent_page.permissions_for_user(self.user).can_add_subpage():
raise ValidationError({
'new_parent_page': _("You do not have permission to copy to page \"%(page_title)s\"") % {'page_title': parent_page.get_admin_display_title()}
})
# Count the pages with the same slug within the context of our copy's parent page
for code, name in settings.LANGUAGES:
locale_slug = "new_slug_{}".format(code)
slug = cleaned_data.get(locale_slug)
param = 'slug_' + code
query = {param: slug}
if slug and parent_page.get_children().filter(**query).count():
raise ValidationError({
locale_slug: _("This slug is already in use within the context of its parent page \"%s\"" % parent_page)
})
# Don't allow recursive copies into self
if cleaned_data.get('copy_subpages') and (self.page == parent_page or parent_page.is_descendant_of(self.page)):
raise ValidationError({
'new_parent_page': _("You cannot copy a page into itself when copying subpages")
})
return cleaned_data

View file

@ -7,47 +7,22 @@ $(document).ready(function(){
for (var i = 0; i < allStreamFields.length; i++) {
//Current Field with all content
var currentStreamField = allStreamFields[i];
//Current field header
var header;
//Current field name
var fieldLang = "";
//Current field language
var fieldName = "";
if(versionCompare(WAGTAIL_VERSION,'2.6.0', {zeroExtend: true})===-1){
// Wagtail < 2.6
header = $(currentStreamField).children('h2')[0];
//Search for the input field so that we can get is id to know the field's name.
var streamFieldDiv = $(currentStreamField).find('div.sequence-container.sequence-type-stream')[0];
var fieldInfos = $(streamFieldDiv).find('input')[0].id.split('-')[0];
var lastUnderscore = fieldInfos.lastIndexOf("_");
fieldName = fieldInfos.substring(0, lastUnderscore);
fieldLang = fieldInfos.substring(lastUnderscore + 1, fieldInfos.length);
} else if(versionCompare(WAGTAIL_VERSION,'2.7.0', {zeroExtend: true})===-1){
// Wagtail < 2.7
header = $(currentStreamField).children('.title-wrapper')[0];
//Search for the input field so that we can get is id to know the field's name.
var streamFieldDiv = $(currentStreamField).find('div.sequence-container.sequence-type-stream')[0];
var fieldInfos = $(streamFieldDiv).find('input')[0].id.split('-')[0];
var lastUnderscore = fieldInfos.lastIndexOf("_");
fieldName = fieldInfos.substring(0, lastUnderscore);
fieldLang = fieldInfos.substring(lastUnderscore + 1, fieldInfos.length);
} else {
// Wagtail >= 2.7
header = $(currentStreamField).children('.title-wrapper')[0];
//Search for the input field so that we can get is id to know the field's name.
var streamFieldDiv = $(currentStreamField).find('.field-content')[0];
var fieldInfos = $(streamFieldDiv).find('input')[0].id.split('-')[0];
var lastUnderscore = fieldInfos.lastIndexOf("_");
fieldName = fieldInfos.substring(0, lastUnderscore);
fieldLang = fieldInfos.substring(lastUnderscore + 1, fieldInfos.length);
}
//Current Field header
var header = $(currentStreamField).children('h2')[0];
//Search for the input field so that we can get is id to know the field's name.
var streamFieldDiv = $(currentStreamField).find('div.sequence-container.sequence-type-stream')[0];
var fieldInfos = $(streamFieldDiv).children('input')[0].id.split('-')[0];
var lastUnderscore = fieldInfos.lastIndexOf("_");
var fieldName = fieldInfos.substring(0, lastUnderscore);
var fieldLang = fieldInfos.substring(lastUnderscore + 1, fieldInfos.length);
//The cycle to create the buttons for copy each language field
header.innerHTML += '<div class="translation-field-copy-wrapper">Copy content from: </div>';
var copyContentString = 'Copy content from';
header.innerHTML += '<div class="translation-field-copy-wrapper">'+copyContentString+': </div>';
for (var j = 0; j < langs.length; j++) {
if (fieldLang != langs[j]) {
var currentFieldID = fieldName + '_' + fieldLang;
var targetFieldID = fieldName + '_' + langs [j];
$(header).children('.translation-field-copy-wrapper')[0].innerHTML += '<button class="button translation-field-copy" current-lang-code="' + currentFieldID + '" data-lang-code="' + targetFieldID + '">' + langs[j] + '</button>';
$(header).children('.translation-field-copy-wrapper')[0].innerHTML += '<button class="translation-field-copy" current-lang-code="'+ currentFieldID +'" data-lang-code="'+ targetFieldID +'">'+langs[j]+'</button>';
};
};
};
@ -80,11 +55,11 @@ function requestCopyField(originID, targetID) {
})
.done(function(data) {
/* Put the html data in the targetID field */
var wrapperDiv = $('#' + targetID + '-count').parents('.input')[0];
var wrapperDiv = $("#"+targetID+"-count").parents('.input')[0];
$(wrapperDiv).html(data);
})
.fail(function(error) {
console.log('wagtail-modeltranslation error: ' + error.responseText);
console.log("wagtail-modeltranslation error: %s", error.responseText);
})
}

View file

@ -1,78 +0,0 @@
/**
* Compares two software version numbers (e.g. "1.7.1" or "1.2b").
*
* This function was born in http://stackoverflow.com/a/6832721.
*
* @param {string} v1 The first version to be compared.
* @param {string} v2 The second version to be compared.
* @param {object} [options] Optional flags that affect comparison behavior.
* @param {boolean} [options.lexicographical = false] Switch to compare version strings lexicographically instead of naturally.
* @param {boolean} [options.zeroExtend = false] Switch to pad version with "zero" parts instead to be considered smaller.
* <ul>
* <li>
* <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
* naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
* "1.2".
* </li>
* <li>
* <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
* this case the shorter string will be padded with "zero" parts instead of being considered smaller.
* </li>
* </ul>
* @returns {number|NaN}
* <ul>
* <li>0 if the versions are equal</li>
* <li>a negative integer (-1) if v1 < v2</li>
* <li>a positive integer (1) if v1 > v2</li>
* <li>NaN if either version string is in the wrong format</li>
* </ul>
*
* @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
* @license This function is in the public domain. Do what you want with it, no strings attached.
*/
function versionCompare(v1, v2, options) {
var lexicographical = options && options.lexicographical,
zeroExtend = options && options.zeroExtend,
v1parts = v1.split('.'),
v2parts = v2.split('.');
function isValidPart(x) {
return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
}
if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
return NaN;
}
if (zeroExtend) {
while (v1parts.length < v2parts.length) v1parts.push("0");
while (v2parts.length < v1parts.length) v2parts.push("0");
}
if (!lexicographical) {
v1parts = v1parts.map(Number);
v2parts = v2parts.map(Number);
}
for (var i = 0; i < v1parts.length; ++i) {
if (v2parts.length == i) {
return 1;
}
if (v1parts[i] == v2parts[i]) {
continue;
}
else if (v1parts[i] > v2parts[i]) {
return 1;
}
else {
return -1;
}
}
if (v1parts.length != v2parts.length) {
return -1;
}
return 0;
}

View file

@ -1,31 +0,0 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% blocktrans with title=page.get_admin_display_title %}Copy {{ title }}{% endblocktrans %}{% endblock %}
{% block content %}
{% trans "Copy" as copy_str %}
{% include "wagtailadmin/shared/header.html" with title=copy_str subtitle=page.get_admin_display_title icon="doc-empty-inverse" %}
<div class="nice-padding">
<form action="{% url 'wagtailadmin_pages:copy' page.id %}" method="POST" novalidate>
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}" />
<ul class="fields">
{% for field in form.visible_fields %}
{% include "wagtailadmin/shared/field_as_li.html" with field=field %}
{% endfor %}
{% if form.copy_subpages %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.copy_subpages %}
{% endif %}
</ul>
<input type="submit" value="{% trans 'Copy this page' %}" class="button">
</form>
</div>
{% endblock %}
{% block extra_js %}
{{ block.super }}
{% include "wagtailadmin/pages/_editor_js.html" %}
{% endblock %}

View file

@ -2,35 +2,24 @@
import json
from django.core.exceptions import PermissionDenied
from six import iteritems
from django.conf import settings
from django.conf.urls import url
from django.http import HttpResponse, QueryDict
from django.shortcuts import redirect, render
from django.templatetags.static import static
from django.utils.html import escape, format_html, format_html_join
from django.utils.translation import ugettext as _
from django.views.decorators.csrf import csrf_exempt
from wagtail_modeltranslation import settings as wmt_settings
from modeltranslation import settings as mt_settings
from .patch_wagtailadmin_forms import PatchedCopyForm
try:
from wagtail.core import hooks
from wagtail.core.models import Page
from wagtail.core.rich_text.pages import PageLinkHandler
from wagtail.core import __version__ as WAGTAIL_VERSION
from wagtail.admin import messages
from wagtail.admin.views.pages import get_valid_next_url_from_request
except ImportError:
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.rich_text import PageLinkHandler
from wagtail.wagtailcore import __version__ as WAGTAIL_VERSION
from wagtail.wagtailadmin import messages
from wagtail.wagtailadmin.views.pages import get_valid_next_url_from_request
@hooks.register('insert_editor_js')
@ -39,9 +28,9 @@ def translated_slugs():
'wagtail_modeltranslation/js/wagtail_translated_slugs.js',
]
js_includes = format_html_join('\n', '<script src="{0}"></script>', (
(static(filename),) for filename in js_files)
)
js_includes = format_html_join('\n', '<script src="{0}{1}"></script>', (
(settings.STATIC_URL, filename) for filename in js_files)
)
lang_codes = []
for lang in settings.LANGUAGES:
@ -131,26 +120,21 @@ def streamfields_translation_copy():
# includes the javascript file in the html file
js_files = [
'wagtail_modeltranslation/js/version_compare.js',
'wagtail_modeltranslation/js/copy_stream_fields.js',
]
js_includes = format_html_join('\n', '<script src="{0}"></script>', (
(static(filename),) for filename in js_files)
)
js_includes = format_html_join('\n', '<script src="{0}{1}"></script>', (
(settings.STATIC_URL, filename) for filename in js_files)
)
js_wagtail_version = """
<script>
var WAGTAIL_VERSION='{wagtail_version}';
</script>
""".format(wagtail_version=WAGTAIL_VERSION)
return format_html(js_wagtail_version) + js_includes
return js_includes
@hooks.register('insert_editor_css')
def modeltranslation_page_editor_css():
filename = 'wagtail_modeltranslation/css/page_editor_modeltranslation.css'
return format_html('<link rel="stylesheet" href="{}" >'.format(static(filename)))
return format_html('<link rel="stylesheet" href="'
+ settings.STATIC_URL
+ 'wagtail_modeltranslation/css/page_editor_modeltranslation.css" >')
@hooks.register('register_rich_text_link_handler')
@ -176,70 +160,3 @@ def register_localized_page_link_handler():
return "<a>"
return ('page', LocalizedPageLinkHandler)
@hooks.register('before_copy_page')
def before_copy_page(request, page):
parent_page = page.get_parent()
can_publish = parent_page.permissions_for_user(request.user).can_publish_subpage()
form = PatchedCopyForm(request.POST or None, user=request.user, page=page, can_publish=can_publish)
next_url = get_valid_next_url_from_request(request)
if request.method == 'POST':
# Prefill parent_page in case the form is invalid (as prepopulated value for the form field,
# because ModelChoiceField seems to not fall back to the user given value)
parent_page = Page.objects.get(id=request.POST['new_parent_page'])
if form.is_valid():
# Receive the parent page (this should never be empty)
if form.cleaned_data['new_parent_page']:
parent_page = form.cleaned_data['new_parent_page']
if not page.permissions_for_user(request.user).can_copy_to(parent_page,
form.cleaned_data.get('copy_subpages')):
raise PermissionDenied
# Re-check if the user has permission to publish subpages on the new parent
can_publish = parent_page.permissions_for_user(request.user).can_publish_subpage()
update_attrs = {}
for code, name in settings.LANGUAGES:
slug = "slug_{}".format(code)
title = "title_{}".format(code)
update_attrs[slug] = form.cleaned_data["new_{}".format(slug)]
update_attrs[title] = form.cleaned_data["new_{}".format(title)]
# Copy the page
new_page = page.copy(
recursive=form.cleaned_data.get('copy_subpages'),
to=parent_page,
update_attrs=update_attrs,
keep_live=(can_publish and form.cleaned_data.get('publish_copies')),
user=request.user,
)
# Give a success message back to the user
if form.cleaned_data.get('copy_subpages'):
messages.success(
request,
_("Page '{0}' and {1} subpages copied.").format(
page.get_admin_display_title(), new_page.get_descendants().count())
)
else:
messages.success(request, _("Page '{0}' copied.").format(page.get_admin_display_title()))
for fn in hooks.get_hooks('after_copy_page'):
result = fn(request, page, new_page)
if hasattr(result, 'status_code'):
return result
# Redirect to explore of parent page
if next_url:
return redirect(next_url)
return redirect('wagtailadmin_explore', parent_page.id)
return render(request, 'modeltranslation_copy.html', {
'page': page,
'form': form,
'next': next_url
})