mirror of
https://github.com/Hopiu/wagtail-modeltranslation.git
synced 2026-05-20 13:01:57 +00:00
Compare commits
48 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
765ac7a19d | ||
|
|
57d0a348bf | ||
|
|
154acd006c | ||
|
|
18ed10a2a9 | ||
|
|
a92d287a6e | ||
|
|
187e524ed2 | ||
|
|
e742a93f4c | ||
|
|
1366c86151 | ||
|
|
8b945cec37 | ||
|
|
40b2b01648 | ||
|
|
a170f7a213 | ||
|
|
4456f6f902 | ||
|
|
80def8ecde | ||
|
|
29404348cb | ||
|
|
1495f7278a | ||
|
|
6fb4725f65 | ||
|
|
3191abde46 | ||
|
|
86c4711e48 | ||
|
|
6cbd98ee54 | ||
|
|
3034d5807c | ||
|
|
07e0e98b47 | ||
|
|
88e5895c5b | ||
|
|
55fff643d3 | ||
|
|
d630f9c988 | ||
|
|
fe0cd4c0b6 | ||
|
|
8a1a9eb94b | ||
|
|
425438acd1 | ||
|
|
ff8a75479c | ||
|
|
af888092bf | ||
|
|
34e67bd0ed | ||
|
|
da68dd1e40 | ||
|
|
eb5eee8092 | ||
|
|
5ec163b020 | ||
|
|
75facc5f22 | ||
|
|
f9afc8dd17 | ||
|
|
f52993d73c | ||
|
|
58fdc7148b | ||
|
|
f1b04f9202 | ||
|
|
30a6ada4de | ||
|
|
bbe19792c9 | ||
|
|
640d5202c9 | ||
|
|
5ef04f30f2 | ||
|
|
b883f051f3 | ||
|
|
8deb0424f1 | ||
|
|
7d9b42f542 | ||
|
|
4f0b07789c | ||
|
|
372a2f31df | ||
|
|
304554f405 |
19 changed files with 599 additions and 65 deletions
37
.travis.yml
37
.travis.yml
|
|
@ -1,34 +1,45 @@
|
||||||
language: python
|
language: python
|
||||||
python:
|
python:
|
||||||
- "3.6"
|
- "3.8"
|
||||||
env:
|
env:
|
||||||
- WAGTAIL="wagtail>=2.4,<2.5" DB=sqlite
|
- WAGTAIL="wagtail>=2.7,<2.8" DB=sqlite
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
# Latest Wagtail version
|
# Latest Wagtail version
|
||||||
- env: WAGTAIL="wagtail>=2.4,<2.5" DB=sqlite
|
- env: WAGTAIL="wagtail>=2.7,<2.8" DB=postgres
|
||||||
- env: WAGTAIL="wagtail>=2.4,<2.5" DB=postgres
|
- env: WAGTAIL="wagtail>=2.7,<2.8" DB=mysql
|
||||||
- env: WAGTAIL="wagtail>=2.4,<2.5" DB=mysql
|
- python: "3.8"
|
||||||
|
- python: "3.7"
|
||||||
- python: "3.6"
|
- python: "3.6"
|
||||||
- python: "3.5"
|
- python: "3.5"
|
||||||
- python: "3.4"
|
|
||||||
# Past Wagtail versions
|
# Past Wagtail versions
|
||||||
- python: "3.6"
|
- 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"
|
||||||
env: WAGTAIL="wagtail>=2.3,<2.4"
|
env: WAGTAIL="wagtail>=2.3,<2.4"
|
||||||
- python: "3.6"
|
- python: "3.7"
|
||||||
env: WAGTAIL="wagtail>=2.2,<2.3"
|
env: WAGTAIL="wagtail>=2.2,<2.3"
|
||||||
- python: "3.6"
|
- python: "3.7"
|
||||||
env: WAGTAIL="wagtail>=2.1,<2.2"
|
env: WAGTAIL="wagtail>=2.1,<2.2"
|
||||||
- python: "3.6"
|
- python: "3.7"
|
||||||
env: WAGTAIL="wagtail>=2.0,<2.1"
|
env: WAGTAIL="wagtail>=2.0,<2.1"
|
||||||
- python: "2.7" # Wagtail 1.13 was the latest tested against 2.7
|
- python: "2.7" # Wagtail 1.13 was the latest tested against 2.7
|
||||||
env: WAGTAIL="wagtail>=1.13,<1.14"
|
env: WAGTAIL="wagtail>=1.13,<1.14"
|
||||||
- python: "3.6"
|
- python: "3.7"
|
||||||
env: WAGTAIL="wagtail>=1.13,<1.14"
|
env: WAGTAIL="wagtail>=1.13,<1.14"
|
||||||
- python: "2.7"
|
- python: "2.7"
|
||||||
env: WAGTAIL="wagtail>=1.12,<1.13"
|
env: WAGTAIL="wagtail>=1.12,<1.13"
|
||||||
- python: "3.6"
|
- python: "3.7"
|
||||||
env: WAGTAIL="wagtail>=1.12,<1.13"
|
env: WAGTAIL="wagtail>=1.12,<1.13"
|
||||||
|
services:
|
||||||
|
- mysql
|
||||||
|
- postgresql
|
||||||
addons:
|
addons:
|
||||||
postgresql: "9.4"
|
postgresql: "9.4"
|
||||||
before_script:
|
before_script:
|
||||||
|
|
@ -37,7 +48,7 @@ before_script:
|
||||||
install:
|
install:
|
||||||
- pip install --upgrade -q pip setuptools
|
- 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 == 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; fi
|
- if [[ $DB == postgres ]]; then pip install -q 'psycopg2-binary'; fi
|
||||||
- pip install $WAGTAIL
|
- pip install $WAGTAIL
|
||||||
- pip install -e .
|
- pip install -e .
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ Contributors
|
||||||
* Raphael Grill
|
* Raphael Grill
|
||||||
* Tom Dyson
|
* Tom Dyson
|
||||||
* Tim Tan
|
* Tim Tan
|
||||||
|
* Benedikt Willi
|
||||||
|
|
||||||
|
|
||||||
.. _Django-modeltranslation: https://github.com/deschler/django-modeltranslation
|
.. _Django-modeltranslation: https://github.com/deschler/django-modeltranslation
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,11 @@
|
||||||
|
v0.6.0rc2:
|
||||||
|
- added RichTextFieldPanel to the default list of patched panels
|
||||||
|
- added settings to allow the patching of custom panels
|
||||||
|
- slug auto-population is now made the same way as wagtail (no changes in live pages)
|
||||||
|
- Fixed: When adding a page link in a translated RichTextField the link was always to the default language version of that page
|
||||||
|
- Fixed: Copy content of streamfield fails with 414 Request-URI Too Long
|
||||||
|
- Fixed: Panel patching failed with the error "AttributeError: 'list' object has no attribute 'children'"
|
||||||
|
|
||||||
v0.6.0rc1:
|
v0.6.0rc1:
|
||||||
- django-modeltranslation is now a dependency.
|
- django-modeltranslation is now a dependency.
|
||||||
- added compatibility with Python 3 (3.3, 3.4, 3.5).
|
- added compatibility with Python 3 (3.3, 3.4, 3.5).
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,6 @@ recursive-include docs *.rst conf.py Makefile make.bat
|
||||||
recursive-include wagtail_modeltranslation/static *
|
recursive-include wagtail_modeltranslation/static *
|
||||||
recursive-include wagtail_modeltranslation/management *
|
recursive-include wagtail_modeltranslation/management *
|
||||||
recursive-include wagtail_modeltranslation/templatetags *
|
recursive-include wagtail_modeltranslation/templatetags *
|
||||||
|
recursive-include wagtail_modeltranslation/templates *
|
||||||
global-exclude *.pyc
|
global-exclude *.pyc
|
||||||
global-exclude *.DS_Store
|
global-exclude *.DS_Store
|
||||||
|
|
|
||||||
2
PKG-INFO
2
PKG-INFO
|
|
@ -1,6 +1,6 @@
|
||||||
Metadata-Version: 1.0
|
Metadata-Version: 1.0
|
||||||
Name: wagtail-modeltranslation
|
Name: wagtail-modeltranslation
|
||||||
Version: 0.10b1
|
Version: 0.10.6
|
||||||
Summary: Translates Wagtail CMS models using a registration approach.
|
Summary: Translates Wagtail CMS models using a registration approach.
|
||||||
Home-page: https://github.com/infoportugal/wagtail-modeltranslation
|
Home-page: https://github.com/infoportugal/wagtail-modeltranslation
|
||||||
Author: InfoPortugal S.A.
|
Author: InfoPortugal S.A.
|
||||||
|
|
|
||||||
1
Pipfile
1
Pipfile
|
|
@ -8,3 +8,4 @@ bumpversion = "*"
|
||||||
wheel = "*"
|
wheel = "*"
|
||||||
|
|
||||||
[dev-packages]
|
[dev-packages]
|
||||||
|
twine = "*"
|
||||||
|
|
|
||||||
122
Pipfile.lock
generated
122
Pipfile.lock
generated
|
|
@ -1,12 +1,10 @@
|
||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "8a50cf92fd274fbd58348130a7ab3568a8f694ad373cb5a67d45da7a46b96827"
|
"sha256": "191a6f860a13836c57a16587784ceca36f791bfae1270cf937286a496e891114"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {},
|
||||||
"python_version": "3.6"
|
|
||||||
},
|
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"name": "pypi",
|
"name": "pypi",
|
||||||
|
|
@ -26,12 +24,120 @@
|
||||||
},
|
},
|
||||||
"wheel": {
|
"wheel": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:1ae8153bed701cb062913b72429bcf854ba824f973735427681882a688cb55ce",
|
"sha256:5e79117472686ac0c4aef5bad5172ea73a1c2d1646b808c35926bd26bdfb0c08",
|
||||||
"sha256:9cdc8ab2cc9c3c2e2727a4b67c22881dbb0e1c503d592992594c5e131c867107"
|
"sha256:62fcfa03d45b5b722539ccbc07b190e4bfff4bb9e3a4d470dd9f6a0981002565"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.31.0"
|
"version": "==0.33.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"develop": {}
|
"develop": {
|
||||||
|
"bleach": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:213336e49e102af26d9cde77dd2d0397afabc5a6bf2fed985dc35b5d1e285a16",
|
||||||
|
"sha256:3fdf7f77adcf649c9911387df51254b813185e32b2c6619f690b593a617e19fa"
|
||||||
|
],
|
||||||
|
"version": "==3.1.0"
|
||||||
|
},
|
||||||
|
"certifi": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
|
||||||
|
"sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
|
||||||
|
],
|
||||||
|
"version": "==2019.3.9"
|
||||||
|
},
|
||||||
|
"chardet": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||||
|
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||||
|
],
|
||||||
|
"version": "==3.0.4"
|
||||||
|
},
|
||||||
|
"docutils": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6",
|
||||||
|
"sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274",
|
||||||
|
"sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"
|
||||||
|
],
|
||||||
|
"version": "==0.14"
|
||||||
|
},
|
||||||
|
"idna": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
|
||||||
|
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
|
||||||
|
],
|
||||||
|
"version": "==2.8"
|
||||||
|
},
|
||||||
|
"pkginfo": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb",
|
||||||
|
"sha256:a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32"
|
||||||
|
],
|
||||||
|
"version": "==1.5.0.1"
|
||||||
|
},
|
||||||
|
"pygments": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127",
|
||||||
|
"sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"
|
||||||
|
],
|
||||||
|
"version": "==2.4.2"
|
||||||
|
},
|
||||||
|
"readme-renderer": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:bb16f55b259f27f75f640acf5e00cf897845a8b3e4731b5c1a436e4b8529202f",
|
||||||
|
"sha256:c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d"
|
||||||
|
],
|
||||||
|
"version": "==24.0"
|
||||||
|
},
|
||||||
|
"requests": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
|
||||||
|
"sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
|
||||||
|
],
|
||||||
|
"version": "==2.22.0"
|
||||||
|
},
|
||||||
|
"requests-toolbelt": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f",
|
||||||
|
"sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"
|
||||||
|
],
|
||||||
|
"version": "==0.9.1"
|
||||||
|
},
|
||||||
|
"six": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
|
||||||
|
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
|
||||||
|
],
|
||||||
|
"version": "==1.12.0"
|
||||||
|
},
|
||||||
|
"tqdm": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0a860bf2683fdbb4812fe539a6c22ea3f1777843ea985cb8c3807db448a0f7ab",
|
||||||
|
"sha256:e288416eecd4df19d12407d0c913cbf77aa8009d7fddb18f632aded3bdbdda6b"
|
||||||
|
],
|
||||||
|
"version": "==4.32.1"
|
||||||
|
},
|
||||||
|
"twine": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0fb0bfa3df4f62076cab5def36b1a71a2e4acb4d1fa5c97475b048117b1a6446",
|
||||||
|
"sha256:d6c29c933ecfc74e9b1d9fa13aa1f87c5d5770e119f5a4ce032092f0ff5b14dc"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==1.13.0"
|
||||||
|
},
|
||||||
|
"urllib3": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
|
||||||
|
"sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
|
||||||
|
],
|
||||||
|
"version": "==1.25.3"
|
||||||
|
},
|
||||||
|
"webencodings": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78",
|
||||||
|
"sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"
|
||||||
|
],
|
||||||
|
"version": "==0.5.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ Installation
|
||||||
Requirements
|
Requirements
|
||||||
============
|
============
|
||||||
|
|
||||||
* Wagtail >= 1.4
|
* Wagtail >= 1.12
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -89,7 +89,7 @@ To setup the application please follow these steps:
|
||||||
|
|
||||||
To learn more about preparing Wagtail for Internationalisation check the `Wagtail i18n docs <http://docs.wagtail.io/en/latest/advanced_topics/i18n/>`_.
|
To learn more about preparing Wagtail for Internationalisation check the `Wagtail i18n docs <http://docs.wagtail.io/en/latest/advanced_topics/i18n/>`_.
|
||||||
|
|
||||||
2. Create a ``translation.py`` file in your app directory and register ``TranslationOptions`` for every model you want to translate.
|
2. Create a ``translation.py`` file in your app directory and register ``TranslationOptions`` for every model you want to translate and for all subclasses of Page model.
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 0.10b1
|
current_version = 0.10.6
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
|
|
||||||
[bumpversion:file:wagtail_modeltranslation/__init__.py]
|
[bumpversion:file:wagtail_modeltranslation/__init__.py]
|
||||||
|
|
||||||
|
|
|
||||||
6
setup.py
6
setup.py
|
|
@ -44,8 +44,9 @@ setup(
|
||||||
'wagtail_modeltranslation.migrate.management',
|
'wagtail_modeltranslation.migrate.management',
|
||||||
'wagtail_modeltranslation.migrate.management.commands'],
|
'wagtail_modeltranslation.migrate.management.commands'],
|
||||||
package_data={'wagtail_modeltranslation': ['static/wagtail_modeltranslation/css/*.css',
|
package_data={'wagtail_modeltranslation': ['static/wagtail_modeltranslation/css/*.css',
|
||||||
'static/wagtail_modeltranslation/js/*.js']},
|
'static/wagtail_modeltranslation/js/*.js',
|
||||||
install_requires=['wagtail>=1.12', 'django-modeltranslation>=0.13b1'],
|
'templates/*.html']},
|
||||||
|
install_requires=['wagtail>=1.12', 'django-modeltranslation>=0.13'],
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 2.7',
|
'Programming Language :: Python :: 2.7',
|
||||||
|
|
@ -54,6 +55,7 @@ setup(
|
||||||
'Programming Language :: Python :: 3.5',
|
'Programming Language :: Python :: 3.5',
|
||||||
'Programming Language :: Python :: 3.6',
|
'Programming Language :: Python :: 3.6',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
|
'Programming Language :: Python :: 3.8',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Environment :: Web Environment',
|
'Environment :: Web Environment',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
|
|
|
||||||
67
tox.ini
67
tox.ini
|
|
@ -1,5 +1,17 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist =
|
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,
|
py37-2.4.X,
|
||||||
py36-2.4.X,
|
py36-2.4.X,
|
||||||
py35-2.4.X,
|
py35-2.4.X,
|
||||||
|
|
@ -29,6 +41,61 @@ envlist =
|
||||||
commands =
|
commands =
|
||||||
{envpython} runtests.py
|
{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]
|
[testenv:py37-2.4.X]
|
||||||
basepython = python3.7
|
basepython = python3.7
|
||||||
deps =
|
deps =
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
__version__ = '0.10b1'
|
__version__ = '0.10.6'
|
||||||
default_app_config = 'wagtail_modeltranslation.apps.ModeltranslationConfig'
|
default_app_config = 'wagtail_modeltranslation.apps.ModeltranslationConfig'
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,22 @@ class ModeltranslationConfig(AppConfig):
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from modeltranslation import settings as mt_settings
|
||||||
|
|
||||||
# Add Wagtail defined fields as modeltranslation custom fields
|
# Add Wagtail defined fields as modeltranslation custom fields
|
||||||
setattr(settings, 'MODELTRANSLATION_CUSTOM_FIELDS', getattr(settings, 'MODELTRANSLATION_CUSTOM_FIELDS', ()) + (
|
wagtail_fields = (
|
||||||
'StreamField', 'RichTextField'))
|
'StreamField',
|
||||||
|
'RichTextField',
|
||||||
|
)
|
||||||
|
|
||||||
|
# update both the standard settings and the modeltranslation settings,
|
||||||
|
# as we cannot guarantee the load order, and so django_modeltranslation
|
||||||
|
# may bootstrap itself either before, or after, our ready() gets called.
|
||||||
|
custom_fields = getattr(settings, 'MODELTRANSLATION_CUSTOM_FIELDS', tuple())
|
||||||
|
setattr(settings, 'MODELTRANSLATION_CUSTOM_FIELDS', tuple(set(custom_fields + wagtail_fields)))
|
||||||
|
|
||||||
|
mt_custom_fields = getattr(mt_settings, 'CUSTOM_FIELDS', tuple())
|
||||||
|
setattr(mt_settings, 'CUSTOM_FIELDS', tuple(set(mt_custom_fields + wagtail_fields)))
|
||||||
|
|
||||||
from modeltranslation.models import handle_translation_registrations
|
from modeltranslation.models import handle_translation_registrations
|
||||||
handle_translation_registrations()
|
handle_translation_registrations()
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from modeltranslation import settings as mt_settings
|
from modeltranslation import settings as mt_settings
|
||||||
from modeltranslation.translator import translator, NotRegistered
|
from modeltranslation.translator import translator, NotRegistered
|
||||||
from modeltranslation.utils import build_localized_fieldname, get_language
|
from modeltranslation.utils import build_localized_fieldname, get_language
|
||||||
from wagtail.contrib.settings.models import BaseSetting
|
|
||||||
from wagtail.contrib.settings.views import get_setting_edit_handler
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from wagtail.contrib.routable_page.models import RoutablePageMixin
|
from wagtail.contrib.routable_page.models import RoutablePageMixin
|
||||||
|
|
@ -32,7 +30,6 @@ try:
|
||||||
from wagtail.core.utils import WAGTAIL_APPEND_SLASH
|
from wagtail.core.utils import WAGTAIL_APPEND_SLASH
|
||||||
from wagtail.images.edit_handlers import ImageChooserPanel
|
from wagtail.images.edit_handlers import ImageChooserPanel
|
||||||
from wagtail.search.index import SearchField
|
from wagtail.search.index import SearchField
|
||||||
from wagtail.snippets.models import get_snippet_models
|
|
||||||
from wagtail.snippets.views.snippets import SNIPPET_EDIT_HANDLERS
|
from wagtail.snippets.views.snippets import SNIPPET_EDIT_HANDLERS
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from wagtail.contrib.wagtailroutablepage.models import RoutablePageMixin
|
from wagtail.contrib.wagtailroutablepage.models import RoutablePageMixin
|
||||||
|
|
@ -45,10 +42,10 @@ except ImportError:
|
||||||
from wagtail.wagtailcore.utils import WAGTAIL_APPEND_SLASH
|
from wagtail.wagtailcore.utils import WAGTAIL_APPEND_SLASH
|
||||||
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
|
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
|
||||||
from wagtail.wagtailsearch.index import SearchField
|
from wagtail.wagtailsearch.index import SearchField
|
||||||
from wagtail.wagtailsnippets.models import get_snippet_models
|
|
||||||
from wagtail.wagtailsnippets.views.snippets import SNIPPET_EDIT_HANDLERS
|
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.settings import CUSTOM_SIMPLE_PANELS, CUSTOM_COMPOSED_PANELS, TRANSLATE_SLUGS
|
||||||
from wagtail_modeltranslation.utils import compare_class_tree_depth
|
from wagtail_modeltranslation.utils import compare_class_tree_depth
|
||||||
|
from wagtail import VERSION
|
||||||
|
|
||||||
logger = logging.getLogger('wagtail.core')
|
logger = logging.getLogger('wagtail.core')
|
||||||
|
|
||||||
|
|
@ -135,7 +132,7 @@ class WagtailTranslator(object):
|
||||||
def _patch_other_models(self, model):
|
def _patch_other_models(self, model):
|
||||||
if hasattr(model, 'edit_handler'):
|
if hasattr(model, 'edit_handler'):
|
||||||
edit_handler = model.edit_handler
|
edit_handler = model.edit_handler
|
||||||
for tab in edit_handler:
|
for tab in edit_handler.children:
|
||||||
tab.children = self._patch_panels(tab.children)
|
tab.children = self._patch_panels(tab.children)
|
||||||
elif hasattr(model, 'panels'):
|
elif hasattr(model, 'panels'):
|
||||||
model.panels = self._patch_panels(model.panels)
|
model.panels = self._patch_panels(model.panels)
|
||||||
|
|
@ -144,8 +141,11 @@ class WagtailTranslator(object):
|
||||||
translation_registered_fields = translator.get_options_for_model(model).fields
|
translation_registered_fields = translator.get_options_for_model(model).fields
|
||||||
panels = filter(lambda field: field.field_name not in translation_registered_fields, panels)
|
panels = filter(lambda field: field.field_name not in translation_registered_fields, panels)
|
||||||
edit_handler = ObjectList(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):
|
def _patch_panels(self, panels_list, related_model=None):
|
||||||
"""
|
"""
|
||||||
|
|
@ -262,9 +262,9 @@ def _localized_set_url_path(page, parent, language):
|
||||||
# for the current language. If the value for the current language is invalid we get the one
|
# for the current language. If the value for the current language is invalid we get the one
|
||||||
# for the default fallback language
|
# for the default fallback language
|
||||||
slug = getattr(page, localized_slug_field, None) or \
|
slug = getattr(page, localized_slug_field, None) or \
|
||||||
getattr(page, default_localized_slug_field, None) or page.slug
|
getattr(page, default_localized_slug_field, None) or page.slug
|
||||||
parent_url_path = getattr(parent, localized_url_path_field, None) or \
|
parent_url_path = getattr(parent, localized_url_path_field, None) or \
|
||||||
getattr(parent, default_localized_url_path_field, None) or parent.url_path
|
getattr(parent, default_localized_url_path_field, None) or parent.url_path
|
||||||
|
|
||||||
setattr(page, localized_url_path_field, parent_url_path + slug + '/')
|
setattr(page, localized_url_path_field, parent_url_path + slug + '/')
|
||||||
|
|
||||||
|
|
@ -459,7 +459,7 @@ def _update_translation_descendant_url_paths(old_record, page):
|
||||||
default_localized_url_path = build_localized_fieldname('url_path', mt_settings.DEFAULT_LANGUAGE)
|
default_localized_url_path = build_localized_fieldname('url_path', mt_settings.DEFAULT_LANGUAGE)
|
||||||
for language in mt_settings.AVAILABLE_LANGUAGES:
|
for language in mt_settings.AVAILABLE_LANGUAGES:
|
||||||
localized_url_path = build_localized_fieldname('url_path', language)
|
localized_url_path = build_localized_fieldname('url_path', language)
|
||||||
old_url_path = getattr(old_record, localized_url_path) or getattr(old_record, default_localized_url_path)
|
old_url_path = getattr(old_record, localized_url_path) or getattr(old_record, default_localized_url_path) or ''
|
||||||
new_url_path = getattr(page, localized_url_path) or getattr(page, default_localized_url_path)
|
new_url_path = getattr(page, localized_url_path) or getattr(page, default_localized_url_path)
|
||||||
|
|
||||||
if old_url_path == new_url_path:
|
if old_url_path == new_url_path:
|
||||||
|
|
@ -573,5 +573,4 @@ def patch_wagtail_models():
|
||||||
registered_models.sort(key=compare_class_tree_depth)
|
registered_models.sort(key=compare_class_tree_depth)
|
||||||
|
|
||||||
for model_class in registered_models:
|
for model_class in registered_models:
|
||||||
if issubclass(model_class, Page) or model_class in get_snippet_models() or issubclass(model_class, BaseSetting):
|
WagtailTranslator(model_class)
|
||||||
WagtailTranslator(model_class)
|
|
||||||
|
|
|
||||||
107
wagtail_modeltranslation/patch_wagtailadmin_forms.py
Normal file
107
wagtail_modeltranslation/patch_wagtailadmin_forms.py
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
# 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
|
||||||
|
|
@ -7,22 +7,47 @@ $(document).ready(function(){
|
||||||
for (var i = 0; i < allStreamFields.length; i++) {
|
for (var i = 0; i < allStreamFields.length; i++) {
|
||||||
//Current Field with all content
|
//Current Field with all content
|
||||||
var currentStreamField = allStreamFields[i];
|
var currentStreamField = allStreamFields[i];
|
||||||
//Current Field header
|
//Current field header
|
||||||
var header = $(currentStreamField).children('h2')[0];
|
var header;
|
||||||
//Search for the input field so that we can get is id to know the field's name.
|
//Current field name
|
||||||
var streamFieldDiv = $(currentStreamField).find('div.sequence-container.sequence-type-stream')[0];
|
var fieldLang = "";
|
||||||
var fieldInfos = $(streamFieldDiv).children('input')[0].id.split('-')[0];
|
//Current field language
|
||||||
var lastUnderscore = fieldInfos.lastIndexOf("_");
|
var fieldName = "";
|
||||||
var fieldName = fieldInfos.substring(0, lastUnderscore);
|
if(versionCompare(WAGTAIL_VERSION,'2.6.0', {zeroExtend: true})===-1){
|
||||||
var fieldLang = fieldInfos.substring(lastUnderscore + 1, fieldInfos.length);
|
// 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);
|
||||||
|
}
|
||||||
//The cycle to create the buttons for copy each language field
|
//The cycle to create the buttons for copy each language field
|
||||||
var copyContentString = 'Copy content from';
|
header.innerHTML += '<div class="translation-field-copy-wrapper">Copy content from: </div>';
|
||||||
header.innerHTML += '<div class="translation-field-copy-wrapper">'+copyContentString+': </div>';
|
|
||||||
for (var j = 0; j < langs.length; j++) {
|
for (var j = 0; j < langs.length; j++) {
|
||||||
if (fieldLang != langs[j]) {
|
if (fieldLang != langs[j]) {
|
||||||
var currentFieldID = fieldName + '_' + fieldLang;
|
var currentFieldID = fieldName + '_' + fieldLang;
|
||||||
var targetFieldID = fieldName + '_' + langs [j];
|
var targetFieldID = fieldName + '_' + langs [j];
|
||||||
$(header).children('.translation-field-copy-wrapper')[0].innerHTML += '<button class="translation-field-copy" current-lang-code="'+ currentFieldID +'" data-lang-code="'+ targetFieldID +'">'+langs[j]+'</button>';
|
$(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>';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -55,11 +80,11 @@ function requestCopyField(originID, targetID) {
|
||||||
})
|
})
|
||||||
.done(function(data) {
|
.done(function(data) {
|
||||||
/* Put the html data in the targetID field */
|
/* 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);
|
$(wrapperDiv).html(data);
|
||||||
})
|
})
|
||||||
.fail(function(error) {
|
.fail(function(error) {
|
||||||
console.log("wagtail-modeltranslation error: %s", error.responseText);
|
console.log('wagtail-modeltranslation error: ' + error.responseText);
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
{% 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 %}
|
||||||
|
|
@ -2,24 +2,35 @@
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.http import HttpResponse, QueryDict
|
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.html import escape, format_html, format_html_join
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from wagtail_modeltranslation import settings as wmt_settings
|
from wagtail_modeltranslation import settings as wmt_settings
|
||||||
from modeltranslation import settings as mt_settings
|
from modeltranslation import settings as mt_settings
|
||||||
|
|
||||||
|
from .patch_wagtailadmin_forms import PatchedCopyForm
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from wagtail.core import hooks
|
from wagtail.core import hooks
|
||||||
from wagtail.core.models import Page
|
from wagtail.core.models import Page
|
||||||
from wagtail.core.rich_text.pages import PageLinkHandler
|
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:
|
except ImportError:
|
||||||
from wagtail.wagtailcore import hooks
|
from wagtail.wagtailcore import hooks
|
||||||
from wagtail.wagtailcore.models import Page
|
from wagtail.wagtailcore.models import Page
|
||||||
from wagtail.wagtailcore.rich_text import PageLinkHandler
|
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')
|
@hooks.register('insert_editor_js')
|
||||||
|
|
@ -28,9 +39,9 @@ def translated_slugs():
|
||||||
'wagtail_modeltranslation/js/wagtail_translated_slugs.js',
|
'wagtail_modeltranslation/js/wagtail_translated_slugs.js',
|
||||||
]
|
]
|
||||||
|
|
||||||
js_includes = format_html_join('\n', '<script src="{0}{1}"></script>', (
|
js_includes = format_html_join('\n', '<script src="{0}"></script>', (
|
||||||
(settings.STATIC_URL, filename) for filename in js_files)
|
(static(filename),) for filename in js_files)
|
||||||
)
|
)
|
||||||
|
|
||||||
lang_codes = []
|
lang_codes = []
|
||||||
for lang in settings.LANGUAGES:
|
for lang in settings.LANGUAGES:
|
||||||
|
|
@ -120,21 +131,26 @@ def streamfields_translation_copy():
|
||||||
|
|
||||||
# includes the javascript file in the html file
|
# includes the javascript file in the html file
|
||||||
js_files = [
|
js_files = [
|
||||||
|
'wagtail_modeltranslation/js/version_compare.js',
|
||||||
'wagtail_modeltranslation/js/copy_stream_fields.js',
|
'wagtail_modeltranslation/js/copy_stream_fields.js',
|
||||||
]
|
]
|
||||||
|
|
||||||
js_includes = format_html_join('\n', '<script src="{0}{1}"></script>', (
|
js_includes = format_html_join('\n', '<script src="{0}"></script>', (
|
||||||
(settings.STATIC_URL, filename) for filename in js_files)
|
(static(filename),) for filename in js_files)
|
||||||
)
|
)
|
||||||
|
|
||||||
return js_includes
|
js_wagtail_version = """
|
||||||
|
<script>
|
||||||
|
var WAGTAIL_VERSION='{wagtail_version}';
|
||||||
|
</script>
|
||||||
|
""".format(wagtail_version=WAGTAIL_VERSION)
|
||||||
|
return format_html(js_wagtail_version) + js_includes
|
||||||
|
|
||||||
|
|
||||||
@hooks.register('insert_editor_css')
|
@hooks.register('insert_editor_css')
|
||||||
def modeltranslation_page_editor_css():
|
def modeltranslation_page_editor_css():
|
||||||
return format_html('<link rel="stylesheet" href="'
|
filename = 'wagtail_modeltranslation/css/page_editor_modeltranslation.css'
|
||||||
+ settings.STATIC_URL
|
return format_html('<link rel="stylesheet" href="{}" >'.format(static(filename)))
|
||||||
+ 'wagtail_modeltranslation/css/page_editor_modeltranslation.css" >')
|
|
||||||
|
|
||||||
|
|
||||||
@hooks.register('register_rich_text_link_handler')
|
@hooks.register('register_rich_text_link_handler')
|
||||||
|
|
@ -160,3 +176,70 @@ def register_localized_page_link_handler():
|
||||||
return "<a>"
|
return "<a>"
|
||||||
|
|
||||||
return ('page', LocalizedPageLinkHandler)
|
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
|
||||||
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue