summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS48
-rw-r--r--INSTALL19
-rw-r--r--MANIFEST.in8
-rw-r--r--README4
-rw-r--r--django/__init__.py2
-rwxr-xr-xdjango/bin/compile-messages.py17
-rw-r--r--django/bin/daily_cleanup.py13
-rwxr-xr-xdjango/bin/make-messages.py4
-rw-r--r--django/conf/__init__.py1
-rw-r--r--django/conf/global_settings.py24
-rw-r--r--django/conf/locale/cs/LC_MESSAGES/django.mobin33632 -> 37754 bytes
-rw-r--r--django/conf/locale/cs/LC_MESSAGES/django.po732
-rw-r--r--django/conf/locale/da/LC_MESSAGES/django.mobin16153 -> 32010 bytes
-rw-r--r--django/conf/locale/da/LC_MESSAGES/django.po708
-rw-r--r--django/conf/locale/de/LC_MESSAGES/django.mobin32926 -> 37729 bytes
-rw-r--r--django/conf/locale/de/LC_MESSAGES/django.po717
-rw-r--r--django/conf/locale/en/LC_MESSAGES/django.mobin536 -> 627 bytes
-rw-r--r--django/conf/locale/en/LC_MESSAGES/django.po672
-rw-r--r--django/conf/locale/es_AR/LC_MESSAGES/django.mobin33953 -> 36332 bytes
-rw-r--r--django/conf/locale/es_AR/LC_MESSAGES/django.po548
-rw-r--r--django/conf/locale/fi/LC_MESSAGES/django.mobin0 -> 33598 bytes
-rw-r--r--django/conf/locale/fi/LC_MESSAGES/django.po2031
-rw-r--r--django/conf/locale/fi/LC_MESSAGES/djangojs.mobin0 -> 1529 bytes
-rw-r--r--django/conf/locale/fi/LC_MESSAGES/djangojs.po110
-rw-r--r--django/conf/locale/ja/LC_MESSAGES/django.mobin33761 -> 41208 bytes
-rw-r--r--django/conf/locale/ja/LC_MESSAGES/django.po771
-rw-r--r--django/conf/locale/ja/LC_MESSAGES/djangojs.mobin1560 -> 1604 bytes
-rw-r--r--django/conf/locale/ja/LC_MESSAGES/djangojs.po44
-rw-r--r--django/conf/locale/no/LC_MESSAGES/django.mobin23238 -> 27469 bytes
-rw-r--r--django/conf/locale/no/LC_MESSAGES/django.po273
-rw-r--r--django/conf/locale/no/LC_MESSAGES/djangojs.mobin1432 -> 1492 bytes
-rw-r--r--django/conf/locale/no/LC_MESSAGES/djangojs.po11
-rw-r--r--django/conf/locale/pl/LC_MESSAGES/django.mobin23926 -> 28373 bytes
-rw-r--r--django/conf/locale/pl/LC_MESSAGES/django.po96
-rw-r--r--django/conf/locale/ru/LC_MESSAGES/django.mobin31822 -> 42820 bytes
-rw-r--r--django/conf/locale/ru/LC_MESSAGES/django.po842
-rw-r--r--django/conf/locale/sl/LC_MESSAGES/django.mobin29424 -> 33224 bytes
-rw-r--r--django/conf/locale/sl/LC_MESSAGES/django.po638
-rw-r--r--django/conf/locale/ta/LC_MESSAGES/django.mobin0 -> 52050 bytes
-rw-r--r--django/conf/locale/ta/LC_MESSAGES/django.po2111
-rw-r--r--django/conf/locale/tr/LC_MESSAGES/django.mobin0 -> 37149 bytes
-rw-r--r--django/conf/locale/tr/LC_MESSAGES/django.po2209
-rw-r--r--django/conf/locale/tr/LC_MESSAGES/djangojs.mobin0 -> 1508 bytes
-rw-r--r--django/conf/locale/tr/LC_MESSAGES/djangojs.po109
-rw-r--r--django/conf/locale/zh_CN/LC_MESSAGES/django.mobin30798 -> 30798 bytes
-rw-r--r--django/conf/locale/zh_CN/LC_MESSAGES/django.po4
-rw-r--r--django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mobin1513 -> 1505 bytes
-rw-r--r--django/conf/locale/zh_CN/LC_MESSAGES/djangojs.po28
-rw-r--r--django/conf/project_template/settings.py7
-rw-r--r--django/conf/urls/defaults.py8
-rw-r--r--django/contrib/admin/filterspecs.py2
-rw-r--r--django/contrib/admin/media/css/changelists.css4
-rw-r--r--django/contrib/admin/media/css/forms.css4
-rw-r--r--django/contrib/admin/media/css/global.css8
-rw-r--r--django/contrib/admin/media/css/layout.css8
-rw-r--r--django/contrib/admin/media/css/rtl.css2
-rw-r--r--django/contrib/admin/media/js/admin/CollapsedFieldsets.js144
-rw-r--r--django/contrib/admin/media/js/admin/DateTimeShortcuts.js67
-rw-r--r--django/contrib/admin/media/js/admin/RelatedObjectLookups.js2
-rw-r--r--django/contrib/admin/templates/admin/auth/user/add_form.html28
-rw-r--r--django/contrib/admin/templates/admin/base.html9
-rw-r--r--django/contrib/admin/templates/admin/base_site.html2
-rw-r--r--django/contrib/admin/templates/admin/change_form.html6
-rw-r--r--django/contrib/admin/templates/admin/change_list.html4
-rw-r--r--django/contrib/admin/templates/admin/date_hierarchy.html6
-rw-r--r--django/contrib/admin/templates/admin/delete_confirmation.html10
-rw-r--r--django/contrib/admin/templates/admin/edit_inline_stacked.html2
-rw-r--r--django/contrib/admin/templates/admin/edit_inline_tabular.html5
-rw-r--r--django/contrib/admin/templates/admin/filter.html2
-rw-r--r--django/contrib/admin/templates/admin/index.html6
-rw-r--r--django/contrib/admin/templates/admin/invalid_setup.html2
-rw-r--r--django/contrib/admin/templates/admin/login.html22
-rw-r--r--django/contrib/admin/templates/admin/object_history.html2
-rw-r--r--django/contrib/admin/templates/admin/pagination.html2
-rw-r--r--django/contrib/admin/templates/admin_doc/index.html16
-rw-r--r--django/contrib/admin/templates/admin_doc/missing_docutils.html4
-rw-r--r--django/contrib/admin/templates/admin_doc/model_detail.html6
-rw-r--r--django/contrib/admin/templates/admin_doc/template_detail.html10
-rw-r--r--django/contrib/admin/templates/widget/file.html2
-rw-r--r--django/contrib/admin/templates/widget/foreign.html2
-rw-r--r--django/contrib/admin/templates/widget/one_to_one.html2
-rw-r--r--django/contrib/admin/templatetags/admin_list.py11
-rw-r--r--django/contrib/admin/templatetags/admin_modify.py8
-rw-r--r--django/contrib/admin/urls.py4
-rw-r--r--django/contrib/admin/utils.py1
-rw-r--r--django/contrib/admin/views/auth.py44
-rw-r--r--django/contrib/admin/views/decorators.py4
-rw-r--r--django/contrib/admin/views/doc.py48
-rw-r--r--django/contrib/admin/views/main.py21
-rw-r--r--django/contrib/admin/views/template.py4
-rw-r--r--django/contrib/auth/__init__.py12
-rw-r--r--django/contrib/auth/backends.py2
-rw-r--r--django/contrib/auth/create_superuser.py1
-rw-r--r--django/contrib/auth/decorators.py12
-rw-r--r--django/contrib/auth/forms.py32
-rw-r--r--django/contrib/auth/handlers/modpython.py31
-rw-r--r--django/contrib/auth/management.py8
-rw-r--r--django/contrib/auth/middleware.py9
-rw-r--r--django/contrib/auth/models.py26
-rw-r--r--django/contrib/auth/views.py14
-rw-r--r--django/contrib/comments/feeds.py3
-rw-r--r--django/contrib/comments/models.py2
-rw-r--r--django/contrib/comments/templates/comments/form.html6
-rw-r--r--django/contrib/comments/templatetags/comments.py2
-rw-r--r--django/contrib/comments/views/comments.py8
-rw-r--r--django/contrib/comments/views/karma.py2
-rw-r--r--django/contrib/contenttypes/management.py5
-rw-r--r--django/contrib/flatpages/README.TXT4
-rw-r--r--django/contrib/flatpages/views.py7
-rw-r--r--django/contrib/sessions/middleware.py3
-rw-r--r--django/contrib/sessions/models.py16
-rw-r--r--django/contrib/sitemaps/__init__.py90
-rw-r--r--django/contrib/sitemaps/templates/sitemap.xml13
-rw-r--r--django/contrib/sitemaps/templates/sitemap_index.xml4
-rw-r--r--django/contrib/sitemaps/views.py30
-rw-r--r--django/contrib/sites/management.py5
-rw-r--r--django/contrib/syndication/feeds.py2
-rw-r--r--django/core/cache/backends/db.py2
-rw-r--r--django/core/cache/backends/locmem.py4
-rw-r--r--django/core/cache/backends/memcached.py2
-rw-r--r--django/core/context_processors.py6
-rw-r--r--django/core/handlers/base.py36
-rw-r--r--django/core/handlers/modpython.py58
-rw-r--r--django/core/handlers/wsgi.py61
-rw-r--r--django/core/management.py222
-rw-r--r--django/core/paginator.py1
-rw-r--r--django/core/serializers/base.py54
-rw-r--r--django/core/serializers/json.py10
-rw-r--r--django/core/serializers/python.py2
-rw-r--r--django/core/servers/basehttp.py15
-rw-r--r--django/core/servers/fastcgi.py3
-rw-r--r--django/core/urlresolvers.py75
-rw-r--r--django/core/validators.py34
-rw-r--r--django/core/xheaders.py5
-rw-r--r--django/db/backends/mysql/base.py18
-rw-r--r--django/db/backends/mysql/introspection.py3
-rw-r--r--django/db/backends/oracle/base.py1
-rw-r--r--django/db/backends/oracle/introspection.py2
-rw-r--r--django/db/backends/postgresql_psycopg2/base.py21
-rw-r--r--django/db/backends/postgresql_psycopg2/introspection.py1
-rw-r--r--django/db/backends/sqlite3/base.py17
-rw-r--r--django/db/backends/util.py8
-rw-r--r--django/db/models/__init__.py14
-rw-r--r--django/db/models/base.py18
-rw-r--r--django/db/models/fields/__init__.py15
-rw-r--r--django/db/models/fields/generic.py2
-rw-r--r--django/db/models/fields/related.py24
-rw-r--r--django/db/models/loading.py10
-rw-r--r--django/db/models/manager.py3
-rw-r--r--django/db/models/manipulators.py17
-rw-r--r--django/db/models/query.py57
-rw-r--r--django/db/models/related.py3
-rw-r--r--django/dispatch/dispatcher.py810
-rw-r--r--django/dispatch/errors.py6
-rw-r--r--django/dispatch/license.txt62
-rw-r--r--django/dispatch/robust.py88
-rw-r--r--django/dispatch/robustapply.py70
-rw-r--r--django/dispatch/saferef.py298
-rw-r--r--django/forms/__init__.py36
-rw-r--r--django/http/__init__.py48
-rw-r--r--django/middleware/cache.py19
-rw-r--r--django/middleware/common.py15
-rw-r--r--django/middleware/doc.py9
-rw-r--r--django/middleware/gzip.py6
-rw-r--r--django/middleware/http.py24
-rw-r--r--django/middleware/transaction.py1
-rw-r--r--django/template/__init__.py42
-rw-r--r--django/template/defaultfilters.py10
-rw-r--r--django/template/defaulttags.py22
-rw-r--r--django/template/loader.py10
-rw-r--r--django/template/loader_tags.py13
-rw-r--r--django/template/loaders/filesystem.py2
-rw-r--r--django/templatetags/i18n.py7
-rw-r--r--django/test/__init__.py (renamed from tests/othertests/__init__.py)0
-rw-r--r--django/test/client.py216
-rw-r--r--django/test/doctest.py (renamed from tests/doctest.py)18
-rw-r--r--django/test/signals.py1
-rw-r--r--django/test/simple.py85
-rw-r--r--django/test/testcases.py30
-rw-r--r--django/test/utils.py107
-rw-r--r--django/utils/autoreload.py8
-rw-r--r--django/utils/datastructures.py31
-rw-r--r--django/utils/functional.py4
-rw-r--r--django/utils/itercompat.py31
-rw-r--r--django/utils/simplejson/scanner.py3
-rw-r--r--django/utils/termcolors.py2
-rw-r--r--django/utils/text.py6
-rw-r--r--django/utils/translation/trans_null.py11
-rw-r--r--django/views/debug.py30
-rw-r--r--django/views/decorators/cache.py1
-rw-r--r--django/views/generic/create_update.py26
-rw-r--r--django/views/generic/date_based.py72
-rw-r--r--django/views/static.py3
-rw-r--r--docs/add_ons.txt16
-rw-r--r--docs/admin_css.txt8
-rw-r--r--docs/apache_auth.txt2
-rw-r--r--docs/api_stability.txt123
-rw-r--r--docs/authentication.txt104
-rw-r--r--docs/cache.txt12
-rw-r--r--docs/contributing.txt54
-rw-r--r--docs/db-api.txt57
-rw-r--r--docs/design_philosophies.txt4
-rw-r--r--docs/django-admin.txt57
-rw-r--r--docs/documentation.txt148
-rw-r--r--docs/faq.txt113
-rw-r--r--docs/fastcgi.txt4
-rw-r--r--docs/forms.txt89
-rw-r--r--docs/generic_views.txt66
-rw-r--r--docs/i18n.txt22
-rw-r--r--docs/install.txt48
-rw-r--r--docs/middleware.txt18
-rw-r--r--docs/model-api.txt106
-rw-r--r--docs/overview.txt2
-rw-r--r--docs/release_notes_0.95.txt126
-rw-r--r--docs/request_response.txt40
-rw-r--r--docs/serialization.txt31
-rw-r--r--docs/sessions.txt11
-rw-r--r--docs/settings.txt83
-rw-r--r--docs/sitemaps.txt320
-rw-r--r--docs/sites.txt11
-rw-r--r--docs/syndication_feeds.txt4
-rw-r--r--docs/templates.txt48
-rw-r--r--docs/templates_python.txt117
-rw-r--r--docs/testing.txt453
-rw-r--r--docs/transactions.txt19
-rw-r--r--docs/tutorial01.txt4
-rw-r--r--docs/tutorial02.txt13
-rw-r--r--docs/tutorial03.txt14
-rw-r--r--docs/tutorial04.txt6
-rw-r--r--docs/url_dispatch.txt97
-rw-r--r--ez_setup.py231
-rw-r--r--setup.cfg3
-rw-r--r--setup.py72
-rw-r--r--tests/modeltests/basic/models.py15
-rw-r--r--tests/modeltests/choices/models.py4
-rw-r--r--tests/modeltests/custom_columns/models.py4
-rw-r--r--tests/modeltests/custom_managers/models.py4
-rw-r--r--tests/modeltests/custom_methods/models.py4
-rw-r--r--tests/modeltests/custom_pk/models.py8
-rw-r--r--tests/modeltests/empty/models.py6
-rw-r--r--tests/modeltests/field_defaults/models.py4
-rw-r--r--tests/modeltests/generic_relations/models.py4
-rw-r--r--tests/modeltests/get_latest/models.py12
-rw-r--r--tests/modeltests/get_or_create/models.py4
-rw-r--r--tests/modeltests/invalid_models/models.py39
-rw-r--r--tests/modeltests/lookup/models.py15
-rw-r--r--tests/modeltests/m2m_and_m2o/models.py4
-rw-r--r--tests/modeltests/m2m_intermediary/models.py4
-rw-r--r--tests/modeltests/m2m_multiple/models.py4
-rw-r--r--tests/modeltests/m2m_recursive/models.py4
-rw-r--r--tests/modeltests/m2o_recursive/models.py4
-rw-r--r--tests/modeltests/m2o_recursive2/models.py4
-rw-r--r--tests/modeltests/manipulators/models.py4
-rw-r--r--tests/modeltests/many_to_many/models.py4
-rw-r--r--tests/modeltests/many_to_one/models.py4
-rw-r--r--tests/modeltests/many_to_one_null/models.py4
-rw-r--r--tests/modeltests/model_inheritance/models.py4
-rw-r--r--tests/modeltests/mutually_referential/models.py4
-rw-r--r--tests/modeltests/one_to_one/models.py18
-rw-r--r--tests/modeltests/or_lookups/models.py4
-rw-r--r--tests/modeltests/ordering/models.py4
-rw-r--r--tests/modeltests/pagination/models.py4
-rw-r--r--tests/modeltests/properties/models.py4
-rw-r--r--tests/modeltests/reserved_names/models.py4
-rw-r--r--tests/modeltests/reverse_lookup/models.py4
-rw-r--r--tests/modeltests/save_delete_hooks/models.py4
-rw-r--r--tests/modeltests/serializers/models.py4
-rw-r--r--tests/modeltests/str/models.py4
-rw-r--r--tests/modeltests/test_client/__init__.py0
-rw-r--r--tests/modeltests/test_client/management.py10
-rw-r--r--tests/modeltests/test_client/models.py101
-rw-r--r--tests/modeltests/test_client/urls.py9
-rw-r--r--tests/modeltests/test_client/views.py35
-rw-r--r--tests/modeltests/transactions/models.py6
-rw-r--r--tests/modeltests/validation/models.py4
-rw-r--r--tests/othertests/cache.py60
-rw-r--r--tests/othertests/markup.py68
-rw-r--r--tests/othertests/templates.py625
-rw-r--r--tests/regressiontests/cache/__init__.py0
-rw-r--r--tests/regressiontests/cache/models.py0
-rw-r--r--tests/regressiontests/cache/tests.py71
-rw-r--r--tests/regressiontests/dateformat/__init__.py0
-rw-r--r--tests/regressiontests/dateformat/models.py0
-rw-r--r--tests/regressiontests/dateformat/tests.py (renamed from tests/othertests/dateformat.py)42
-rw-r--r--tests/regressiontests/db_typecasts/__init__.py0
-rw-r--r--tests/regressiontests/db_typecasts/models.py0
-rw-r--r--tests/regressiontests/db_typecasts/tests.py (renamed from tests/othertests/db_typecasts.py)15
-rw-r--r--tests/regressiontests/defaultfilters/__init__.py0
-rw-r--r--tests/regressiontests/defaultfilters/models.py0
-rw-r--r--tests/regressiontests/defaultfilters/tests.py (renamed from tests/othertests/defaultfilters.py)6
-rw-r--r--tests/regressiontests/httpwrappers/__init__.py0
-rw-r--r--tests/regressiontests/httpwrappers/models.py0
-rw-r--r--tests/regressiontests/httpwrappers/tests.py (renamed from tests/othertests/httpwrappers.py)0
-rw-r--r--tests/regressiontests/initial_sql_regress/models.py2
-rw-r--r--tests/regressiontests/initial_sql_regress/sql/simple.sql1
-rw-r--r--tests/regressiontests/many_to_one_regress/models.py2
-rw-r--r--tests/regressiontests/markup/__init__.py0
-rw-r--r--tests/regressiontests/markup/models.py0
-rw-r--r--tests/regressiontests/markup/tests.py69
-rw-r--r--tests/regressiontests/null_queries/__init__.py0
-rw-r--r--tests/regressiontests/null_queries/models.py54
-rw-r--r--tests/regressiontests/one_to_one_regress/models.py4
-rw-r--r--tests/regressiontests/string_lookup/models.py4
-rw-r--r--tests/regressiontests/templates/__init__.py0
-rw-r--r--tests/regressiontests/templates/models.py0
-rw-r--r--tests/regressiontests/templates/tests.py667
-rw-r--r--tests/regressiontests/urlpatterns_reverse/__init__.py0
-rw-r--r--tests/regressiontests/urlpatterns_reverse/models.py0
-rw-r--r--tests/regressiontests/urlpatterns_reverse/tests.py39
-rwxr-xr-xtests/runtests.py340
-rw-r--r--tests/templates/404.html1
-rw-r--r--tests/templates/500.html1
-rw-r--r--tests/templates/login.html19
-rw-r--r--tests/urls.py10
314 files changed, 16288 insertions, 5759 deletions
diff --git a/AUTHORS b/AUTHORS
index fb299a9e3b..52d4950e4e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -16,12 +16,23 @@ before Simon departed and currently oversees things with Adrian.
Wilson Miner <http://www.wilsonminer.com/>, who designed Django's admin
interface, pretty error pages, official Web site (djangoproject.com) and has
-made many other contributions.
+made many other contributions. He makes us look good.
+
+Malcolm Tredinnick <http://www.pointy-stick.com/blog/>, who has made
+significant contributions to all levels of the framework, from its database
+layer to template system and documentation.
Georg "Hugo" Bauer <http://hugo.muensterland.org/>, who added
internationalization support, manages i18n contributions and has made a ton
of excellent tweaks, feature additions and bug fixes.
+Luke Plant <http://lukeplant.me.uk/>, who has contributed many excellent
+improvements, including database-level improvements, the CSRF middleware and
+unit tests.
+
+Russell Keith-Magee <freakboy@iinet.net.au>, who has contributed many excellent
+improvements, including refactoring of the Django ORM code and unit tests.
+
Robert Wittams <http://robert.wittams.com/>, who majorly refactored the Django
admin application to allow for easier reuse and has made a ton of excellent
tweaks, feature additions and bug fixes.
@@ -31,8 +42,10 @@ And here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS --
people who have submitted patches, reported bugs, added translations, helped
answer newbie questions, and generally made Django that much better:
+ adurdin@gmail.com
akaihola
Andreas
+ ant9000@netwise.it
David Ascher <http://ascher.ca/>
Arthur <avandorp@gmail.com>
Jiri Barton
@@ -49,18 +62,30 @@ answer newbie questions, and generally made Django that much better:
Amit Chakradeo <http://amit.chakradeo.net/>
ChaosKCW
Ian Clelland <clelland@gmail.com>
+ crankycoder@gmail.com
Matt Croydon <http://www.postneo.com/>
+ dackze+django@gmail.com
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
Jason Davies (Esaj) <http://www.jasondavies.com/>
Alex Dedul
deric@monowerks.com
dne@mayonnaise.net
+ Maximillian Dornseif <md@hudora.de>
+ dummy@habmalnefrage.de
Jeremy Dunck <http://dunck.us/>
+ Andy Dustman <farcepest@gmail.com>
Clint Ecker
+ Enrico <rico.bl@gmail.com>
+ favo@exoweb.net
gandalf@owca.info
Baishampayan Ghose
+ martin.glueck@gmail.com
+ Simon Greenhill <dev@simon.net.nz>
Espen Grindhaug <http://grindhaug.org/>
Brant Harris
+ Hawkeye
+ heckj@mac.com
+ Joel Heenan <joelh-django@planetjoel.com>
hipertracker@gmail.com
Ian Holsman <http://feh.holsman.net/>
Kieran Holland <http://www.kieranholland.com>
@@ -70,34 +95,39 @@ answer newbie questions, and generally made Django that much better:
Michael Josephson <http://www.sdjournal.com/>
jpellerin@gmail.com
junzhang.jn@gmail.com
- Russell Keith-Magee <freakboy@iinet.net.au>
Garth Kidd <http://www.deadlybloodyserious.com/>
kilian <kilian.cavalotti@lip6.fr>
Sune Kirkeby <http://ibofobi.dk/>
Cameron Knight (ckknight)
+ Meir Kriheli <http://mksoft.co.il/>
Bruce Kroeze <http://coderseye.com/>
Joseph Kocherhans
konrad@gwu.edu
lakin.wecker@gmail.com
Stuart Langridge <http://www.kryogenix.org/>
Eugene Lazutkin <http://lazutkin.com/blog/>
+ Jeong-Min Lee
Christopher Lenz <http://www.cmlenz.net/>
+ lerouxb@gmail.com
limodou
+ mattmcc
Martin Maney <http://www.chipy.org/Martin_Maney>
Manuzhai
Petar Marić
mark@junklight.com
mattycakes@gmail.com
Jason McBrayer <http://www.carcosa.net/jason/>
+ mccutchen@gmail.com
michael.mcewan@gmail.com
- mir@noris.de
mmarshall
Eric Moritz <http://eric.themoritzfamily.com/>
Robin Munn <http://www.geekforgod.com/>
Nebojša Dorđević
+ Fraser Nevett <mail@nevett.org>
Sam Newman <http://www.magpiebrain.com/>
Neal Norwitz <nnorwitz@google.com>
oggie rob <oz.robharvey@gmail.com>
+ Jay Parlar <parlar@gmail.com>
pgross@thoughtworks.com
phaedo <http://phaedo.cx/>
phil@produxion.net
@@ -106,25 +136,35 @@ answer newbie questions, and generally made Django that much better:
plisk
Daniel Poelzleithner <http://poelzi.org/>
J. Rademaker
+ Michael Radziej <mir@noris.de>
+ ramiro
Brian Ray <http://brianray.chipy.org/>
rhettg@gmail.com
Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
David Schein
+ serbaut@gmail.com
+ Pete Shinners <pete@shinners.org>
+ SmileyChris <smileychris@gmail.com>
sopel
+ Thomas Steinacher <tom@eggdrop.ch>
Radek Å varz <http://www.svarz.cz/translate/>
Swaroop C H <http://www.swaroopch.info>
Aaron Swartz <http://www.aaronsw.com/>
+ Tyson Tate <tyson@fallingbullets.com>
Tom Tobin
Tom Insam
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
- Malcolm Tredinnick
+ Karen Tracey <graybark@bellsouth.net>
Amit Upadhyay
Geert Vanderkelen
Milton Waddams
+ Dan Watson <http://theidioteque.net/>
Rachel Willmer <http://www.willmer.com/kb/>
+ Gary Wilson <gary.wilson@gmail.com>
wojtek
ye7cakf02@sneakemail.com
+ ymasuda@ethercube.com
Cheng Zhang
A big THANK YOU goes to:
diff --git a/INSTALL b/INSTALL
index fc21a61b47..23e24c0cdf 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,22 @@
Thanks for downloading Django.
-To install it, make sure you have Python 2.3 or greater installed. Then run this command:
+To install it, make sure you have Python 2.3 or greater installed. Then run
+this command from the command prompt:
-python setup.py install
+ python setup.py install
+
+Note this requires a working Internet connection if you don't already have the
+Python utility "setuptools" installed.
+
+AS AN ALTERNATIVE, you can just copy the entire "django" directory to Python's
+site-packages directory, which is located wherever your Python installation
+lives. Some places you might check are:
+
+ /usr/lib/python2.4/site-packages (Unix, Python 2.4)
+ /usr/lib/python2.3/site-packages (Unix, Python 2.3)
+ C:\\PYTHON\site-packages (Windows)
+
+This second solution does not require a working Internet connection; it
+bypasses "setuptools" entirely.
For more detailed instructions, see docs/install.txt.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000000..b5fbb3cb90
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,8 @@
+include AUTHORS
+include INSTALL
+include LICENSE
+recursive-include django/conf/locale *
+recursive-include django/contrib/admin/templates
+recursive-include django/contrib/admin/media
+recursive-include django/contrib/comments/templates
+recursive-include django/contrib/sitemaps/templates
diff --git a/README b/README
index d52451d3ba..084f863a1e 100644
--- a/README
+++ b/README
@@ -25,10 +25,10 @@ http://code.djangoproject.com/newticket
To get more help:
* Join the #django channel on irc.freenode.net. Lots of helpful people
- hang out there. Read the archives at http://loglibrary.com/179 .
+ hang out there. Read the archives at http://simon.bofh.ms/logger/django/ .
* Join the django-users mailing list, or read the archives, at
- http://groups-beta.google.com/group/django-users.
+ http://groups.google.com/group/django-users.
To contribute to Django:
diff --git a/django/__init__.py b/django/__init__.py
index 00c6f82478..5d5461c867 100644
--- a/django/__init__.py
+++ b/django/__init__.py
@@ -1 +1 @@
-VERSION = (0, 95, 'post-magic-removal')
+VERSION = (0, 96, 'pre')
diff --git a/django/bin/compile-messages.py b/django/bin/compile-messages.py
index e33fdd780b..0137ec8dd4 100755
--- a/django/bin/compile-messages.py
+++ b/django/bin/compile-messages.py
@@ -2,7 +2,6 @@
import os
import sys
-import getopt
def compile_messages():
basedir = None
@@ -12,15 +11,25 @@ def compile_messages():
elif os.path.isdir('locale'):
basedir = os.path.abspath('locale')
else:
- print "this script should be run from the django svn tree or your project or app tree"
+ print "This script should be run from the Django SVN tree or your project or app tree."
sys.exit(1)
- for (dirpath, dirnames, filenames) in os.walk(basedir):
+ for dirpath, dirnames, filenames in os.walk(basedir):
for f in filenames:
if f.endswith('.po'):
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
pf = os.path.splitext(os.path.join(dirpath, f))[0]
- cmd = 'msgfmt -o "%s.mo" "%s.po"' % (pf, pf)
+ # Store the names of the .mo and .po files in an environment
+ # variable, rather than doing a string replacement into the
+ # command, so that we can take advantage of shell quoting, to
+ # quote any malicious characters/escaping.
+ # See http://cyberelk.net/tim/articles/cmdline/ar01s02.html
+ os.environ['djangocompilemo'] = pf + '.mo'
+ os.environ['djangocompilepo'] = pf + '.po'
+ if sys.platform == 'win32': # Different shell-variable syntax
+ cmd = 'msgfmt -o "%djangocompilemo%" "%djangocompilepo%"'
+ else:
+ cmd = 'msgfmt -o "$djangocompilemo" "$djangocompilepo"'
os.system(cmd)
if __name__ == "__main__":
diff --git a/django/bin/daily_cleanup.py b/django/bin/daily_cleanup.py
index 6eb5c17feb..667e0f16c6 100644
--- a/django/bin/daily_cleanup.py
+++ b/django/bin/daily_cleanup.py
@@ -1,16 +1,17 @@
-"Daily cleanup file"
+"""
+Daily cleanup job.
-from django.db import backend, connection, transaction
+Can be run as a cronjob to clean out old data from the database (only expired
+sessions at the moment).
+"""
-DOCUMENTATION_DIRECTORY = '/home/html/documentation/'
+from django.db import backend, connection, transaction
def clean_up():
# Clean up old database records
cursor = connection.cursor()
cursor.execute("DELETE FROM %s WHERE %s < NOW()" % \
- (backend.quote_name('core_sessions'), backend.quote_name('expire_date')))
- cursor.execute("DELETE FROM %s WHERE %s < NOW() - INTERVAL '1 week'" % \
- (backend.quote_name('registration_challenges'), backend.quote_name('request_date')))
+ (backend.quote_name('django_session'), backend.quote_name('expire_date')))
transaction.commit_unless_managed()
if __name__ == "__main__":
diff --git a/django/bin/make-messages.py b/django/bin/make-messages.py
index 75b0bc0ca0..557cb5eeec 100755
--- a/django/bin/make-messages.py
+++ b/django/bin/make-messages.py
@@ -1,5 +1,9 @@
#!/usr/bin/env python
+# Need to ensure that the i18n framework is enabled
+from django.conf import settings
+settings.configure(USE_I18N = True)
+
from django.utils.translation import templatize
import re
import os
diff --git a/django/conf/__init__.py b/django/conf/__init__.py
index a6a09d772f..1a04bbfb02 100644
--- a/django/conf/__init__.py
+++ b/django/conf/__init__.py
@@ -7,7 +7,6 @@ a list of all possible variables.
"""
import os
-import sys
from django.conf import global_settings
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
index 497a0d16aa..69c775cdec 100644
--- a/django/conf/global_settings.py
+++ b/django/conf/global_settings.py
@@ -46,6 +46,7 @@ LANGUAGES = (
('en', gettext_noop('English')),
('es', gettext_noop('Spanish')),
('es_AR', gettext_noop('Argentinean Spanish')),
+ ('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')),
('gl', gettext_noop('Galician')),
('hu', gettext_noop('Hungarian')),
@@ -55,6 +56,7 @@ LANGUAGES = (
('ja', gettext_noop('Japanese')),
('nl', gettext_noop('Dutch')),
('no', gettext_noop('Norwegian')),
+ ('pl', gettext_noop('Polish')),
('pt-br', gettext_noop('Brazilian')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
@@ -62,6 +64,8 @@ LANGUAGES = (
('sl', gettext_noop('Slovenian')),
('sr', gettext_noop('Serbian')),
('sv', gettext_noop('Swedish')),
+ ('ta', gettext_noop('Tamil')),
+ ('tr', gettext_noop('Turkish')),
('uk', gettext_noop('Ukrainian')),
('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese')),
@@ -220,10 +224,6 @@ YEAR_MONTH_FORMAT = 'F Y'
# http://www.djangoproject.com/documentation/templates/#now
MONTH_DAY_FORMAT = 'F j'
-# Whether to enable Psyco, which optimizes Python code. Requires Psyco.
-# http://psyco.sourceforge.net/
-ENABLE_PSYCO = False
-
# Do you want to manage transactions manually?
# Hint: you really don't!
TRANSACTIONS_MANAGED = False
@@ -251,6 +251,7 @@ MIDDLEWARE_CLASSES = (
SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want.
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie.
+SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only).
SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request.
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser.
@@ -269,6 +270,10 @@ CACHE_MIDDLEWARE_KEY_PREFIX = ''
COMMENTS_ALLOW_PROFANITIES = False
+# The profanities that will trigger a validation error in the
+# 'hasNoProfanities' validator. All of these should be in lowercase.
+PROFANITIES_LIST = ('asshat', 'asshead', 'asshole', 'cunt', 'fuck', 'gook', 'nigger', 'shit')
+
# The group ID that designates which users are banned.
# Set to None if you're not using it.
COMMENTS_BANNED_USERS_GROUP = None
@@ -294,3 +299,14 @@ BANNED_IPS = ()
##################
AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
+
+###########
+# TESTING #
+###########
+
+# The name of the method to use to invoke the test suite
+TEST_RUNNER = 'django.test.simple.run_tests'
+
+# The name of the database to use for testing purposes.
+# If None, a name of 'test_' + DATABASE_NAME will be assumed
+TEST_DATABASE_NAME = None
diff --git a/django/conf/locale/cs/LC_MESSAGES/django.mo b/django/conf/locale/cs/LC_MESSAGES/django.mo
index 8984023810..c2f04edb81 100644
--- a/django/conf/locale/cs/LC_MESSAGES/django.mo
+++ b/django/conf/locale/cs/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/cs/LC_MESSAGES/django.po b/django/conf/locale/cs/LC_MESSAGES/django.po
index cdbb124c94..0dcc31394c 100644
--- a/django/conf/locale/cs/LC_MESSAGES/django.po
+++ b/django/conf/locale/cs/LC_MESSAGES/django.po
@@ -8,15 +8,14 @@ msgstr ""
"Project-Id-Version: Django Czech translation\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:11+0200\n"
-"PO-Revision-Date: 2006-05-20 22:44+0100\n"
-"Last-Translator: Radek Å varz <translate@svarz.cz>\n"
+"PO-Revision-Date: 2006-10-07 13:10+0100\n"
+"Last-Translator: \n"
"Language-Team: Czech\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Poedit-Country: CZECH REPUBLIC\n"
-"X-Poedit-Bookmarks: -1,-1,-1,-1,-1,-1,-1,-1,-1,139\n"
#: contrib/comments/models.py:67
#: contrib/comments/models.py:166
@@ -80,7 +79,7 @@ msgid "is public"
msgstr "je veřejné"
#: contrib/comments/models.py:85
-#: contrib/admin/views/doc.py:289
+#: contrib/admin/views/doc.py:304
msgid "IP address"
msgstr "IP adresa"
@@ -214,11 +213,11 @@ msgstr "Neplatné ID komentáře"
msgid "No voting for yourself"
msgstr "Nelze hlasovat pro sebe"
-#: contrib/comments/views/comments.py:28
+#: contrib/comments/views/comments.py:27
msgid "This rating is required because you've entered at least one other rating."
msgstr "Toto hodnocení je povinné, protože jste zadal(a) alespoň jedno jiné hodnocení."
-#: contrib/comments/views/comments.py:112
+#: contrib/comments/views/comments.py:111
#, python-format
msgid ""
"This comment was posted by a user who has posted fewer than %(count)s comment:\n"
@@ -241,7 +240,7 @@ msgstr[2] ""
"\n"
"%(text)s"
-#: contrib/comments/views/comments.py:117
+#: contrib/comments/views/comments.py:116
#, python-format
msgid ""
"This comment was posted by a sketchy user:\n"
@@ -252,22 +251,22 @@ msgstr ""
"\n"
"%(text)s"
-#: contrib/comments/views/comments.py:189
+#: contrib/comments/views/comments.py:188
#: contrib/comments/views/comments.py:280
msgid "Only POSTs are allowed"
msgstr "Je povolená pouze metoda POST"
-#: contrib/comments/views/comments.py:193
+#: contrib/comments/views/comments.py:192
#: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted"
msgstr "Jedno nebo více povinných polí nebylo vyplněné"
-#: contrib/comments/views/comments.py:197
+#: contrib/comments/views/comments.py:196
#: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)"
msgstr "NÄ›kdo falÅ¡oval formulář komentáře (bezpeÄnostní naruÅ¡ení)"
-#: contrib/comments/views/comments.py:207
+#: contrib/comments/views/comments.py:206
#: contrib/comments/views/comments.py:292
msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid"
msgstr "Formulář komentáře měl neplatný parametr 'target' -- ID objektu nebylo platné"
@@ -284,18 +283,9 @@ msgid "Username:"
msgstr "Uživatelské jméno:"
#: contrib/comments/templates/comments/form.html:6
-#: contrib/admin/templates/admin/login.html:20
-msgid "Password:"
-msgstr "Heslo:"
-
-#: contrib/comments/templates/comments/form.html:6
-msgid "Forgotten your password?"
-msgstr "Zapomenuté heslo?"
-
-#: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:3
@@ -313,6 +303,15 @@ msgstr "Zapomenuté heslo?"
msgid "Log out"
msgstr "Odhlásit se"
+#: contrib/comments/templates/comments/form.html:8
+#: contrib/admin/templates/admin/login.html:20
+msgid "Password:"
+msgstr "Heslo:"
+
+#: contrib/comments/templates/comments/form.html:8
+msgid "Forgotten your password?"
+msgstr "Zapomenuté heslo?"
+
#: contrib/comments/templates/comments/form.html:12
msgid "Ratings"
msgstr "Hodnocení"
@@ -331,13 +330,13 @@ msgstr "Volitelné"
msgid "Post a photo"
msgstr "Zařadit fotografii"
-#: contrib/comments/templates/comments/form.html:27
+#: contrib/comments/templates/comments/form.html:28
#: contrib/comments/templates/comments/freeform.html:5
msgid "Comment:"
msgstr "Komentář:"
-#: contrib/comments/templates/comments/form.html:32
-#: contrib/comments/templates/comments/freeform.html:9
+#: contrib/comments/templates/comments/form.html:35
+#: contrib/comments/templates/comments/freeform.html:10
msgid "Preview comment"
msgstr "Náhled komentáře"
@@ -357,6 +356,7 @@ msgstr ""
#: contrib/admin/filterspecs.py:70
#: contrib/admin/filterspecs.py:88
#: contrib/admin/filterspecs.py:143
+#: contrib/admin/filterspecs.py:169
msgid "All"
msgstr "Vše"
@@ -420,217 +420,292 @@ msgstr "log záznam"
msgid "log entries"
msgstr "log záznamy"
-#: contrib/admin/templatetags/admin_list.py:228
+#: contrib/admin/templatetags/admin_list.py:230
msgid "All dates"
msgstr "Všechna data"
-#: contrib/admin/views/decorators.py:9
-#: contrib/auth/forms.py:36
-#: contrib/auth/forms.py:41
+#: contrib/admin/views/decorators.py:10
+#: contrib/auth/forms.py:59
msgid "Please enter a correct username and password. Note that both fields are case-sensitive."
msgstr "Prosíme, vložte správné uživatelské jméno a heslo. Poznámka - u obou položek se rozlišuje velikost písmen."
-#: contrib/admin/views/decorators.py:23
+#: contrib/admin/views/decorators.py:24
#: contrib/admin/templates/admin/login.html:25
msgid "Log in"
msgstr "Přihlášení"
-#: contrib/admin/views/decorators.py:61
+#: contrib/admin/views/decorators.py:62
msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved."
msgstr "Prosíme, znovu se přihlašte, Vaše sezení vypršelo. Nemusíte se obávat, Vaše podání je uloženo."
-#: contrib/admin/views/decorators.py:68
+#: contrib/admin/views/decorators.py:69
msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again."
msgstr "Vypadá to, že Váš prohlížeÄ není nastaven, aby akceptoval cookies. Prosíme, zapnÄ›te cookies, obnovte tuto stránku a zkuste znovu."
-#: contrib/admin/views/decorators.py:82
+#: contrib/admin/views/decorators.py:83
msgid "Usernames cannot contain the '@' character."
msgstr "Uživatelská jména nemohou obsahovat znak '@'."
-#: contrib/admin/views/decorators.py:84
+#: contrib/admin/views/decorators.py:85
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
msgstr "Vaše e-mailová adresa není Vaše uživatelské jméno. Zkuste místo toho '%s'."
-#: contrib/admin/views/main.py:226
+#: contrib/admin/views/main.py:223
msgid "Site administration"
msgstr "Django správa"
-#: contrib/admin/views/main.py:260
+#: contrib/admin/views/main.py:257
+#: contrib/admin/views/auth.py:17
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "Záznam %(name)s \"%(obj)s\" byl úspěšně přidán."
-#: contrib/admin/views/main.py:264
-#: contrib/admin/views/main.py:348
+#: contrib/admin/views/main.py:261
+#: contrib/admin/views/main.py:347
+#: contrib/admin/views/auth.py:22
msgid "You may edit it again below."
msgstr "Můžete to opět upravit níže."
-#: contrib/admin/views/main.py:272
-#: contrib/admin/views/main.py:357
+#: contrib/admin/views/main.py:271
+#: contrib/admin/views/main.py:356
#, python-format
msgid "You may add another %s below."
msgstr "Můžete přidat další %s níže."
-#: contrib/admin/views/main.py:290
+#: contrib/admin/views/main.py:289
#, python-format
msgid "Add %s"
msgstr "%s: přidat"
-#: contrib/admin/views/main.py:336
+#: contrib/admin/views/main.py:335
#, python-format
msgid "Added %s."
msgstr "Záznam %s byl přidán."
-#: contrib/admin/views/main.py:336
-#: contrib/admin/views/main.py:338
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:335
+#: contrib/admin/views/main.py:337
+#: contrib/admin/views/main.py:339
msgid "and"
msgstr "a"
-#: contrib/admin/views/main.py:338
+#: contrib/admin/views/main.py:337
#, python-format
msgid "Changed %s."
msgstr "%s: změněno"
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:339
#, python-format
msgid "Deleted %s."
msgstr "Záznam %s byl smazán."
-#: contrib/admin/views/main.py:343
+#: contrib/admin/views/main.py:342
msgid "No fields changed."
msgstr "Nebyly změněny žádné pole."
-#: contrib/admin/views/main.py:346
+#: contrib/admin/views/main.py:345
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr "%(name)s \"%(obj)s\" byl úspěšně změněn."
-#: contrib/admin/views/main.py:354
+#: contrib/admin/views/main.py:353
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr "The %(name)s \"%(obj)s\" byl úspěšně přidán. Můžete to opět upravit níže."
-#: contrib/admin/views/main.py:392
+#: contrib/admin/views/main.py:391
#, python-format
msgid "Change %s"
msgstr "%s: změnit"
-#: contrib/admin/views/main.py:470
+#: contrib/admin/views/main.py:473
#, python-format
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
msgstr "Jedno nebo více %(fieldname)s z %(name)s: %(obj)s"
-#: contrib/admin/views/main.py:475
+#: contrib/admin/views/main.py:478
#, python-format
msgid "One or more %(fieldname)s in %(name)s:"
msgstr "Jedno nebo více %(fieldname)s z %(name)s:"
-#: contrib/admin/views/main.py:508
+#: contrib/admin/views/main.py:511
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "Záznam %(name)s \"%(obj)s\" byl úspěšně smazán."
-#: contrib/admin/views/main.py:511
+#: contrib/admin/views/main.py:514
msgid "Are you sure?"
msgstr "Jste si jist(á)?"
-#: contrib/admin/views/main.py:533
+#: contrib/admin/views/main.py:536
#, python-format
msgid "Change history: %s"
msgstr "Historie změn: %s"
-#: contrib/admin/views/main.py:565
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s"
msgstr "Vybrat %s"
-#: contrib/admin/views/main.py:565
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s to change"
msgstr "Vyberte %s pro změnu"
-#: contrib/admin/views/doc.py:277
-#: contrib/admin/views/doc.py:286
-#: contrib/admin/views/doc.py:288
-#: contrib/admin/views/doc.py:294
-#: contrib/admin/views/doc.py:295
-#: contrib/admin/views/doc.py:297
+#: contrib/admin/views/main.py:758
+msgid "Database error"
+msgstr "Databázová chyba"
+
+#: contrib/admin/views/doc.py:46
+#: contrib/admin/views/doc.py:48
+#: contrib/admin/views/doc.py:50
+msgid "tag:"
+msgstr "tag:"
+
+#: contrib/admin/views/doc.py:77
+#: contrib/admin/views/doc.py:79
+#: contrib/admin/views/doc.py:81
+msgid "filter:"
+msgstr "filtr:"
+
+#: contrib/admin/views/doc.py:135
+#: contrib/admin/views/doc.py:137
+#: contrib/admin/views/doc.py:139
+msgid "view:"
+msgstr "pohled (view):"
+
+#: contrib/admin/views/doc.py:164
+#, python-format
+msgid "App %r not found"
+msgstr "Aplikace %r nenalezena"
+
+#: contrib/admin/views/doc.py:171
+#, python-format
+msgid "Model %r not found in app %r"
+msgstr "Model %r v aplikaci %r nenalezen"
+
+#: contrib/admin/views/doc.py:183
+#, python-format
+msgid "the related `%s.%s` object"
+msgstr "související objekt `%s.%s`"
+
+#: contrib/admin/views/doc.py:183
+#: contrib/admin/views/doc.py:205
+#: contrib/admin/views/doc.py:219
+#: contrib/admin/views/doc.py:224
+msgid "model:"
+msgstr "model:"
+
+#: contrib/admin/views/doc.py:214
+#, python-format
+msgid "related `%s.%s` objects"
+msgstr "související objekty `%s.%s`"
+
+#: contrib/admin/views/doc.py:219
+#, python-format
+msgid "all %s"
+msgstr "%s: vše"
+
+#: contrib/admin/views/doc.py:224
+#, python-format
+msgid "number of %s"
+msgstr "%s: poÄet"
+
+#: contrib/admin/views/doc.py:229
+#, python-format
+msgid "Fields on %s objects"
+msgstr "Pole na objektech %s"
+
+#: contrib/admin/views/doc.py:291
+#: contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:303
+#: contrib/admin/views/doc.py:309
+#: contrib/admin/views/doc.py:310
+#: contrib/admin/views/doc.py:312
msgid "Integer"
msgstr "Celé Äíslo"
-#: contrib/admin/views/doc.py:278
+#: contrib/admin/views/doc.py:292
msgid "Boolean (Either True or False)"
msgstr "Boolean (buÄ Ano (True), nebo Ne (False))"
-#: contrib/admin/views/doc.py:279
-#: contrib/admin/views/doc.py:296
+#: contrib/admin/views/doc.py:293
+#: contrib/admin/views/doc.py:311
#, python-format
msgid "String (up to %(maxlength)s)"
msgstr "Text (maximálně %(maxlength)s znaků)"
-#: contrib/admin/views/doc.py:280
+#: contrib/admin/views/doc.py:294
msgid "Comma-separated integers"
msgstr "Celá Äísla oddÄ›lená Äárkou"
-#: contrib/admin/views/doc.py:281
+#: contrib/admin/views/doc.py:295
msgid "Date (without time)"
msgstr "Datum (bez Äasu)"
-#: contrib/admin/views/doc.py:282
+#: contrib/admin/views/doc.py:296
msgid "Date (with time)"
msgstr "Datum (s Äasem)"
-#: contrib/admin/views/doc.py:283
+#: contrib/admin/views/doc.py:297
msgid "E-mail address"
msgstr "E-mailová adresa"
-#: contrib/admin/views/doc.py:284
-#: contrib/admin/views/doc.py:287
+#: contrib/admin/views/doc.py:298
+#: contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:302
msgid "File path"
msgstr "Cesta k souboru"
-#: contrib/admin/views/doc.py:285
+#: contrib/admin/views/doc.py:300
msgid "Decimal number"
msgstr "Desetiné Äíslo"
-#: contrib/admin/views/doc.py:291
+#: contrib/admin/views/doc.py:306
msgid "Boolean (Either True, False or None)"
msgstr "Boolean (buÄ Ano (True), Ne (False), nebo Nic (None))"
-#: contrib/admin/views/doc.py:292
+#: contrib/admin/views/doc.py:307
msgid "Relation to parent model"
msgstr "V relaci k rodiÄovskému modelu"
-#: contrib/admin/views/doc.py:293
+#: contrib/admin/views/doc.py:308
msgid "Phone number"
msgstr "Telefonní Äíslo"
-#: contrib/admin/views/doc.py:298
+#: contrib/admin/views/doc.py:313
msgid "Text"
msgstr "Text"
-#: contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:314
msgid "Time"
msgstr "ÄŒas"
-#: contrib/admin/views/doc.py:300
+#: contrib/admin/views/doc.py:315
#: contrib/flatpages/models.py:7
msgid "URL"
msgstr "URL"
-#: contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:316
msgid "U.S. state (two uppercase letters)"
msgstr "Stát US (2 velké znaky)"
-#: contrib/admin/views/doc.py:302
+#: contrib/admin/views/doc.py:317
msgid "XML text"
msgstr "text XML"
+#: contrib/admin/views/doc.py:343
+#, python-format
+msgid "%s does not appear to be a urlpattern object"
+msgstr "%s pravděpodobně není objekt urlpattern"
+
+#: contrib/admin/views/auth.py:28
+msgid "Add user"
+msgstr "Přidat uživatele"
+
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:3
@@ -641,7 +716,7 @@ msgstr "Dokumentace"
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:3
@@ -662,9 +737,10 @@ msgstr "Změnit heslo"
#: contrib/admin/templates/admin/object_history.html:5
#: contrib/admin/templates/admin/500.html:4
#: contrib/admin/templates/admin/change_list.html:6
-#: contrib/admin/templates/admin/base.html:28
+#: contrib/admin/templates/admin/base.html:30
#: contrib/admin/templates/admin/delete_confirmation.html:6
#: contrib/admin/templates/admin/change_form.html:13
+#: contrib/admin/templates/admin/invalid_setup.html:4
#: contrib/admin/templates/registration/password_change_done.html:4
#: contrib/admin/templates/registration/password_reset_form.html:4
#: contrib/admin/templates/registration/logged_out.html:4
@@ -737,6 +813,11 @@ msgstr "Je nám líto, ale vyžádaná stránka nebyla nalezena."
msgid "Models available in the %(name)s application."
msgstr "Dostupné modely v aplikaci %(name)s."
+#: contrib/admin/templates/admin/index.html:18
+#, python-format
+msgid "%(name)s"
+msgstr "%(name)s"
+
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
msgid "Add"
@@ -771,7 +852,7 @@ msgstr "%(name)s: přidat"
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "<a href=\"/password_reset/\">Zapomněl(a) jste své heslo?</a>"
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
msgid "Welcome,"
msgstr "Vítejte,"
@@ -782,13 +863,13 @@ msgstr "Smazat"
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
-msgid "Deleting the %(object_name)s '%(object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:"
-msgstr "Mazání %(object_name)s '%(object)s' by vyústilo ve vymazání souvisejících objektů, ale Váš úÄet nemá oprávnÄ›ní pro mazání následujících typů objektů:"
+msgid "Deleting the %(object_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:"
+msgstr "Mazání %(object_name)s '%(escaped_object)s' by vyústilo ve vymazání souvisejících objektů, ale Váš úÄet nemá oprávnÄ›ní pro mazání následujících typů objektů:"
#: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format
-msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of the following related items will be deleted:"
-msgstr "Jste si jist(á), že chcete smazat %(object_name)s \"%(object)s\"? Všechny následující související položky budou smazány:"
+msgid "Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:"
+msgstr "Jste si jist(á), že chcete smazat %(object_name)s \"%(escaped_object)s\"? Všechny následující související položky budou smazány:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure"
@@ -796,13 +877,34 @@ msgstr "Ano, jsem si jist"
#: contrib/admin/templates/admin/filter.html:2
#, python-format
-msgid " By %(title)s "
-msgstr "Od %(title)s"
+msgid " By %(filter_title)s "
+msgstr " Dle %(filter_title)s "
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
msgstr "Provést"
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "1 result"
+msgid_plural "%(counter)s results"
+msgstr[0] "1 výsledek"
+msgstr[1] "%(counter)s výsledky"
+msgstr[2] "%(counter)s výsledků"
+
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "%(full_result_count)s total"
+msgstr "celkem %(full_result_count)s"
+
+#: contrib/admin/templates/admin/pagination.html:10
+msgid "Show all"
+msgstr "Zobrazit všechny"
+
+#: contrib/admin/templates/admin/filters.html:4
+msgid "Filter"
+msgstr "Filtr"
+
#: contrib/admin/templates/admin/change_form.html:21
msgid "View on site"
msgstr "Pohled na stránku"
@@ -838,6 +940,30 @@ msgstr "Uložit a pokraÄovat v úpravách"
msgid "Save"
msgstr "Uložit"
+#: contrib/admin/templates/admin/invalid_setup.html:8
+msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user."
+msgstr "NÄ›co není v pořádku s Vaší instalací databáze. UjistÄ›te se, že byly vytvoÅ™eny odpovídající tabulky databáze a že databáze je přístupná pro Ätení daným databázovým uživatelem."
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:6
+msgid "First, enter a username and password. Then, you'll be able to edit more user options."
+msgstr "Nejdříve vložte uživatelské jméno a heslo. Poté budete moci upravovat více uživatelských možností."
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:12
+msgid "Username"
+msgstr "Uživatelské jméno"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:18
+msgid "Password"
+msgstr "Heslo"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:23
+msgid "Password (again)"
+msgstr "Heslo (znova)"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:24
+msgid "Enter the same password as above, for verification."
+msgstr "Pro ověření vložte stejné heslo znovu."
+
#: contrib/admin/templates/registration/password_change_done.html:4
#: contrib/admin/templates/registration/password_change_form.html:4
#: contrib/admin/templates/registration/password_change_form.html:6
@@ -1031,11 +1157,11 @@ msgstr "přesměrovat na"
msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'."
msgstr "Toto může být buÄ absolutní cesta (jako nahoÅ™e) nebo plné URL zaÄínající na 'http://'."
-#: contrib/redirects/models.py:12
+#: contrib/redirects/models.py:13
msgid "redirect"
msgstr "přesměrovat"
-#: contrib/redirects/models.py:13
+#: contrib/redirects/models.py:14
msgid "redirects"
msgstr "přesměrování"
@@ -1060,8 +1186,8 @@ msgid "template name"
msgstr "jméno šablony"
#: contrib/flatpages/models.py:13
-msgid "Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'."
-msgstr "Například: 'flatfiles/kontaktni_stranka'. Pokud toto není zadáno, systém použije 'flatfiles/default'."
+msgid "Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'."
+msgstr "Například: 'flatpages/kontaktni_stranka.html'. Pokud toto není zadáno, systém použije 'flatpages/default.html'."
#: contrib/flatpages/models.py:14
msgid "registration required"
@@ -1079,150 +1205,170 @@ msgstr "statická stránka"
msgid "flat pages"
msgstr "statické stránky"
-#: contrib/auth/models.py:13
-#: contrib/auth/models.py:26
+#: contrib/auth/views.py:39
+msgid "Logged out"
+msgstr "Odhlášeno"
+
+#: contrib/auth/models.py:38
+#: contrib/auth/models.py:57
msgid "name"
msgstr "jméno"
-#: contrib/auth/models.py:15
+#: contrib/auth/models.py:40
msgid "codename"
msgstr "codename"
-#: contrib/auth/models.py:17
+#: contrib/auth/models.py:42
msgid "permission"
msgstr "oprávnění"
-#: contrib/auth/models.py:18
-#: contrib/auth/models.py:27
+#: contrib/auth/models.py:43
+#: contrib/auth/models.py:58
msgid "permissions"
msgstr "oprávnění"
-#: contrib/auth/models.py:29
+#: contrib/auth/models.py:60
msgid "group"
msgstr "skupina"
-#: contrib/auth/models.py:30
-#: contrib/auth/models.py:65
+#: contrib/auth/models.py:61
+#: contrib/auth/models.py:100
msgid "groups"
msgstr "skupiny"
-#: contrib/auth/models.py:55
+#: contrib/auth/models.py:90
msgid "username"
msgstr "uživatelské jméno"
-#: contrib/auth/models.py:56
+#: contrib/auth/models.py:90
+msgid "Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."
+msgstr "Požadováno. 30 znaků nebo ménÄ›. Pouze alfanumerické znaky (znaky, Äísla a podtržítka)."
+
+#: contrib/auth/models.py:91
msgid "first name"
msgstr "křestní jméno"
-#: contrib/auth/models.py:57
+#: contrib/auth/models.py:92
msgid "last name"
msgstr "příjmení"
-#: contrib/auth/models.py:58
+#: contrib/auth/models.py:93
msgid "e-mail address"
msgstr "e-mailová adresa"
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "password"
msgstr "heslo"
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "Use '[algo]$[salt]$[hexdigest]'"
msgstr "Použijte '[algo]$[salt]$[hexdigest]'"
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "staff status"
msgstr "administrativní přístup "
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "Designates whether the user can log into this admin site."
msgstr "Rozhodne, zda se může uživatel přihlásit do správy webu."
-#: contrib/auth/models.py:61
+#: contrib/auth/models.py:96
msgid "active"
msgstr "aktivní"
-#: contrib/auth/models.py:62
+#: contrib/auth/models.py:96
+msgid "Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts."
+msgstr "Rozhodne, zda se může uživatel pÅ™ihlásit do správy webu. Nastavte toto místo mazání úÄtů."
+
+#: contrib/auth/models.py:97
msgid "superuser status"
msgstr "stav superuživatel"
-#: contrib/auth/models.py:63
+#: contrib/auth/models.py:97
+msgid "Designates that this user has all permissions without explicitly assigning them."
+msgstr "Stanoví, že tento uživatel má veškerá oprávnění bez jejich explicitního přiřazení."
+
+#: contrib/auth/models.py:98
msgid "last login"
msgstr "poslední přihlášení"
-#: contrib/auth/models.py:64
+#: contrib/auth/models.py:99
msgid "date joined"
msgstr "datum zaregistrování"
-#: contrib/auth/models.py:66
+#: contrib/auth/models.py:101
msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."
msgstr "Kromě manuálně přidělených oprávnění uživatel dostane všechna oprávnění pro každou skupinu, ve které je."
-#: contrib/auth/models.py:67
+#: contrib/auth/models.py:102
msgid "user permissions"
msgstr "uživatelskí oprávnění"
-#: contrib/auth/models.py:70
+#: contrib/auth/models.py:105
msgid "user"
msgstr "uživatel"
-#: contrib/auth/models.py:71
+#: contrib/auth/models.py:106
msgid "users"
msgstr "uživatelé"
-#: contrib/auth/models.py:76
+#: contrib/auth/models.py:111
msgid "Personal info"
msgstr "Osobní informace"
-#: contrib/auth/models.py:77
+#: contrib/auth/models.py:112
msgid "Permissions"
msgstr "Oprávnění"
-#: contrib/auth/models.py:78
+#: contrib/auth/models.py:113
msgid "Important dates"
msgstr "Důležitá data"
-#: contrib/auth/models.py:79
+#: contrib/auth/models.py:114
msgid "Groups"
msgstr "Skupiny"
-#: contrib/auth/models.py:219
+#: contrib/auth/models.py:256
msgid "message"
msgstr "zpráva"
-#: contrib/auth/forms.py:30
+#: contrib/auth/forms.py:52
msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."
msgstr "Váš prohlížeÄ pravdÄ›podobnÄ› nemá zapnuté cookies. Cookies jsou potÅ™eba pro zalogování."
-#: contrib/contenttypes/models.py:25
+#: contrib/auth/forms.py:61
+msgid "This account is inactive."
+msgstr "Tento úÄet není aktivní."
+
+#: contrib/contenttypes/models.py:20
msgid "python model class name"
msgstr "jméno modelu Pythonu"
-#: contrib/contenttypes/models.py:28
+#: contrib/contenttypes/models.py:23
msgid "content type"
msgstr "typ obsahu"
-#: contrib/contenttypes/models.py:29
+#: contrib/contenttypes/models.py:24
msgid "content types"
msgstr "typy obsahu"
-#: contrib/sessions/models.py:35
+#: contrib/sessions/models.py:51
msgid "session key"
msgstr "klÃ­Ä sezení"
-#: contrib/sessions/models.py:36
+#: contrib/sessions/models.py:52
msgid "session data"
msgstr "data sezení"
-#: contrib/sessions/models.py:37
+#: contrib/sessions/models.py:53
msgid "expire date"
msgstr "datum expirace"
-#: contrib/sessions/models.py:41
+#: contrib/sessions/models.py:57
msgid "session"
msgstr "sezení"
-#: contrib/sessions/models.py:42
+#: contrib/sessions/models.py:58
msgid "sessions"
msgstr "sezení"
@@ -1242,18 +1388,6 @@ msgstr "web"
msgid "sites"
msgstr "weby"
-#: utils/translation.py:360
-msgid "DATE_FORMAT"
-msgstr "j.n.Y"
-
-#: utils/translation.py:361
-msgid "DATETIME_FORMAT"
-msgstr "j.n.Y, H:i"
-
-#: utils/translation.py:362
-msgid "TIME_FORMAT"
-msgstr "H:i"
-
#: utils/dates.py:6
msgid "Monday"
msgstr "Pondělí"
@@ -1453,203 +1587,263 @@ msgstr[0] "minuta"
msgstr[1] "minuty"
msgstr[2] "minut"
-#: conf/global_settings.py:37
+#: utils/translation/trans_real.py:362
+msgid "DATE_FORMAT"
+msgstr "j.n.Y"
+
+#: utils/translation/trans_real.py:363
+msgid "DATETIME_FORMAT"
+msgstr "j.n.Y, H:i"
+
+#: utils/translation/trans_real.py:364
+msgid "TIME_FORMAT"
+msgstr "H:i"
+
+#: utils/translation/trans_real.py:380
+msgid "YEAR_MONTH_FORMAT"
+msgstr "F Y"
+
+#: utils/translation/trans_real.py:381
+msgid "MONTH_DAY_FORMAT"
+msgstr "j. F"
+
+#: conf/global_settings.py:39
+msgid "Arabic"
+msgstr "Arabic"
+
+#: conf/global_settings.py:40
msgid "Bengali"
msgstr "Bengálsky"
-#: conf/global_settings.py:38
+#: conf/global_settings.py:41
msgid "Czech"
msgstr "ÄŒesky"
-#: conf/global_settings.py:39
+#: conf/global_settings.py:42
msgid "Welsh"
msgstr "Welšsky"
-#: conf/global_settings.py:40
+#: conf/global_settings.py:43
msgid "Danish"
msgstr "Dánsky"
-#: conf/global_settings.py:41
+#: conf/global_settings.py:44
msgid "German"
msgstr "Německy"
-#: conf/global_settings.py:42
+#: conf/global_settings.py:45
msgid "Greek"
msgstr "Řecky"
-#: conf/global_settings.py:43
+#: conf/global_settings.py:46
msgid "English"
msgstr "Anglicky"
-#: conf/global_settings.py:44
+#: conf/global_settings.py:47
msgid "Spanish"
msgstr "Španělsky"
-#: conf/global_settings.py:45
+#: conf/global_settings.py:48
+msgid "Argentinean Spanish"
+msgstr "Argentinean Spanish"
+
+#: conf/global_settings.py:49
+msgid "Finnish"
+msgstr "Finsky"
+
+#: conf/global_settings.py:50
msgid "French"
msgstr "Francouzsky"
-#: conf/global_settings.py:46
+#: conf/global_settings.py:51
msgid "Galician"
msgstr "Galicijsky"
-#: conf/global_settings.py:47
+#: conf/global_settings.py:52
msgid "Hungarian"
msgstr "MaÄarsky"
-#: conf/global_settings.py:48
+#: conf/global_settings.py:53
msgid "Hebrew"
msgstr "Hebrejsky"
-#: conf/global_settings.py:49
+#: conf/global_settings.py:54
msgid "Icelandic"
msgstr "Islandština"
-#: conf/global_settings.py:50
+#: conf/global_settings.py:55
msgid "Italian"
msgstr "Italsky"
-#: conf/global_settings.py:51
+#: conf/global_settings.py:56
msgid "Japanese"
msgstr "Japonština"
-#: conf/global_settings.py:52
+#: conf/global_settings.py:57
msgid "Dutch"
msgstr "Holandština"
-#: conf/global_settings.py:53
+#: conf/global_settings.py:58
msgid "Norwegian"
msgstr "Norsky"
-#: conf/global_settings.py:54
+#: conf/global_settings.py:59
msgid "Brazilian"
msgstr "Brazilsky"
-#: conf/global_settings.py:55
+#: conf/global_settings.py:60
msgid "Romanian"
msgstr "Rumunsky"
-#: conf/global_settings.py:56
+#: conf/global_settings.py:61
msgid "Russian"
msgstr "Rusky"
-#: conf/global_settings.py:57
+#: conf/global_settings.py:62
msgid "Slovak"
msgstr "Slovensky"
-#: conf/global_settings.py:58
+#: conf/global_settings.py:63
msgid "Slovenian"
msgstr "Slovinsky"
-#: conf/global_settings.py:59
+#: conf/global_settings.py:64
msgid "Serbian"
msgstr "Srbsky"
-#: conf/global_settings.py:60
+#: conf/global_settings.py:65
msgid "Swedish"
msgstr "Švédsky"
-#: conf/global_settings.py:61
+#: conf/global_settings.py:66
+msgid "Tamil"
+msgstr "Tamil"
+
+#: conf/global_settings.py:67
+msgid "Turkish"
+msgstr "Turecky"
+
+#: conf/global_settings.py:68
msgid "Ukrainian"
msgstr "Ukrajinsky"
-#: conf/global_settings.py:62
+#: conf/global_settings.py:69
msgid "Simplified Chinese"
msgstr "Jednoduchá ÄínÅ¡tina"
-#: conf/global_settings.py:63
+#: conf/global_settings.py:70
msgid "Traditional Chinese"
msgstr "TradiÄní ÄínÅ¡tina"
-#: core/validators.py:60
+#: core/validators.py:63
msgid "This value must contain only letters, numbers and underscores."
msgstr "Tato hodnota musí obsahovat pouze znaky, Äísla nebo podtržítka."
-#: core/validators.py:64
+#: core/validators.py:67
msgid "This value must contain only letters, numbers, underscores, dashes or slashes."
msgstr "Tato hodnota musí obsahovat pouze znaky, Äísla, podtržítka, pomlÄky nebo lomítka."
-#: core/validators.py:72
+#: core/validators.py:71
+msgid "This value must contain only letters, numbers, underscores or hyphens."
+msgstr "Tato hodnota musí obsahovat pouze znaky, Äísla, podtržítka nebo Äárky."
+
+#: core/validators.py:75
msgid "Uppercase letters are not allowed here."
msgstr "Velká písmena zde nejsou povolená."
-#: core/validators.py:76
+#: core/validators.py:79
msgid "Lowercase letters are not allowed here."
msgstr "Malá písmena zde nejsou povolená."
-#: core/validators.py:83
+#: core/validators.py:86
msgid "Enter only digits separated by commas."
msgstr "Vložte pouze cifry oddÄ›lené Äárkami."
-#: core/validators.py:95
+#: core/validators.py:98
msgid "Enter valid e-mail addresses separated by commas."
msgstr "Vložte platné e-mailové adresy oddÄ›lené Äárkami."
-#: core/validators.py:99
+#: core/validators.py:102
msgid "Please enter a valid IP address."
msgstr "Prosíme, zadejte platnou IP adresu."
-#: core/validators.py:103
+#: core/validators.py:106
msgid "Empty values are not allowed here."
msgstr "Zde nejsou povolené prázdné hodnoty."
-#: core/validators.py:107
+#: core/validators.py:110
msgid "Non-numeric characters aren't allowed here."
msgstr "Znaky, které nejsou Äísla, nejsou zde povoleny."
-#: core/validators.py:111
+#: core/validators.py:114
msgid "This value can't be comprised solely of digits."
msgstr "Tato hodnota nemůže být složená pouze z cifer."
-#: core/validators.py:116
+#: core/validators.py:119
msgid "Enter a whole number."
msgstr "Vložte celé Äíslo."
-#: core/validators.py:120
+#: core/validators.py:123
msgid "Only alphabetical characters are allowed here."
msgstr "Zde jsou povoleny pouze alfanumerické znaky."
-#: core/validators.py:124
+#: core/validators.py:138
+msgid "Year must be 1900 or later."
+msgstr "Rok musí být 1900 a vyšší."
+
+#: core/validators.py:142
+#, python-format
+msgid "Invalid date: %s."
+msgstr "Neplatné datum: %s."
+
+#: core/validators.py:146
+#: db/models/fields/__init__.py:415
msgid "Enter a valid date in YYYY-MM-DD format."
msgstr "Vložte platné datum ve formátu RRRR-MM-DD."
-#: core/validators.py:128
+#: core/validators.py:151
msgid "Enter a valid time in HH:MM format."
msgstr "Vložte platný Äas ve formátu HH:MM."
-#: core/validators.py:132
-#: db/models/fields/__init__.py:468
+#: core/validators.py:155
+#: db/models/fields/__init__.py:477
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr "Vložte platné datum a Äas ve formátu RRRR-MM-DD HH:MM."
-#: core/validators.py:136
+#: core/validators.py:160
msgid "Enter a valid e-mail address."
msgstr "Vložte platnou e-mailovou adresu."
-#: core/validators.py:148
+#: core/validators.py:172
+#: core/validators.py:401
+#: forms/__init__.py:661
+msgid "No file was submitted. Check the encoding type on the form."
+msgstr "Soubor nebyl odeslán. Zkontrolujte encoding type formuláře."
+
+#: core/validators.py:176
msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image."
msgstr "Nahrajte na server platný obrázek. Soubor, který jste nahrál(a) nebyl obrázek, nebo byl porušen."
-#: core/validators.py:155
+#: core/validators.py:183
#, python-format
msgid "The URL %s does not point to a valid image."
msgstr "URL %s neukazuje na platný obrázek."
-#: core/validators.py:159
+#: core/validators.py:187
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr "Telefonní Äísla musí být ve formátu XXX-XXX-XXXX. \"%s\" není platné."
-#: core/validators.py:167
+#: core/validators.py:195
#, python-format
msgid "The URL %s does not point to a valid QuickTime video."
msgstr "URL %s neodkazuje na platné video ve formátu QuickTime."
-#: core/validators.py:171
+#: core/validators.py:199
msgid "A valid URL is required."
msgstr "Je vyžadováno platné URL."
-#: core/validators.py:185
+#: core/validators.py:213
#, python-format
msgid ""
"Valid HTML is required. Specific errors are:\n"
@@ -1658,27 +1852,27 @@ msgstr ""
"Je vyžadováno platné HTML. Konkrétní chyby jsou:\n"
"%s"
-#: core/validators.py:192
+#: core/validators.py:220
#, python-format
msgid "Badly formed XML: %s"
msgstr "Špatně formované XML: %s"
-#: core/validators.py:202
+#: core/validators.py:230
#, python-format
msgid "Invalid URL: %s"
msgstr "Neplatné URL: %s"
-#: core/validators.py:206
-#: core/validators.py:208
+#: core/validators.py:234
+#: core/validators.py:236
#, python-format
msgid "The URL %s is a broken link."
msgstr "Odkaz na URL %s je rozbitý."
-#: core/validators.py:214
+#: core/validators.py:242
msgid "Enter a valid U.S. state abbreviation."
msgstr "Vložte platnou zkraku U.S. státu."
-#: core/validators.py:229
+#: core/validators.py:256
#, python-format
msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
@@ -1686,44 +1880,44 @@ msgstr[0] "Mluvte slušně! Slovo %s zde není přípustné."
msgstr[1] "Mluvte slušně! Slova %s zde nejsou přípustná."
msgstr[2] "Mluvte slušně! Slova %s zde nejsou přípustná."
-#: core/validators.py:236
+#: core/validators.py:263
#, python-format
msgid "This field must match the '%s' field."
msgstr "Toto pole se musí shodovat s polem '%s'."
-#: core/validators.py:255
+#: core/validators.py:282
msgid "Please enter something for at least one field."
msgstr "Prosíme, vložte něco alespoň pro jedno pole."
-#: core/validators.py:264
-#: core/validators.py:275
+#: core/validators.py:291
+#: core/validators.py:302
msgid "Please enter both fields or leave them both empty."
msgstr "Prosíme, vložte obě pole, nebo je nechte obě prázdná."
-#: core/validators.py:282
+#: core/validators.py:309
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
msgstr "Toto pole musí být vyplněno, když %(field)s má %(value)s"
-#: core/validators.py:294
+#: core/validators.py:321
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
msgstr "Toto pole musí být vyplněno, když %(field)s nemá %(value)s"
-#: core/validators.py:313
+#: core/validators.py:340
msgid "Duplicate values are not allowed."
msgstr "Duplikátní hodnoty nejsou povolené."
-#: core/validators.py:336
+#: core/validators.py:363
#, python-format
msgid "This value must be a power of %s."
msgstr "Tato hodnota musí být mocninou %s."
-#: core/validators.py:347
+#: core/validators.py:374
msgid "Please enter a valid decimal number."
msgstr "Prosíme, vložte platné Äíslo."
-#: core/validators.py:349
+#: core/validators.py:378
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural "Please enter a valid decimal number with at most %s total digits."
@@ -1731,7 +1925,15 @@ msgstr[0] "Prosíme, vložte platné Äíslo s nejvíce %s cifrou celkem."
msgstr[1] "Prosíme, vložte platné Äíslo s nejvíce %s ciframi celkem."
msgstr[2] "Prosíme, vložte platné Äíslo s nejvíce %s ciframi celkem."
-#: core/validators.py:352
+#: core/validators.py:381
+#, python-format
+msgid "Please enter a valid decimal number with a whole part of at most %s digit."
+msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits."
+msgstr[0] "Prosíme, vložte platné Äíslo s nejvíce %s cifrou."
+msgstr[1] "Prosíme, vložte platné Äíslo s nejvíce %s ciframi."
+msgstr[2] "Prosíme, vložte platné Äíslo s nejvíce %s ciframi."
+
+#: core/validators.py:384
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural "Please enter a valid decimal number with at most %s decimal places."
@@ -1739,64 +1941,79 @@ msgstr[0] "Prosíme, vložte platné Äíslo s nejvíce %s cifrou za desetinnou
msgstr[1] "Prosíme, vložte platné Äíslo s nejvíce %s ciframi za desetinnou Äárkou celkem."
msgstr[2] "Prosíme, vložte platné Äíslo s nejvíce %s ciframi za desetinnou Äárkou celkem."
-#: core/validators.py:362
+#: core/validators.py:394
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr "Ujistěte se, že posílaný soubor je velký nejméně %s bytů."
-#: core/validators.py:363
+#: core/validators.py:395
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr "Ujistěte se, že posílaný soubor je velký nejvíce %s bytů."
-#: core/validators.py:376
+#: core/validators.py:412
msgid "The format for this field is wrong."
msgstr "Formát pro toto pole je špatný."
-#: core/validators.py:391
+#: core/validators.py:427
msgid "This field is invalid."
msgstr "Toto pole není platné."
-#: core/validators.py:426
+#: core/validators.py:463
#, python-format
msgid "Could not retrieve anything from %s."
msgstr "Nemohl jsem získat nic z %s."
-#: core/validators.py:429
+#: core/validators.py:466
#, python-format
msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr "URL %(url)s vrátilo neplatnou hlaviÄku Content-Type '%(contenttype)s'."
-#: core/validators.py:462
+#: core/validators.py:499
#, python-format
msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)"
msgstr "Prosíme, zavÅ™ete nezavÅ™enou znaÄku %(tag)s z řádky %(line)s. (Řádka zaÄíná s \"%(start)s\".)"
-#: core/validators.py:466
+#: core/validators.py:503
#, python-format
msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)"
msgstr "NÄ›jaký text zaÄínající na řádce %(line)s není povolen v tomto kontextu. (Řádka zaÄíná s \"%(start)s\".)"
-#: core/validators.py:471
+#: core/validators.py:508
#, python-format
msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)"
msgstr "\"%(attr)s\" na řádce %(line)s je neplatný atribut. (Řádka zaÄíná s \"%(start)s\".)"
-#: core/validators.py:476
+#: core/validators.py:513
#, python-format
msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)"
msgstr "\"<%(tag)s>\" na řádce %(line)s je neplatná znaÄka. (Řádka zaÄíná s \"%(start)s\".)"
-#: core/validators.py:480
+#: core/validators.py:517
#, python-format
msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)"
msgstr "ZnaÄce na řádce %(line)s schází jeden nebo více požadovaných atributů. (Řádka zaÄíná s \"%(start)s\".)"
-#: core/validators.py:485
+#: core/validators.py:522
#, python-format
msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)"
msgstr "Atribut \"%(attr)s\" na řádce %(line)s má neplatnou hodnotu. (Řádka zaÄína s \"%(start)s\".)"
+#: views/generic/create_update.py:43
+#, python-format
+msgid "The %(verbose_name)s was created successfully."
+msgstr "Záznam %(verbose_name)s byl úspěšně vytvořen."
+
+#: views/generic/create_update.py:117
+#, python-format
+msgid "The %(verbose_name)s was updated successfully."
+msgstr "Záznam %(verbose_name)s byl úspěšně změnen."
+
+#: views/generic/create_update.py:184
+#, python-format
+msgid "The %(verbose_name)s was deleted."
+msgstr "Záznam %(verbose_name)s byl smazán."
+
#: db/models/manipulators.py:302
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
@@ -1809,42 +2026,42 @@ msgstr "%(optname)s s tímto %(fieldname)s již existuje."
#: db/models/fields/__init__.py:114
#: db/models/fields/__init__.py:265
-#: db/models/fields/__init__.py:542
-#: db/models/fields/__init__.py:553
+#: db/models/fields/__init__.py:551
+#: db/models/fields/__init__.py:562
#: forms/__init__.py:346
msgid "This field is required."
msgstr "Toto pole je povinné."
-#: db/models/fields/__init__.py:337
+#: db/models/fields/__init__.py:340
msgid "This value must be an integer."
msgstr "Tato hodnota musí být celé Äíslo."
-#: db/models/fields/__init__.py:369
+#: db/models/fields/__init__.py:372
msgid "This value must be either True or False."
msgstr "Tato hodnota musí být buÄ Ano (True), nebo Ne (False)."
-#: db/models/fields/__init__.py:385
+#: db/models/fields/__init__.py:388
msgid "This field cannot be null."
msgstr "Toto pole nemůže být prázdné (null)."
-#: db/models/fields/__init__.py:562
+#: db/models/fields/__init__.py:571
msgid "Enter a valid filename."
msgstr "Vložte platný název souboru."
-#: db/models/fields/related.py:43
+#: db/models/fields/related.py:51
#, python-format
msgid "Please enter a valid %s."
msgstr "Prosíme, zadejte %s správně."
-#: db/models/fields/related.py:579
+#: db/models/fields/related.py:618
msgid "Separate multiple IDs with commas."
msgstr "OddÄ›lte více identifikátorů Äárkami."
-#: db/models/fields/related.py:581
+#: db/models/fields/related.py:620
msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr "Podržte \"Control\", nebo \"Command\" na Macu pro vybrání více jak jedné položky."
-#: db/models/fields/related.py:625
+#: db/models/fields/related.py:664
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid."
@@ -1852,7 +2069,7 @@ msgstr[0] "Prosíme, vložte platná %(self)s ID. Hodnota %(value)r není platnÃ
msgstr[1] "Prosíme, vložte platná %(self)s ID. Hodnoty %(value)r nejsou platné."
msgstr[2] "Prosíme, vložte platná %(self)s ID. Hodnoty %(value)r nejsou platné."
-#: forms/__init__.py:380
+#: forms/__init__.py:381
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
@@ -1860,59 +2077,34 @@ msgstr[0] "Ujistěte se, že Váš text má méně než %s znak."
msgstr[1] "Ujistěte se, že Váš text má méně než %s znaky."
msgstr[2] "Ujistěte se, že Váš text má méně než %s znaků."
-#: forms/__init__.py:385
+#: forms/__init__.py:386
msgid "Line breaks are not allowed here."
msgstr "Zalomení řádky zde nenjsou povolená."
-#: forms/__init__.py:480
-#: forms/__init__.py:551
-#: forms/__init__.py:589
+#: forms/__init__.py:487
+#: forms/__init__.py:560
+#: forms/__init__.py:599
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "Vyberte platnou volbu. '%(data)s' není mezi %(choices)s."
-#: forms/__init__.py:645
+#: forms/__init__.py:663
msgid "The submitted file is empty."
msgstr "Odevzdaný soubor je prázdný."
-#: forms/__init__.py:699
+#: forms/__init__.py:719
msgid "Enter a whole number between -32,768 and 32,767."
msgstr "Vložte celé Äíslo mezi -32,768 a 32,767."
-#: forms/__init__.py:708
+#: forms/__init__.py:729
msgid "Enter a positive number."
msgstr "Vložte celé kladné Äíslo."
-#: forms/__init__.py:717
+#: forms/__init__.py:739
msgid "Enter a whole number between 0 and 32,767."
msgstr "Vložte celé Äíslo mezi 0 a 32,767."
-#: template/defaultfilters.py:379
+#: template/defaultfilters.py:401
msgid "yes,no,maybe"
msgstr "ano, ne, možná"
-#~ msgid "Comment"
-#~ msgstr "Komentář"
-#~ msgid "Comments"
-#~ msgstr "Komentáře"
-#~ msgid "String (up to 50)"
-#~ msgstr "Text (max. 50 znaků)"
-#~ msgid "label"
-#~ msgstr "nadpis"
-#~ msgid "package"
-#~ msgstr "balík"
-#~ msgid "packages"
-#~ msgstr "balíky"
-#~ msgid "Error in Template"
-#~ msgstr "Chyba v šabloně"
-#~ msgid ""
-#~ "\n"
-#~ "In template %(name)s, error at line %(line)s:\n"
-#~ msgstr ""
-#~ "\n"
-#~ "V šabloně %(name)s, chyba na řádce %(line)s:\n"
-
-#, fuzzy
-#~ msgid "count"
-#~ msgstr "poÄet"
-
diff --git a/django/conf/locale/da/LC_MESSAGES/django.mo b/django/conf/locale/da/LC_MESSAGES/django.mo
index 668f02cbef..9f86e56407 100644
--- a/django/conf/locale/da/LC_MESSAGES/django.mo
+++ b/django/conf/locale/da/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/da/LC_MESSAGES/django.po b/django/conf/locale/da/LC_MESSAGES/django.po
index 9bf20cf833..7688907694 100644
--- a/django/conf/locale/da/LC_MESSAGES/django.po
+++ b/django/conf/locale/da/LC_MESSAGES/django.po
@@ -1,104 +1,100 @@
-# SOME DESCRIPTIVE TITLE.
+# translation of django.po to Dansk
+# Rune Rønde Laursen <runerl@skjoldhoej.dk>, 2006.
# Copyright (C) 2005 and beyond
# This file is distributed under the same license as the PACKAGE package.
# Morten Bagai <m@bagai.com>, Nov 2005.
-#
-#
+# Rune Rønde Laursen <runerl@skjoldhoej.dk>, Sept 2006.
msgid ""
msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
+"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:12+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: Morten Bagai <m@bagai.com>\n"
-"Language-Team: Danish\n"
+"PO-Revision-Date: 2006-09-24 10:34+0200\n"
+"Last-Translator: Rune Rønde Laursen <runerl@skjoldhoej.dk>\n"
+"Language-Team: Dansk <dansk@klid.dk>\n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
#: contrib/comments/models.py:67 contrib/comments/models.py:166
-#, fuzzy
msgid "object ID"
-msgstr "objekt id"
+msgstr "objekt ID"
#: contrib/comments/models.py:68
msgid "headline"
-msgstr ""
+msgstr "overskrift"
#: contrib/comments/models.py:69 contrib/comments/models.py:90
#: contrib/comments/models.py:167
-#, fuzzy
msgid "comment"
-msgstr "indhold"
+msgstr "kommentar"
#: contrib/comments/models.py:70
msgid "rating #1"
-msgstr ""
+msgstr "rangering # 1"
#: contrib/comments/models.py:71
msgid "rating #2"
-msgstr ""
+msgstr "rangering # 2"
#: contrib/comments/models.py:72
msgid "rating #3"
-msgstr ""
+msgstr "rangering # 3"
#: contrib/comments/models.py:73
msgid "rating #4"
-msgstr ""
+msgstr "rangering # 4"
#: contrib/comments/models.py:74
msgid "rating #5"
-msgstr ""
+msgstr "rangering # 5"
#: contrib/comments/models.py:75
msgid "rating #6"
-msgstr ""
+msgstr "rangering # 6"
#: contrib/comments/models.py:76
msgid "rating #7"
-msgstr ""
+msgstr "rangering # 7"
#: contrib/comments/models.py:77
msgid "rating #8"
-msgstr ""
+msgstr "rangering # 8"
#: contrib/comments/models.py:82
msgid "is valid rating"
-msgstr ""
+msgstr "er gyldig rangering"
#: contrib/comments/models.py:83 contrib/comments/models.py:169
msgid "date/time submitted"
-msgstr ""
+msgstr "dato/tidspunkt oprettet"
#: contrib/comments/models.py:84 contrib/comments/models.py:170
msgid "is public"
-msgstr ""
+msgstr "er offentlig"
#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
-#, fuzzy
msgid "IP address"
-msgstr "e-mail adresse"
+msgstr "IP-adresse"
#: contrib/comments/models.py:86
msgid "is removed"
-msgstr ""
+msgstr "er fjernet"
#: contrib/comments/models.py:86
msgid ""
"Check this box if the comment is inappropriate. A \"This comment has been "
"removed\" message will be displayed instead."
-msgstr ""
+msgstr "Afkryds denne boks hvis kommentaren er upassende. Beskeden \"Denne kommentar er blevet fjernet\" vil blive vist istedet."
#: contrib/comments/models.py:91
-#, fuzzy
msgid "comments"
-msgstr "indhold"
+msgstr "kommentarer"
#: contrib/comments/models.py:131 contrib/comments/models.py:207
-#, fuzzy
msgid "Content object"
-msgstr "indholdstype"
+msgstr "Indholdsobjekt"
#: contrib/comments/models.py:159
#, python-format
@@ -109,52 +105,52 @@ msgid ""
"\n"
"http://%(domain)s%(url)s"
msgstr ""
+"Indsendt af %(user)s den %(date)s\n"
+"\n"
+"%(comment)s\n"
+"\n"
+"http://%(domain)s%(url)s"
#: contrib/comments/models.py:168
-#, fuzzy
msgid "person's name"
-msgstr "fornavn"
+msgstr "personens navn"
#: contrib/comments/models.py:171
-#, fuzzy
msgid "ip address"
-msgstr "e-mail adresse"
+msgstr "IP-adresse"
#: contrib/comments/models.py:173
msgid "approved by staff"
-msgstr ""
+msgstr "godkendt af personale"
#: contrib/comments/models.py:176
-#, fuzzy
msgid "free comment"
-msgstr "tillad kommentarer"
+msgstr "fri kommentar"
#: contrib/comments/models.py:177
-#, fuzzy
msgid "free comments"
-msgstr "tillad kommentarer"
+msgstr "frie kommentarer"
#: contrib/comments/models.py:233
msgid "score"
-msgstr ""
+msgstr "score"
#: contrib/comments/models.py:234
-#, fuzzy
msgid "score date"
-msgstr "udløbsdato"
+msgstr "scoringsdato"
#: contrib/comments/models.py:237
msgid "karma score"
-msgstr ""
+msgstr "karma score"
#: contrib/comments/models.py:238
msgid "karma scores"
-msgstr ""
+msgstr "karma score"
#: contrib/comments/models.py:242
#, python-format
msgid "%(score)d rating by %(user)s"
-msgstr ""
+msgstr "%(score)d rangering efter %(user)s"
#: contrib/comments/models.py:258
#, python-format
@@ -163,62 +159,59 @@ msgid ""
"\n"
"%(text)s"
msgstr ""
+"Denne kommentar blev markeret af %(user)s:\n"
+"\n"
+"%(text)s"
#: contrib/comments/models.py:265
-#, fuzzy
msgid "flag date"
-msgstr "flad side"
+msgstr "mærkedato"
#: contrib/comments/models.py:268
-#, fuzzy
msgid "user flag"
-msgstr "Bruger"
+msgstr "bruger-mærke"
#: contrib/comments/models.py:269
-#, fuzzy
msgid "user flags"
-msgstr "Brugere"
+msgstr "bruger-mærker"
#: contrib/comments/models.py:273
#, python-format
msgid "Flag by %r"
-msgstr ""
+msgstr "Mærket af %r"
#: contrib/comments/models.py:278
-#, fuzzy
msgid "deletion date"
-msgstr "sessionsdata"
+msgstr "sletningsdato"
#: contrib/comments/models.py:280
msgid "moderator deletion"
-msgstr ""
+msgstr "moderator-sletning"
#: contrib/comments/models.py:281
msgid "moderator deletions"
-msgstr ""
+msgstr "moderator-sletninger"
#: contrib/comments/models.py:285
#, python-format
msgid "Moderator deletion by %r"
-msgstr ""
+msgstr "Moderator-sletning af %r"
#: contrib/comments/views/karma.py:19
msgid "Anonymous users cannot vote"
-msgstr ""
+msgstr "Anonyme brugere kan ikke stemme"
#: contrib/comments/views/karma.py:23
-#, fuzzy
msgid "Invalid comment ID"
-msgstr "tillad kommentarer"
+msgstr "Ugyldigt kommentar-ID"
#: contrib/comments/views/karma.py:25
msgid "No voting for yourself"
-msgstr ""
+msgstr "Du kan ikke selv stemme"
#: contrib/comments/views/comments.py:28
-msgid ""
-"This rating is required because you've entered at least one other rating."
-msgstr ""
+msgid "This rating is required because you've entered at least one other rating."
+msgstr "Denne rangering er påkrævet fordi du har indtastet mindst en anden rangering."
#: contrib/comments/views/comments.py:112
#, python-format
@@ -233,7 +226,13 @@ msgid_plural ""
"\n"
"%(text)s"
msgstr[0] ""
+"Denne kommentar blev indsendt af en bruger som har indsendt færre end %(count)s kommentar:\n"
+"\n"
+"%(text)s"
msgstr[1] ""
+"Denne kommentar blev indsendt af en bruger som har indsendt færre end %(count)s kommentarer:\n"
+"\n"
+"%(text)s"
#: contrib/comments/views/comments.py:117
#, python-format
@@ -242,33 +241,36 @@ msgid ""
"\n"
"%(text)s"
msgstr ""
+"Denne kommentar blev indsendt af en overfladisk bruger:\n"
+"\n"
+"%(text)s"
#: contrib/comments/views/comments.py:189
#: contrib/comments/views/comments.py:280
msgid "Only POSTs are allowed"
-msgstr ""
+msgstr "Kun POST er tilladt"
#: contrib/comments/views/comments.py:193
#: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted"
-msgstr ""
+msgstr "En eller flere af de påkrævede felter blev ikke indsendt"
#: contrib/comments/views/comments.py:197
#: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)"
-msgstr ""
+msgstr "Nogen har misbrugt kommentarformularen (sikkerhedsovertrædelse)"
#: contrib/comments/views/comments.py:207
#: contrib/comments/views/comments.py:292
msgid ""
"The comment form had an invalid 'target' parameter -- the object ID was "
"invalid"
-msgstr ""
+msgstr "Kommentarformularen havde en ugyldigt 'target'-parameter -- objekt-ID'var ugyldigt"
#: contrib/comments/views/comments.py:257
#: contrib/comments/views/comments.py:321
msgid "The comment form didn't provide either 'preview' or 'post'"
-msgstr ""
+msgstr "Kommentarformularen tilbød ikke hverken 'forhåndsvis' eller 'indsend'"
#: contrib/comments/templates/comments/form.html:6
#: contrib/comments/templates/comments/form.html:8
@@ -282,9 +284,8 @@ msgid "Password:"
msgstr "Adgangskode:"
#: contrib/comments/templates/comments/form.html:6
-#, fuzzy
msgid "Forgotten your password?"
-msgstr "Ændre adgangskode"
+msgstr "Har du glemt dit kodeord?"
#: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3
@@ -309,38 +310,35 @@ msgstr "Log ud"
#: contrib/comments/templates/comments/form.html:12
msgid "Ratings"
-msgstr ""
+msgstr "Rangeringer"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Required"
-msgstr ""
+msgstr "Påkrævet"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Optional"
-msgstr ""
+msgstr "Valgfri"
#: contrib/comments/templates/comments/form.html:23
msgid "Post a photo"
-msgstr ""
+msgstr "Indsend et foto"
#: contrib/comments/templates/comments/form.html:27
#: contrib/comments/templates/comments/freeform.html:5
-#, fuzzy
msgid "Comment:"
-msgstr "tillad kommentarer"
+msgstr "Kommentar:"
#: contrib/comments/templates/comments/form.html:32
#: contrib/comments/templates/comments/freeform.html:9
-#, fuzzy
msgid "Preview comment"
-msgstr "tillad kommentarer"
+msgstr "Forhåndsvis kommentar"
#: contrib/comments/templates/comments/freeform.html:4
-#, fuzzy
msgid "Your name:"
-msgstr "brugernavn"
+msgstr "Dit navn:"
#: contrib/admin/filterspecs.py:40
#, python-format
@@ -348,45 +346,45 @@ msgid ""
"<h3>By %s:</h3>\n"
"<ul>\n"
msgstr ""
+"<h3>Af %s:</h3>\n"
+"<ul>\n"
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
#: contrib/admin/filterspecs.py:143
msgid "All"
-msgstr ""
+msgstr "Alle"
#: contrib/admin/filterspecs.py:109
msgid "Any date"
-msgstr ""
+msgstr "NÃ¥r som helst"
#: contrib/admin/filterspecs.py:110
-#, fuzzy
msgid "Today"
-msgstr "Mandag"
+msgstr "Idag"
#: contrib/admin/filterspecs.py:113
msgid "Past 7 days"
-msgstr ""
+msgstr "De sidste 7 dage"
#: contrib/admin/filterspecs.py:115
msgid "This month"
-msgstr ""
+msgstr "Denne måned"
#: contrib/admin/filterspecs.py:117
msgid "This year"
-msgstr ""
+msgstr "Dette år"
#: contrib/admin/filterspecs.py:143
msgid "Yes"
-msgstr ""
+msgstr "Ja"
#: contrib/admin/filterspecs.py:143
-#, fuzzy
msgid "No"
-msgstr "Nov."
+msgstr "Nej"
#: contrib/admin/filterspecs.py:150
msgid "Unknown"
-msgstr ""
+msgstr "Ukendt"
#: contrib/admin/models.py:16
msgid "action time"
@@ -394,7 +392,7 @@ msgstr "handlingstid"
#: contrib/admin/models.py:19
msgid "object id"
-msgstr "objekt id"
+msgstr "objekt-ID"
#: contrib/admin/models.py:20
msgid "object repr"
@@ -418,14 +416,14 @@ msgstr "logmeddelelser"
#: contrib/admin/templatetags/admin_list.py:228
msgid "All dates"
-msgstr ""
+msgstr "Alle datoer"
#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
#: contrib/auth/forms.py:41
msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
-msgstr ""
+msgstr "Indtast venligst et korrekt brugernavn og kodeord. Læg mærke til at begge felter er versalfølsomme."
#: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25
@@ -436,196 +434,189 @@ msgstr "Log ind"
msgid ""
"Please log in again, because your session has expired. Don't worry: Your "
"submission has been saved."
-msgstr ""
+msgstr "Log venligst ind igen, da din session er udløbet. Der er ingen grund til bekymring, informationen du indsendte er blevet gemt."
#: contrib/admin/views/decorators.py:68
msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
-msgstr ""
+msgstr "Det ser ud til din browser ikke er indstillet til at acceptere cookier. Slå venligst cookier til, genindlæs denne side og prøv igen."
#: contrib/admin/views/decorators.py:82
msgid "Usernames cannot contain the '@' character."
-msgstr ""
+msgstr "Brugernavne kan ikke indeholde tegnet '@'."
#: contrib/admin/views/decorators.py:84
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
-msgstr ""
+msgstr "Din e-mail-adresse er ikke dit brugernavn. Prøv '%s' i stedet."
#: contrib/admin/views/main.py:226
-#, fuzzy
msgid "Site administration"
-msgstr "Django administration"
+msgstr "Website-administration"
#: contrib/admin/views/main.py:260
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
-msgstr ""
+msgstr "%(name)s \"%(obj)s\" blev tilføjet i databasen."
#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
msgid "You may edit it again below."
-msgstr ""
+msgstr "Du kan redigere det igen herunder."
#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
#, python-format
msgid "You may add another %s below."
-msgstr ""
+msgstr "Du kan tilføje endnu en %s herunder."
#: contrib/admin/views/main.py:290
-#, fuzzy, python-format
+#, python-format
msgid "Add %s"
-msgstr "Tilføj"
+msgstr "Tilføj %s"
#: contrib/admin/views/main.py:336
#, python-format
msgid "Added %s."
-msgstr ""
+msgstr "Tilføjede %s."
#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
#: contrib/admin/views/main.py:340
msgid "and"
-msgstr ""
+msgstr "og"
#: contrib/admin/views/main.py:338
-#, fuzzy, python-format
+#, python-format
msgid "Changed %s."
-msgstr "Ændre"
+msgstr "Ændrede %s."
#: contrib/admin/views/main.py:340
#, python-format
msgid "Deleted %s."
-msgstr ""
+msgstr "Slettede %s."
#: contrib/admin/views/main.py:343
msgid "No fields changed."
-msgstr ""
+msgstr "Ingen filer ændret."
#: contrib/admin/views/main.py:346
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
-msgstr ""
+msgstr "%(name)s \"%(obj)s\" blev ændret."
#: contrib/admin/views/main.py:354
#, python-format
-msgid ""
-"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
-msgstr ""
+msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
+msgstr "%(name)s \"%(obj)s\" blev tilføjet. Du kan redigere det igen herunder."
#: contrib/admin/views/main.py:392
-#, fuzzy, python-format
+#, python-format
msgid "Change %s"
-msgstr "Ændre"
+msgstr "Ændr %s"
#: contrib/admin/views/main.py:470
#, python-format
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
-msgstr ""
+msgstr "Et eller flere %(fieldname)s i %(name)s: %(obj)s"
#: contrib/admin/views/main.py:475
#, python-format
msgid "One or more %(fieldname)s in %(name)s:"
-msgstr ""
+msgstr "Et eller flere %(fieldname)s i %(name)s:"
#: contrib/admin/views/main.py:508
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
-msgstr ""
+msgstr "%(name)s \"%(obj)s\" blev slettet."
#: contrib/admin/views/main.py:511
msgid "Are you sure?"
-msgstr ""
+msgstr "Er du sikker?"
#: contrib/admin/views/main.py:533
-#, fuzzy, python-format
+#, python-format
msgid "Change history: %s"
-msgstr "Ændre adgangskode"
+msgstr "Ændringshistorik: %s"
#: contrib/admin/views/main.py:565
#, python-format
msgid "Select %s"
-msgstr ""
+msgstr "Vælg %s"
#: contrib/admin/views/main.py:565
#, python-format
msgid "Select %s to change"
-msgstr ""
+msgstr "Vælg %s for at ændre"
#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
msgid "Integer"
-msgstr ""
+msgstr "Heltal"
#: contrib/admin/views/doc.py:278
msgid "Boolean (Either True or False)"
-msgstr ""
+msgstr "Boolsk (enten \"true\" eller \"false\")"
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
#, python-format
msgid "String (up to %(maxlength)s)"
-msgstr ""
+msgstr "Tekst (op til %(maxlength)s)"
#: contrib/admin/views/doc.py:280
msgid "Comma-separated integers"
-msgstr ""
+msgstr "Kommaadskilte heltal"
#: contrib/admin/views/doc.py:281
-#, fuzzy
msgid "Date (without time)"
-msgstr "handlingstid"
+msgstr "Dato (uden tid)"
#: contrib/admin/views/doc.py:282
-#, fuzzy
msgid "Date (with time)"
-msgstr "Dato/tid"
+msgstr "Dato (med tid)"
#: contrib/admin/views/doc.py:283
-#, fuzzy
msgid "E-mail address"
-msgstr "E-mail adresse:"
+msgstr "E-mail-adresse"
#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
msgid "File path"
-msgstr ""
+msgstr "Filsti"
#: contrib/admin/views/doc.py:285
-#, fuzzy
msgid "Decimal number"
-msgstr "December"
+msgstr "Decimaltal"
#: contrib/admin/views/doc.py:291
msgid "Boolean (Either True, False or None)"
-msgstr ""
+msgstr "Boolsk (enten \"true\", \"false\", eller \"none\")"
#: contrib/admin/views/doc.py:292
msgid "Relation to parent model"
-msgstr ""
+msgstr "Relation-til-forælder-model"
#: contrib/admin/views/doc.py:293
-#, fuzzy
msgid "Phone number"
-msgstr "Indtast et heltal."
+msgstr "Telefonnummer"
#: contrib/admin/views/doc.py:298
msgid "Text"
-msgstr ""
+msgstr "Tekst"
#: contrib/admin/views/doc.py:299
msgid "Time"
-msgstr ""
+msgstr "Tid"
#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
msgid "URL"
-msgstr "Internetadresse"
+msgstr "URL"
#: contrib/admin/views/doc.py:301
msgid "U.S. state (two uppercase letters)"
-msgstr ""
+msgstr "Stat (i USA, to store bogstaver)"
#: contrib/admin/views/doc.py:302
msgid "XML text"
-msgstr ""
+msgstr "XML tekst"
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
@@ -636,7 +627,7 @@ msgstr ""
#: contrib/admin/templates/registration/password_change_form.html:3
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
msgid "Documentation"
-msgstr ""
+msgstr "Dokumentation"
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
@@ -704,7 +695,7 @@ msgstr ""
#: contrib/admin/templates/admin/base_site.html:4
msgid "Django site admin"
-msgstr "Django site administration"
+msgstr "Django website-administration"
#: contrib/admin/templates/admin/base_site.html:7
msgid "Django administration"
@@ -726,9 +717,7 @@ msgstr "Serverfejl <em>(500)</em>"
msgid ""
"There's been an error. It's been reported to the site administrators via e-"
"mail and should be fixed shortly. Thanks for your patience."
-msgstr ""
-"Der opstod en fejl. Fejlen er rapporteret til site-administratoren via e-"
-"mail, og vil blive rettet hurtigst muligt. Tak for din tålmodighed."
+msgstr "Der opstod en fejl. Fejlen er rapporteret til website-administratoren via e-mail, og vil blive rettet hurtigst muligt. Tak for din tålmodighed."
#: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8
@@ -737,12 +726,12 @@ msgstr "Siden blev ikke fundet"
#: contrib/admin/templates/admin/404.html:10
msgid "We're sorry, but the requested page could not be found."
-msgstr "Vi Beklager, men den ønskede side kunne ikke findes"
+msgstr "Vi beklager, men den ønskede side kunne ikke findes"
#: contrib/admin/templates/admin/index.html:17
#, python-format
msgid "Models available in the %(name)s application."
-msgstr ""
+msgstr "Modeller til rådighed i %(name)s applikationen."
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
@@ -751,11 +740,11 @@ msgstr "Tilføj"
#: contrib/admin/templates/admin/index.html:34
msgid "Change"
-msgstr "Ændre"
+msgstr "Ændr"
#: contrib/admin/templates/admin/index.html:44
msgid "You don't have permission to edit anything."
-msgstr "Du har ikke rettigehed til at foretage ændringer"
+msgstr "Du har ikke rettigheder til at foretage ændringer."
#: contrib/admin/templates/admin/index.html:52
msgid "Recent Actions"
@@ -772,7 +761,7 @@ msgstr "Ingen tilgængelige"
#: contrib/admin/templates/admin/change_list.html:11
#, python-format
msgid "Add %(name)s"
-msgstr ""
+msgstr "Tilføj %(name)s"
#: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
@@ -780,12 +769,12 @@ msgstr "Har du <a href=\"/password_reset/\">glemt din adgangskode</a>?"
#: contrib/admin/templates/admin/base.html:23
msgid "Welcome,"
-msgstr "Velkommen"
+msgstr "Velkommen,"
#: contrib/admin/templates/admin/delete_confirmation.html:9
#: contrib/admin/templates/admin/submit_line.html:3
msgid "Delete"
-msgstr ""
+msgstr "Slet"
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
@@ -795,16 +784,14 @@ msgid ""
"types of objects:"
msgstr ""
"Hvis du sletter %(object_name)s '%(object)s' vil du også slette relaterede "
-"objekter, men du har ikke rettigheder til at slette flg. typer objekter:"
+"objekter, men du har ikke rettigheder til at slette følgende objekttyper:"
#: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format
msgid ""
"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
"the following related items will be deleted:"
-msgstr ""
-"Er du sikker på at du vil slette %(object_name) \"%(object)s\"? Alle de "
-"følgende relaterede objekter vil blive slettet:"
+msgstr "Er du sikker på du vil slette %(object_name)s \"%(object)s\"? Alle følgende relaterede objekter vil blive slettet:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure"
@@ -813,62 +800,61 @@ msgstr "Ja, jeg er sikker"
#: contrib/admin/templates/admin/filter.html:2
#, python-format
msgid " By %(title)s "
-msgstr ""
+msgstr " Efter %(title)s "
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
-msgstr ""
+msgstr "Kør"
#: contrib/admin/templates/admin/change_form.html:21
msgid "View on site"
-msgstr ""
+msgstr "Se på website"
#: contrib/admin/templates/admin/change_form.html:30
msgid "Please correct the error below."
msgid_plural "Please correct the errors below."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ret venligst fejlen herunder."
+msgstr[1] "Ret venligst fejlene herunder."
#: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering"
-msgstr ""
+msgstr "Rækkefølge"
#: contrib/admin/templates/admin/change_form.html:51
msgid "Order:"
-msgstr ""
+msgstr "Rækkefølge:"
#: contrib/admin/templates/admin/submit_line.html:4
msgid "Save as new"
-msgstr ""
+msgstr "Gem som ny"
#: contrib/admin/templates/admin/submit_line.html:5
msgid "Save and add another"
-msgstr ""
+msgstr "Gem og tilføj endnu en"
#: contrib/admin/templates/admin/submit_line.html:6
msgid "Save and continue editing"
-msgstr ""
+msgstr "Gem og fortsæt med at redigere"
#: contrib/admin/templates/admin/submit_line.html:7
-#, fuzzy
msgid "Save"
-msgstr "aktiv"
+msgstr "Gem"
#: contrib/admin/templates/registration/password_change_done.html:4
#: contrib/admin/templates/registration/password_change_form.html:4
#: contrib/admin/templates/registration/password_change_form.html:6
#: contrib/admin/templates/registration/password_change_form.html:10
msgid "Password change"
-msgstr "Ændre passord"
+msgstr "Ændr adgangskode"
#: contrib/admin/templates/registration/password_change_done.html:6
#: contrib/admin/templates/registration/password_change_done.html:10
msgid "Password change successful"
-msgstr "Adgangskoden er ændret"
+msgstr "Adgangskoden blev ændret"
#: contrib/admin/templates/registration/password_change_done.html:12
msgid "Your password was changed."
-msgstr "Din adgangskode er ændret"
+msgstr "Din adgangskode blev ændret."
#: contrib/admin/templates/registration/password_reset_form.html:4
#: contrib/admin/templates/registration/password_reset_form.html:6
@@ -881,13 +867,11 @@ msgstr "Nulstil adgangskode"
msgid ""
"Forgotten your password? Enter your e-mail address below, and we'll reset "
"your password and e-mail the new one to you."
-msgstr ""
-"Har din adgangskode? Indtast din email-adresse nedenfor, så sender vi dig en "
-"ny kode via e-mail"
+msgstr "Har du glemt din adgangskode? Indtast din e-mail-adresse herunder, så sender vi dig en ny adgangskode."
#: contrib/admin/templates/registration/password_reset_form.html:16
msgid "E-mail address:"
-msgstr "E-mail adresse:"
+msgstr "E-mail-adresse:"
#: contrib/admin/templates/registration/password_reset_form.html:16
msgid "Reset my password"
@@ -895,7 +879,7 @@ msgstr "Nulstil min adgangskode"
#: contrib/admin/templates/registration/logged_out.html:8
msgid "Thanks for spending some quality time with the Web site today."
-msgstr "Tak for den tid du brugte på sitet idag"
+msgstr "Tak for den kvalitetstid du brugte på websitet idag."
#: contrib/admin/templates/registration/logged_out.html:10
msgid "Log in again"
@@ -910,18 +894,16 @@ msgstr "Adgangskoden blev nulstillet"
msgid ""
"We've e-mailed a new password to the e-mail address you submitted. You "
"should be receiving it shortly."
-msgstr ""
-"Vi har e-mailet en ny adgangskode til dig. Du skulle modtage den om ganske "
-"kort tid."
+msgstr "Vi har sendt en ny adgangskode til din e-mail-adresse. Du skulle modtage den om ganske kort tid."
#: contrib/admin/templates/registration/password_change_form.html:12
msgid ""
"Please enter your old password, for security's sake, and then enter your new "
"password twice so we can verify you typed it in correctly."
msgstr ""
-"Indtast venligst din gamle adgangskode af sikkerhedsgrunde, og indtast så "
-"dit nye password to gange, så vi kan være sikre på, at det er indtastet "
-"korrekt"
+"Indtast venligst din gamle adgangskode, for en sikkerheds skyld og indtast så "
+"din nye adgangskode to gange, så vi kan være sikre på, at den er indtastet "
+"korrekt."
#: contrib/admin/templates/registration/password_change_form.html:17
msgid "Old password:"
@@ -937,17 +919,16 @@ msgstr "Bekræft ny adgangskode:"
#: contrib/admin/templates/registration/password_change_form.html:23
msgid "Change my password"
-msgstr "Ændre adgangskode"
+msgstr "Ændr min adgangskode"
#: contrib/admin/templates/registration/password_reset_email.html:2
msgid "You're receiving this e-mail because you requested a password reset"
-msgstr ""
-"Du modtager denne e-mail, fordi du har bedt om at få nulstillet dit password"
+msgstr "Du modtager denne e-mail, fordi du har bedt om at få nulstillet din adgangskode"
#: contrib/admin/templates/registration/password_reset_email.html:3
#, python-format
msgid "for your user account at %(site_name)s"
-msgstr "for din konto hos %(site_name)s"
+msgstr "til din brugerkonto ved %(site_name)s"
#: contrib/admin/templates/registration/password_reset_email.html:5
#, python-format
@@ -956,15 +937,15 @@ msgstr "Din nye adgangskode er: %(new_password)s"
#: contrib/admin/templates/registration/password_reset_email.html:7
msgid "Feel free to change this password by going to this page:"
-msgstr "Du kan ændre din adgangskode ved at gå til denne side"
+msgstr "Du kan ændre din adgangskode ved at gå til denne side:"
#: contrib/admin/templates/registration/password_reset_email.html:11
msgid "Your username, in case you've forgotten:"
-msgstr "I det tilfælde, at du har glemt dit brugernavn er det:"
+msgstr "I det tilfælde at du har glemt dit brugernavn er det:"
#: contrib/admin/templates/registration/password_reset_email.html:13
msgid "Thanks for using our site!"
-msgstr "Tak, fordi du brugte vores site!"
+msgstr "Tak fordi du brugte vores website!"
#: contrib/admin/templates/registration/password_reset_email.html:15
#, python-format
@@ -973,11 +954,11 @@ msgstr "Med venlig hilsen %(site_name)s"
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
msgid "Bookmarklets"
-msgstr ""
+msgstr "Bookmarklets"
#: contrib/admin/templates/admin_doc/bookmarklets.html:5
msgid "Documentation bookmarklets"
-msgstr ""
+msgstr "Documentation bookmarklets"
#: contrib/admin/templates/admin_doc/bookmarklets.html:9
msgid ""
@@ -989,60 +970,64 @@ msgid ""
"as \"internal\" (talk to your system administrator if you aren't sure if\n"
"your computer is \"internal\").</p>\n"
msgstr ""
+"\n"
+"<p class=\"help\">For at installere bookmarklets, træk linket til din bogmærkelinje\n, eller højreklik på linket og tilføj det til dine bogmærker. Du kan nu\n"
+"markere bookmarkletten fra enhver side på websitet. Bid mærke i at nogle af disse \n"
+"bookmarkletter kræver at du ser på websitet fra en computer der opfattes \n"
+"som \"intern\" (tal med din systemadministrator, hvis du ikke er sikker på om\n"
+"din computer er \"intern\").</p>\n"
#: contrib/admin/templates/admin_doc/bookmarklets.html:19
msgid "Documentation for this page"
-msgstr ""
+msgstr "Dokumentation for denne side"
#: contrib/admin/templates/admin_doc/bookmarklets.html:20
msgid ""
"Jumps you from any page to the documentation for the view that generates "
"that page."
-msgstr ""
+msgstr "Bringer dig fra en hvilken som helst side til dokumentationen for det view der genererer den pågældende side."
#: contrib/admin/templates/admin_doc/bookmarklets.html:22
-#, fuzzy
msgid "Show object ID"
-msgstr "objekt id"
+msgstr "Vis objekt-ID"
#: contrib/admin/templates/admin_doc/bookmarklets.html:23
msgid ""
"Shows the content-type and unique ID for pages that represent a single "
"object."
-msgstr ""
+msgstr "Viser indholdstypen og unikt ID for sider der repræsenterer et enkelt objekt."
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
msgid "Edit this object (current window)"
-msgstr ""
+msgstr "Redigér dette objekt (i det aktuelle vindue)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
msgid "Jumps to the admin page for pages that represent a single object."
-msgstr ""
+msgstr "Springer til administrationssiden for sider der repræsenterer et enkelt objekt."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)"
-msgstr ""
+msgstr "Redigér dette objekt (i nyt vindue)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:29
msgid "As above, but opens the admin page in a new window."
-msgstr ""
+msgstr "Som ovenfor, men åbner administrationssiden i et nyt vindue."
#: contrib/admin/templates/widget/date_time.html:3
msgid "Date:"
-msgstr ""
+msgstr "Dato:"
#: contrib/admin/templates/widget/date_time.html:4
msgid "Time:"
-msgstr ""
+msgstr "Tid:"
#: contrib/admin/templates/widget/file.html:2
msgid "Currently:"
-msgstr ""
+msgstr "Nuværende:"
#: contrib/admin/templates/widget/file.html:3
-#, fuzzy
msgid "Change:"
-msgstr "Ændre"
+msgstr "Ændr:"
#: contrib/redirects/models.py:7
msgid "redirect from"
@@ -1054,7 +1039,7 @@ msgid ""
"events/search/'."
msgstr ""
"Dette skal være en absolut sti uden domænenavnet. For eksempel: '/nyheder/"
-"find/"
+"søg/"
#: contrib/redirects/models.py:9
msgid "redirect to"
@@ -1065,7 +1050,7 @@ msgid ""
"This can be either an absolute path (as above) or a full URL starting with "
"'http://'."
msgstr ""
-"Dette kan enten være en absolut sti (som over), eller en komplet URL "
+"Dette kan enten være en absolut sti (som ovenfor), eller en komplet URL "
"startende med 'http://'"
#: contrib/redirects/models.py:12
@@ -1077,11 +1062,8 @@ msgid "redirects"
msgstr "omaddresseringer"
#: contrib/flatpages/models.py:8
-msgid ""
-"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
-msgstr ""
-"Eksempel: '/om/kontakt/'. Vær sikker på at du har en skråstreg foran og og "
-"bagefter."
+msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes."
+msgstr "Eksempel: '/om/kontakt/'. Vær sikker på at du har en skråstreg foran og bagved."
#: contrib/flatpages/models.py:9
msgid "title"
@@ -1100,22 +1082,19 @@ msgid "template name"
msgstr "skabelonnavn"
#: contrib/flatpages/models.py:13
-#, fuzzy
msgid ""
"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
"use 'flatpages/default'."
-msgstr ""
-"Eksempel: 'fladesider/kontakt_side'. Vist denne ikke denne er gitt, vill "
-"'flatfiles/default' bli brukt."
+msgstr "Eksempel: 'fladesider/kontakt_side'. Hvis dette ikke tilbydes, bruger systemet 'fladesider/default'."
#: contrib/flatpages/models.py:14
msgid "registration required"
-msgstr "registrering kreves"
+msgstr "registrering påkrævet"
#: contrib/flatpages/models.py:14
msgid "If this is checked, only logged-in users will be able to view the page."
msgstr ""
-"Hvis denne box er krydset af, vil kun brugere, der er logget ind, kunne se "
+"Hvis denne boks er markeret, vil kun brugere der er logget ind, kunne se "
"siden."
#: contrib/flatpages/models.py:18
@@ -1135,24 +1114,20 @@ msgid "codename"
msgstr "kodenavn"
#: contrib/auth/models.py:17
-#, fuzzy
msgid "permission"
-msgstr "Rettighed"
+msgstr "rettighed"
#: contrib/auth/models.py:18 contrib/auth/models.py:27
-#, fuzzy
msgid "permissions"
-msgstr "Rettigheder"
+msgstr "rettigheder"
#: contrib/auth/models.py:29
-#, fuzzy
msgid "group"
-msgstr "Gruppe"
+msgstr "gruppe"
#: contrib/auth/models.py:30 contrib/auth/models.py:65
-#, fuzzy
msgid "groups"
-msgstr "Grupper"
+msgstr "grupper"
#: contrib/auth/models.py:55
msgid "username"
@@ -1168,7 +1143,7 @@ msgstr "efternavn"
#: contrib/auth/models.py:58
msgid "e-mail address"
-msgstr "e-mail adresse"
+msgstr "e-mail-adresse"
#: contrib/auth/models.py:59
msgid "password"
@@ -1176,7 +1151,7 @@ msgstr "adgangskode"
#: contrib/auth/models.py:59
msgid "Use '[algo]$[salt]$[hexdigest]'"
-msgstr ""
+msgstr "Brug '[algo]$[salt]$[hexdigest]'"
#: contrib/auth/models.py:60
msgid "staff status"
@@ -1184,7 +1159,7 @@ msgstr "administrationsstatus"
#: contrib/auth/models.py:60
msgid "Designates whether the user can log into this admin site."
-msgstr "Bestemmer om brugeren kan logge ind på dette administrationssite"
+msgstr "Bestemmer om brugeren kan logge ind på dette administrationswebsite."
#: contrib/auth/models.py:61
msgid "active"
@@ -1192,7 +1167,7 @@ msgstr "aktiv"
#: contrib/auth/models.py:62
msgid "superuser status"
-msgstr "superbruger"
+msgstr "superbrugerstatus"
#: contrib/auth/models.py:63
msgid "last login"
@@ -1207,23 +1182,20 @@ msgid ""
"In addition to the permissions manually assigned, this user will also get "
"all permissions granted to each group he/she is in."
msgstr ""
-"I tillæg til de rettighder, som manuelt er tildelt brugeren, vil denne også "
-"få alle rettigheder tildelt hver gruppe han/hun er medlem af"
+"Udover de rettigheder, der manuelt er tildelt brugeren, vil denne også "
+"få alle rettigheder der er tildelt hver gruppe, brugeren er medlem af."
#: contrib/auth/models.py:67
-#, fuzzy
msgid "user permissions"
-msgstr "Rettigheder"
+msgstr "brugerrettigheder"
#: contrib/auth/models.py:70
-#, fuzzy
msgid "user"
-msgstr "Bruger"
+msgstr "bruger"
#: contrib/auth/models.py:71
-#, fuzzy
msgid "users"
-msgstr "Brugere"
+msgstr "brugere"
#: contrib/auth/models.py:76
msgid "Personal info"
@@ -1242,20 +1214,18 @@ msgid "Groups"
msgstr "Grupper"
#: contrib/auth/models.py:219
-#, fuzzy
msgid "message"
-msgstr "Meddelelse"
+msgstr "meddelelse"
#: contrib/auth/forms.py:30
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in."
-msgstr ""
+msgstr "Din browser ser ud til ikke at have cookier aktiveret. Cookier er påkrævet for at kunne logge ind."
#: contrib/contenttypes/models.py:25
-#, fuzzy
msgid "python model class name"
-msgstr "python modulnavn"
+msgstr "python model klassenavn"
#: contrib/contenttypes/models.py:28
msgid "content type"
@@ -1295,11 +1265,11 @@ msgstr "vist navn"
#: contrib/sites/models.py:15
msgid "site"
-msgstr "side"
+msgstr "website"
#: contrib/sites/models.py:16
msgid "sites"
-msgstr "sider"
+msgstr "websites"
#: utils/translation.py:360
msgid "DATE_FORMAT"
@@ -1391,52 +1361,51 @@ msgstr "December"
#: utils/dates.py:19
msgid "jan"
-msgstr ""
+msgstr "jan"
#: utils/dates.py:19
msgid "feb"
-msgstr ""
+msgstr "feb"
#: utils/dates.py:19
msgid "mar"
-msgstr ""
+msgstr "mar"
#: utils/dates.py:19
msgid "apr"
-msgstr ""
+msgstr "apr"
#: utils/dates.py:19
-#, fuzzy
msgid "may"
-msgstr "Maj"
+msgstr "maj"
#: utils/dates.py:19
msgid "jun"
-msgstr ""
+msgstr "jun"
#: utils/dates.py:20
msgid "jul"
-msgstr ""
+msgstr "jul"
#: utils/dates.py:20
msgid "aug"
-msgstr ""
+msgstr "aug"
#: utils/dates.py:20
msgid "sep"
-msgstr ""
+msgstr "sept"
#: utils/dates.py:20
msgid "oct"
-msgstr ""
+msgstr "okt"
#: utils/dates.py:20
msgid "nov"
-msgstr ""
+msgstr "nov"
#: utils/dates.py:20
msgid "dec"
-msgstr ""
+msgstr "dec"
#: utils/dates.py:27
msgid "Jan."
@@ -1469,44 +1438,42 @@ msgstr "Dec."
#: utils/timesince.py:12
msgid "year"
msgid_plural "years"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ã¥r"
+msgstr[1] "Ã¥r"
#: utils/timesince.py:13
msgid "month"
msgid_plural "months"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "måned"
+msgstr[1] "måneder"
#: utils/timesince.py:14
msgid "week"
msgid_plural "weeks"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "uge"
+msgstr[1] "uger"
#: utils/timesince.py:15
-#, fuzzy
msgid "day"
msgid_plural "days"
-msgstr[0] "Maj"
-msgstr[1] "Maj"
+msgstr[0] "dag"
+msgstr[1] "dage"
#: utils/timesince.py:16
msgid "hour"
msgid_plural "hours"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "time"
+msgstr[1] "timer"
#: utils/timesince.py:17
-#, fuzzy
msgid "minute"
msgid_plural "minutes"
-msgstr[0] "side"
-msgstr[1] "side"
+msgstr[0] "minut"
+msgstr[1] "minutter"
#: conf/global_settings.py:37
msgid "Bengali"
-msgstr ""
+msgstr "Bengalsk"
#: conf/global_settings.py:38
msgid "Czech"
@@ -1517,9 +1484,8 @@ msgid "Welsh"
msgstr "Walisisk"
#: conf/global_settings.py:40
-#, fuzzy
msgid "Danish"
-msgstr "Spansk"
+msgstr "Dansk"
#: conf/global_settings.py:41
msgid "German"
@@ -1527,7 +1493,7 @@ msgstr "Tysk"
#: conf/global_settings.py:42
msgid "Greek"
-msgstr ""
+msgstr "Græsk"
#: conf/global_settings.py:43
msgid "English"
@@ -1547,11 +1513,11 @@ msgstr "Galicisk"
#: conf/global_settings.py:47
msgid "Hungarian"
-msgstr ""
+msgstr "Ungarsk"
#: conf/global_settings.py:48
msgid "Hebrew"
-msgstr ""
+msgstr "Hebræisk"
#: conf/global_settings.py:49
msgid "Icelandic"
@@ -1563,11 +1529,11 @@ msgstr "Italiensk"
#: conf/global_settings.py:51
msgid "Japanese"
-msgstr ""
+msgstr "Japansk"
#: conf/global_settings.py:52
msgid "Dutch"
-msgstr ""
+msgstr "Hollandsk"
#: conf/global_settings.py:53
msgid "Norwegian"
@@ -1590,9 +1556,8 @@ msgid "Slovak"
msgstr "Slovakisk"
#: conf/global_settings.py:58
-#, fuzzy
msgid "Slovenian"
-msgstr "Slovakisk"
+msgstr "Slovensk"
#: conf/global_settings.py:59
msgid "Serbian"
@@ -1603,9 +1568,8 @@ msgid "Swedish"
msgstr "Svensk"
#: conf/global_settings.py:61
-#, fuzzy
msgid "Ukrainian"
-msgstr "Brasiliansk"
+msgstr "Ukrainsk"
#: conf/global_settings.py:62
msgid "Simplified Chinese"
@@ -1620,20 +1584,18 @@ msgid "This value must contain only letters, numbers and underscores."
msgstr "Dette felt må kun indeholde bogstaver, tal og understreger."
#: core/validators.py:64
-#, fuzzy
msgid ""
"This value must contain only letters, numbers, underscores, dashes or "
"slashes."
-msgstr ""
-"Dette felt må kun indeholde bogstaver, tal, understreger og skråstreger."
+msgstr "Dette felt må kun indeholde bogstaver, tal, understreger, streger eller skråstreger."
#: core/validators.py:72
msgid "Uppercase letters are not allowed here."
-msgstr "Store bogstaver er ikke tilladt her"
+msgstr "Store bogstaver er ikke tilladt her."
#: core/validators.py:76
msgid "Lowercase letters are not allowed here."
-msgstr "Små bogstaver er ikke tilladt her"
+msgstr "Små bogstaver er ikke tilladt her."
#: core/validators.py:83
msgid "Enter only digits separated by commas."
@@ -1641,11 +1603,11 @@ msgstr "Indtast kun tal adskilt af kommaer."
#: core/validators.py:95
msgid "Enter valid e-mail addresses separated by commas."
-msgstr "Indtast gyldige email-adresser adskilt af kommaer"
+msgstr "Indtast gyldige e-mail-adresser adskilt af kommaer."
#: core/validators.py:99
msgid "Please enter a valid IP address."
-msgstr "Venlist indtast en gyldig email-adresse."
+msgstr "Indtast venligst en gyldig IP-adresse."
#: core/validators.py:103
msgid "Empty values are not allowed here."
@@ -1653,11 +1615,11 @@ msgstr "Dette felt kan ikke være tomt."
#: core/validators.py:107
msgid "Non-numeric characters aren't allowed here."
-msgstr "Der må kun være tal her"
+msgstr "Der må kun være tal i dette felt."
#: core/validators.py:111
msgid "This value can't be comprised solely of digits."
-msgstr "Denne værdi kan ikke kun bestå af tal."
+msgstr "Denne værdi kan ikke udelukkende bestå af tal."
#: core/validators.py:116
msgid "Enter a whole number."
@@ -1681,26 +1643,25 @@ msgstr "Indtast dato og tid i Ã…Ã…Ã…Ã…-MM-DD TT:MM format."
#: core/validators.py:136
msgid "Enter a valid e-mail address."
-msgstr "Indtast en gyldig email-adresse."
+msgstr "Indtast en gyldig e-mail-adresse."
#: core/validators.py:148
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
msgstr ""
-"Upload en billed-fil. Filen du uploadede var enten ikke et billede eller en "
-"ødelagt billed-fil"
+"Indsend en billedfil. Filen du indsendte var enten ikke et billede eller en "
+"ødelagt billedfil."
#: core/validators.py:155
#, python-format
msgid "The URL %s does not point to a valid image."
-msgstr "URLen %s viser ikke til en gyldig billed-fil"
+msgstr "URLen %s viser ikke til en gyldig billedfil."
#: core/validators.py:159
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
-msgstr ""
-"Telefonnumre skal være i XXX-XXX-XXXX formatet. \"%s\" er ikke godkjent."
+msgstr "Telefonnumre skal være i formatet XXXXXXXX. \"%s\" er ikke godkendt."
#: core/validators.py:167
#, python-format
@@ -1709,7 +1670,7 @@ msgstr "URLen %s viser ikke til en gyldig QuickTime-film."
#: core/validators.py:171
msgid "A valid URL is required."
-msgstr "En gyldig URL er påkrævet"
+msgstr "En gyldig URL er påkrævet."
#: core/validators.py:185
#, python-format
@@ -1733,11 +1694,11 @@ msgstr "Ugyldig URL: %s"
#: core/validators.py:206 core/validators.py:208
#, python-format
msgid "The URL %s is a broken link."
-msgstr "Denne URL %s linker ikke til en gyldig side eller fil"
+msgstr "Denne URL %s linker ikke til en gyldig side eller fil."
#: core/validators.py:214
msgid "Enter a valid U.S. state abbreviation."
-msgstr "Indtast en gyldig amerikansk statsforkortelse"
+msgstr "Indtast en gyldig amerikansk statsforkortelse."
#: core/validators.py:229
#, python-format
@@ -1753,25 +1714,25 @@ msgstr "Dette felt skal matche '%s' feltet."
#: core/validators.py:255
msgid "Please enter something for at least one field."
-msgstr "Indtast venligst noget i mindst et felt"
+msgstr "Indtast venligst noget, i mindst ét felt"
#: core/validators.py:264 core/validators.py:275
msgid "Please enter both fields or leave them both empty."
-msgstr "Udfyld begge felter, eller lad dem begge være blanke"
+msgstr "Udfyld begge felter, eller lad dem begge være tomme."
#: core/validators.py:282
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
-msgstr "Dette felt skal udfyldes, hvis %(field)s er lig %(value)s"
+msgstr "Dette felt skal udfyldes, hvis %(field)s er lig %(value)s."
#: core/validators.py:294
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
-msgstr "Dette felt skal udfyldes, hvis %(field)s ikke er lig %(value)s"
+msgstr "Dette felt skal udfyldes, hvis %(field)s ikke er lig %(value)s."
#: core/validators.py:313
msgid "Duplicate values are not allowed."
-msgstr "Duplikate værdier er ikke tilladt her"
+msgstr "Identiske værdier er ikke tilladt her."
#: core/validators.py:336
#, python-format
@@ -1783,34 +1744,32 @@ msgid "Please enter a valid decimal number."
msgstr "Indtast venligst et gyldigt decimaltal."
#: core/validators.py:349
-#, fuzzy, python-format
+#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
-msgid_plural ""
-"Please enter a valid decimal number with at most %s total digits."
-msgstr[0] "Indtast en gyldig decimal med max %s tal ialt"
-msgstr[1] "Indtast en gyldig decimal med max %s tal ialt"
+msgid_plural "Please enter a valid decimal number with at most %s total digits."
+msgstr[0] "Indtast et gyldigt decimaltal med maksimalt %s ciffer i alt."
+msgstr[1] "Indtast et gyldigt decimaltal med maksimalt %s cifre i alt."
#: core/validators.py:352
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
-msgid_plural ""
-"Please enter a valid decimal number with at most %s decimal places."
-msgstr[0] "Indtast en gyldig decimal med max %s tal efter kommaet"
-msgstr[1] "Indtast en gyldig decimal med max %s tal efter kommaet"
+msgid_plural "Please enter a valid decimal number with at most %s decimal places."
+msgstr[0] "Indtast en gyldig decimal med maksimalt %s tal efter kommaet"
+msgstr[1] "Indtast en gyldig decimal med maksimalt %s tal efter kommaet"
#: core/validators.py:362
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
-msgstr "Tjek at den uploadede fil er mindst % bytes."
+msgstr "Tjek at den indsendte fil er mindst %s bytes."
#: core/validators.py:363
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
-msgstr "Tjek at den uploadede file er max %s bytes."
+msgstr "Tjek at den indsendte fil er maksimalt %s bytes."
#: core/validators.py:376
msgid "The format for this field is wrong."
-msgstr "Formatet i dette feltet er feil."
+msgstr "Formatet i dette felt er forkert."
#: core/validators.py:391
msgid "This field is invalid."
@@ -1823,18 +1782,15 @@ msgstr "Kunne ikke finde noget i %s."
#: core/validators.py:429
#, python-format
-msgid ""
-"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
-msgstr ""
-"URLen %(url)s returnerede ikke en godkendt Content-Type '%(contenttype)s'."
+msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
+msgstr "URLen %(url)s returnerede ikke en godkendt Content-Type header '%(contenttype)s'."
#: core/validators.py:462
#, python-format
msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
"\"%(start)s\".)"
-msgstr ""
-"Luk venligst %(tag)s på linje %(line)s. (Linjen starer med \"%(start)s\".)"
+msgstr "Luk venligst %(tag)s på linje %(line)s. (Linjen starter med \"%(start)s\".)"
#: core/validators.py:466
#, python-format
@@ -1860,8 +1816,8 @@ msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
"(start)s\".)"
msgstr ""
-"\"<%(tag)s>\" på linje %(line)s er ikke et gyldigt tag. (Linjen starter med "
-"\"%(start)s\".)"
+"\"<%(tag)s>\" på linje %(line)s er et ugyldigt tag. (Linjen starter med \"%"
+"(start)s\".)"
#: core/validators.py:480
#, python-format
@@ -1869,7 +1825,7 @@ msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line "
"starts with \"%(start)s\".)"
msgstr ""
-"Et tag på linje %(line)s mangler en obligatorisk attribut. (Linjen starter "
+"Et tag på linje %(line)s mangler en påkrævet attribut. (Linjen starter "
"med \"%(start)s\".)"
#: core/validators.py:485
@@ -1878,120 +1834,94 @@ msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
"starts with \"%(start)s\".)"
msgstr ""
-"\"%(attr)s\" attributten på linje $(line)s har en ugyldig værdi. (Linjen "
+"\"%(attr)s\" attributten på linje %(line)s har en ugyldig værdi. (Linjen "
"starter med \"%(start)s\".)"
#: db/models/manipulators.py:302
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
-msgstr ""
+msgstr "%(object)s med denne %(type)s eksisterer allerede for den givne %(field)s."
#: db/models/fields/__init__.py:40
#, python-format
msgid "%(optname)s with this %(fieldname)s already exists."
-msgstr ""
+msgstr "%(optname)s med dette %(fieldname)s eksisterer allerede."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
#: forms/__init__.py:346
-#, fuzzy
msgid "This field is required."
-msgstr "Dette felt er ugyldigt."
+msgstr "Dette felt er påkrævet."
#: db/models/fields/__init__.py:337
-#, fuzzy
msgid "This value must be an integer."
-msgstr "Denne værdi skal være en potens af %s."
+msgstr "Denne værdi skal et heltal."
#: db/models/fields/__init__.py:369
-#, fuzzy
msgid "This value must be either True or False."
-msgstr "Denne værdi skal være en potens af %s."
+msgstr "Denne værdi skal være enten true eller false."
#: db/models/fields/__init__.py:385
-#, fuzzy
msgid "This field cannot be null."
-msgstr "Dette felt er ugyldigt."
+msgstr "Dette felt kan ikke være null."
#: db/models/fields/__init__.py:562
-#, fuzzy
msgid "Enter a valid filename."
-msgstr "Indtast en gyldig email-adresse."
+msgstr "Indtast et gyldigt filnavn."
#: db/models/fields/related.py:43
-#, fuzzy, python-format
+#, python-format
msgid "Please enter a valid %s."
-msgstr "Venlist indtast en gyldig email-adresse."
+msgstr "Indtast venligst en gyldig %s."
#: db/models/fields/related.py:579
-#, fuzzy
msgid "Separate multiple IDs with commas."
-msgstr "Adskil id'er med kommaer."
+msgstr "Adskil flere ID'er med kommaer."
#: db/models/fields/related.py:581
-#, fuzzy
-msgid ""
-"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
-msgstr ""
-"Hold \"Kontrol\", eller \"Æbletasten\" på Mac, nede for at vælge mere end en."
+msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
+msgstr "Hold \"Kontrol\", eller \"Æbletasten\" på Mac nede, for at vælge mere end en."
#: db/models/fields/related.py:625
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
-msgid_plural ""
-"Please enter valid %(self)s IDs. The values %(value)r are invalid."
-msgstr[0] ""
-msgstr[1] ""
+msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid."
+msgstr[0] "Indtast venligst et gyldigt %(self)s-ID. Værdien %(value)r er ugyldig."
+msgstr[1] "Indtast venligst gyldige %(self)s-ID'er. Værdierne %(value)r er ugyldige."
#: forms/__init__.py:380
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Sørg for din tekst er kortere end %s tegn."
+msgstr[1] "Sørg for din tekst er kortere end %s tegn."
#: forms/__init__.py:385
-#, fuzzy
msgid "Line breaks are not allowed here."
-msgstr "Små bogstaver er ikke tilladt her"
+msgstr "Linjebrud er ikke tilladt her."
#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
-msgstr ""
+msgstr "Markér et gyldigt valg; '%(data)s' er ikke i %(choices)s."
#: forms/__init__.py:645
msgid "The submitted file is empty."
-msgstr ""
+msgstr "Den indsendte fil er tom."
#: forms/__init__.py:699
-#, fuzzy
msgid "Enter a whole number between -32,768 and 32,767."
-msgstr "Indtast et heltal."
+msgstr "Indtast et heltal mellem -32,768 og 32,767."
#: forms/__init__.py:708
-#, fuzzy
msgid "Enter a positive number."
-msgstr "Indtast et heltal."
+msgstr "Indtast et positivt tal."
#: forms/__init__.py:717
-#, fuzzy
msgid "Enter a whole number between 0 and 32,767."
-msgstr "Indtast et heltal."
+msgstr "Indtast et heltal mellem 0 og 32,767."
#: template/defaultfilters.py:379
msgid "yes,no,maybe"
-msgstr ""
-
-#, fuzzy
-#~ msgid "Comments"
-#~ msgstr "tillad kommentarer"
-
-#~ msgid "label"
-#~ msgstr "mærkat"
-
-#~ msgid "package"
-#~ msgstr "pakke"
+msgstr "ja,nej,måske"
-#~ msgid "packages"
-#~ msgstr "pakker"
diff --git a/django/conf/locale/de/LC_MESSAGES/django.mo b/django/conf/locale/de/LC_MESSAGES/django.mo
index a4f4af172e..aef68099d3 100644
--- a/django/conf/locale/de/LC_MESSAGES/django.mo
+++ b/django/conf/locale/de/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/de/LC_MESSAGES/django.po b/django/conf/locale/de/LC_MESSAGES/django.po
index 99212a4f53..614ea69247 100644
--- a/django/conf/locale/de/LC_MESSAGES/django.po
+++ b/django/conf/locale/de/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-05-16 10:11+0200\n"
+"POT-Creation-Date: 2006-09-25 16:04+0200\n"
"PO-Revision-Date: 2005-10-08 00:03+0200\n"
"Last-Translator: Georg Bauer <gb@bofh.ms>\n"
"MIME-Version: 1.0\n"
@@ -71,7 +71,7 @@ msgstr "Datum/Zeit Erstellung"
msgid "is public"
msgstr "ist öffentlich"
-#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
+#: contrib/comments/models.py:85 contrib/admin/views/doc.py:304
msgid "IP address"
msgstr "IP-Adresse"
@@ -208,14 +208,14 @@ msgstr "Ungültige Kommentar-ID"
msgid "No voting for yourself"
msgstr "Keine Abstimmung bei Dir selber"
-#: contrib/comments/views/comments.py:28
+#: contrib/comments/views/comments.py:27
msgid ""
"This rating is required because you've entered at least one other rating."
msgstr ""
"Die Abstimmung ist zwangsweise, weil Du an mindestens einer anderen "
"Abstimmung teilnimmst."
-#: contrib/comments/views/comments.py:112
+#: contrib/comments/views/comments.py:111
#, python-format
msgid ""
"This comment was posted by a user who has posted fewer than %(count)s "
@@ -238,7 +238,7 @@ msgstr[1] ""
"\n"
"%(text)s"
-#: contrib/comments/views/comments.py:117
+#: contrib/comments/views/comments.py:116
#, python-format
msgid ""
"This comment was posted by a sketchy user:\n"
@@ -249,23 +249,23 @@ msgstr ""
"\n"
"%(text)s"
-#: contrib/comments/views/comments.py:189
+#: contrib/comments/views/comments.py:188
#: contrib/comments/views/comments.py:280
msgid "Only POSTs are allowed"
msgstr "Nur POST ist erlaubt"
-#: contrib/comments/views/comments.py:193
+#: contrib/comments/views/comments.py:192
#: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted"
msgstr "Eines oder mehrere der erforderlichen Felder fehlt"
-#: contrib/comments/views/comments.py:197
+#: contrib/comments/views/comments.py:196
#: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)"
msgstr ""
"Jemand hat mit dem Kommentarformular herumgespielt (Sicherheitsverletzung)"
-#: contrib/comments/views/comments.py:207
+#: contrib/comments/views/comments.py:206
#: contrib/comments/views/comments.py:292
msgid ""
"The comment form had an invalid 'target' parameter -- the object ID was "
@@ -287,18 +287,9 @@ msgid "Username:"
msgstr "Benutzername:"
#: contrib/comments/templates/comments/form.html:6
-#: contrib/admin/templates/admin/login.html:20
-msgid "Password:"
-msgstr "Passwort:"
-
-#: contrib/comments/templates/comments/form.html:6
-msgid "Forgotten your password?"
-msgstr "Kennwort vergessen?"
-
-#: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:3
@@ -316,6 +307,15 @@ msgstr "Kennwort vergessen?"
msgid "Log out"
msgstr "Abmelden"
+#: contrib/comments/templates/comments/form.html:8
+#: contrib/admin/templates/admin/login.html:20
+msgid "Password:"
+msgstr "Passwort:"
+
+#: contrib/comments/templates/comments/form.html:8
+msgid "Forgotten your password?"
+msgstr "Kennwort vergessen?"
+
#: contrib/comments/templates/comments/form.html:12
msgid "Ratings"
msgstr "Bewertungen"
@@ -334,13 +334,13 @@ msgstr "Optional"
msgid "Post a photo"
msgstr "Ein Bild veröffentlichen"
-#: contrib/comments/templates/comments/form.html:27
+#: contrib/comments/templates/comments/form.html:28
#: contrib/comments/templates/comments/freeform.html:5
msgid "Comment:"
msgstr "Kommentar:"
-#: contrib/comments/templates/comments/form.html:32
-#: contrib/comments/templates/comments/freeform.html:9
+#: contrib/comments/templates/comments/form.html:35
+#: contrib/comments/templates/comments/freeform.html:10
msgid "Preview comment"
msgstr "Kommentarvorschau"
@@ -358,7 +358,7 @@ msgstr ""
"<ul>\n"
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
-#: contrib/admin/filterspecs.py:143
+#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169
msgid "All"
msgstr "Alle"
@@ -422,12 +422,11 @@ msgstr "Logeintrag"
msgid "log entries"
msgstr "Logeinträge"
-#: contrib/admin/templatetags/admin_list.py:228
+#: contrib/admin/templatetags/admin_list.py:230
msgid "All dates"
msgstr "Alle Tage"
-#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
-#: contrib/auth/forms.py:41
+#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:59
msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
@@ -435,12 +434,12 @@ msgstr ""
"Bitte einen Benutzernamen und ein Kennwort eingeben. Beide Felder "
"berücksichtigen die Groß-/Kleinschreibung."
-#: contrib/admin/views/decorators.py:23
+#: contrib/admin/views/decorators.py:24
#: contrib/admin/templates/admin/login.html:25
msgid "Log in"
msgstr "Anmelden"
-#: contrib/admin/views/decorators.py:61
+#: contrib/admin/views/decorators.py:62
msgid ""
"Please log in again, because your session has expired. Don't worry: Your "
"submission has been saved."
@@ -448,7 +447,7 @@ msgstr ""
"Bitte neu anmelden, da die Session ausgelaufen ist. Keine Angst: die "
"Beiträge wurden gesichert."
-#: contrib/admin/views/decorators.py:68
+#: contrib/admin/views/decorators.py:69
msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
@@ -456,70 +455,71 @@ msgstr ""
"Es sieht danach aus, das der Browser keine Cookies akzeptiert. Bitte im "
"Browser Cookies aktivieren und diese Seite neu laden."
-#: contrib/admin/views/decorators.py:82
+#: contrib/admin/views/decorators.py:83
msgid "Usernames cannot contain the '@' character."
msgstr "Benutzernamen können das Zeichen '@' nicht enthalten."
-#: contrib/admin/views/decorators.py:84
+#: contrib/admin/views/decorators.py:85
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
msgstr ""
"Die eMail-Adresse ist nicht der Benutzername. Bitte '%s' stattdessen "
"versuchen."
-#: contrib/admin/views/main.py:226
+#: contrib/admin/views/main.py:223
msgid "Site administration"
msgstr "Website Verwaltung"
-#: contrib/admin/views/main.py:260
+#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:17
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "%(name)s \"%(obj)s\" wurde erfolgreich hinzugefügt."
-#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
+#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347
+#: contrib/admin/views/auth.py:22
msgid "You may edit it again below."
msgstr "Das Element kann jetzt weiter geändert werden."
-#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
+#: contrib/admin/views/main.py:271 contrib/admin/views/main.py:356
#, python-format
msgid "You may add another %s below."
msgstr "Jetzt kann ein weiteres Element vom Typ %s angelegt werden."
-#: contrib/admin/views/main.py:290
+#: contrib/admin/views/main.py:289
#, python-format
msgid "Add %s"
msgstr "%s zufügen"
-#: contrib/admin/views/main.py:336
+#: contrib/admin/views/main.py:335
#, python-format
msgid "Added %s."
msgstr "%s hinzugefügt."
-#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
+#: contrib/admin/views/main.py:339
msgid "and"
msgstr "und"
-#: contrib/admin/views/main.py:338
+#: contrib/admin/views/main.py:337
#, python-format
msgid "Changed %s."
msgstr "%s geändert"
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:339
#, python-format
msgid "Deleted %s."
msgstr "%s gelöscht."
-#: contrib/admin/views/main.py:343
+#: contrib/admin/views/main.py:342
msgid "No fields changed."
msgstr "Keine Felder geändert."
-#: contrib/admin/views/main.py:346
+#: contrib/admin/views/main.py:345
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr "%(name)s \"%(obj)s\" wurde erfolgreich geändert."
-#: contrib/admin/views/main.py:354
+#: contrib/admin/views/main.py:353
#, python-format
msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
@@ -527,119 +527,188 @@ msgstr ""
"%(name)s \"%(obj)s\" wurde erfolgreich zugefügt. Das Element kann jetzt "
"geändert werden."
-#: contrib/admin/views/main.py:392
+#: contrib/admin/views/main.py:391
#, python-format
msgid "Change %s"
msgstr "%s ändern"
-#: contrib/admin/views/main.py:470
+#: contrib/admin/views/main.py:473
#, python-format
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
msgstr "Ein oder mehrere %(fieldname)s in %(name)s: %(obj)s"
-#: contrib/admin/views/main.py:475
+#: contrib/admin/views/main.py:478
#, python-format
msgid "One or more %(fieldname)s in %(name)s:"
msgstr "Ein oder mehrere %(fieldname)s in %(name)s:"
-#: contrib/admin/views/main.py:508
+#: contrib/admin/views/main.py:511
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "%(name)s \"%(obj)s\" wurde erfolgreich gelöscht."
-#: contrib/admin/views/main.py:511
+#: contrib/admin/views/main.py:514
msgid "Are you sure?"
msgstr "Sicher? Ganz sicher?"
-#: contrib/admin/views/main.py:533
+#: contrib/admin/views/main.py:536
#, python-format
msgid "Change history: %s"
msgstr "Änderungsgeschichte: %s"
-#: contrib/admin/views/main.py:565
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s"
msgstr "%s auswählen"
-#: contrib/admin/views/main.py:565
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s to change"
msgstr "%s zur Änderung auswählen"
-#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
-#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
-#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
+#: contrib/admin/views/main.py:758
+msgid "Database error"
+msgstr "Datenbankfehler"
+
+#: contrib/admin/views/doc.py:46 contrib/admin/views/doc.py:48
+#: contrib/admin/views/doc.py:50
+msgid "tag:"
+msgstr "Schlagwort:"
+
+#: contrib/admin/views/doc.py:77 contrib/admin/views/doc.py:79
+#: contrib/admin/views/doc.py:81
+msgid "filter:"
+msgstr "Filter:"
+
+#: contrib/admin/views/doc.py:135 contrib/admin/views/doc.py:137
+#: contrib/admin/views/doc.py:139
+msgid "view:"
+msgstr "Ansicht:"
+
+#: contrib/admin/views/doc.py:164
+#, python-format
+msgid "App %r not found"
+msgstr "Anwendung %r nicht gefunden"
+
+#: contrib/admin/views/doc.py:171
+#, python-format
+msgid "Model %r not found in app %r"
+msgstr "Modell %r wurde nicht in Anwendung %r gefunden"
+
+#: contrib/admin/views/doc.py:183
+#, python-format
+msgid "the related `%s.%s` object"
+msgstr "Das verknüpfte `%s.%s` Objekt"
+
+#: contrib/admin/views/doc.py:183 contrib/admin/views/doc.py:205
+#: contrib/admin/views/doc.py:219 contrib/admin/views/doc.py:224
+msgid "model:"
+msgstr "Modell:"
+
+#: contrib/admin/views/doc.py:214
+#, python-format
+msgid "related `%s.%s` objects"
+msgstr "verknüpftes `%s.%s` Objekt"
+
+#: contrib/admin/views/doc.py:219
+#, python-format
+msgid "all %s"
+msgstr "Alle %s"
+
+#: contrib/admin/views/doc.py:224
+#, python-format
+msgid "number of %s"
+msgstr "Anzahl von %s"
+
+#: contrib/admin/views/doc.py:229
+#, python-format
+msgid "Fields on %s objects"
+msgstr "Felder am %s Objekt"
+
+#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:303 contrib/admin/views/doc.py:309
+#: contrib/admin/views/doc.py:310 contrib/admin/views/doc.py:312
msgid "Integer"
msgstr "Ganzzahl"
-#: contrib/admin/views/doc.py:278
+#: contrib/admin/views/doc.py:292
msgid "Boolean (Either True or False)"
msgstr "Wahrheitswert (Wahr oder Falsch)"
-#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
+#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:311
#, python-format
msgid "String (up to %(maxlength)s)"
msgstr "Zeichenkette (bis zu %(maxlength)s Zeichen)"
-#: contrib/admin/views/doc.py:280
+#: contrib/admin/views/doc.py:294
msgid "Comma-separated integers"
msgstr "Kommaseparierte Liste von Zahlen"
-#: contrib/admin/views/doc.py:281
+#: contrib/admin/views/doc.py:295
msgid "Date (without time)"
msgstr "Datum (ohne Zeit)"
-#: contrib/admin/views/doc.py:282
+#: contrib/admin/views/doc.py:296
msgid "Date (with time)"
msgstr "Datum (mit Zeit)"
-#: contrib/admin/views/doc.py:283
+#: contrib/admin/views/doc.py:297
msgid "E-mail address"
msgstr "E-mail-Adresse"
-#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
+#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:302
msgid "File path"
msgstr "Dateipfad"
-#: contrib/admin/views/doc.py:285
+#: contrib/admin/views/doc.py:300
msgid "Decimal number"
msgstr "Dezimalzahl"
-#: contrib/admin/views/doc.py:291
+#: contrib/admin/views/doc.py:306
msgid "Boolean (Either True, False or None)"
msgstr "Wahrheitswert (Wahr, Falsch oder Nichts)"
-#: contrib/admin/views/doc.py:292
+#: contrib/admin/views/doc.py:307
msgid "Relation to parent model"
msgstr "Beziehung zum Übermodell"
-#: contrib/admin/views/doc.py:293
+#: contrib/admin/views/doc.py:308
msgid "Phone number"
msgstr "Telefonnummer"
-#: contrib/admin/views/doc.py:298
+#: contrib/admin/views/doc.py:313
msgid "Text"
msgstr "Text"
-#: contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:314
msgid "Time"
msgstr "Zeit"
-#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
+#: contrib/admin/views/doc.py:315 contrib/flatpages/models.py:7
msgid "URL"
msgstr "URL"
-#: contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:316
msgid "U.S. state (two uppercase letters)"
msgstr "U.S. Bundesstaat (zwei Grossbuchstaben)"
-#: contrib/admin/views/doc.py:302
+#: contrib/admin/views/doc.py:317
msgid "XML text"
msgstr "XML Text"
+#: contrib/admin/views/doc.py:343
+#, python-format
+msgid "%s does not appear to be a urlpattern object"
+msgstr "%s ist scheinbar kein urlpattern Objekt"
+
+#: contrib/admin/views/auth.py:28
+msgid "Add user"
+msgstr "Benutzer zufügen"
+
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:3
@@ -650,7 +719,7 @@ msgstr "Dokumentation"
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:3
@@ -671,9 +740,10 @@ msgstr "Passwort ändern"
#: contrib/admin/templates/admin/object_history.html:5
#: contrib/admin/templates/admin/500.html:4
#: contrib/admin/templates/admin/change_list.html:6
-#: contrib/admin/templates/admin/base.html:28
+#: contrib/admin/templates/admin/base.html:30
#: contrib/admin/templates/admin/delete_confirmation.html:6
#: contrib/admin/templates/admin/change_form.html:13
+#: contrib/admin/templates/admin/invalid_setup.html:4
#: contrib/admin/templates/registration/password_change_done.html:4
#: contrib/admin/templates/registration/password_reset_form.html:4
#: contrib/admin/templates/registration/logged_out.html:4
@@ -754,7 +824,12 @@ msgstr ""
#: contrib/admin/templates/admin/index.html:17
#, python-format
msgid "Models available in the %(name)s application."
-msgstr ""
+msgstr "Modelle, die in der Anwendung %(name)s vorhanden sind."
+
+#: contrib/admin/templates/admin/index.html:18
+#, python-format
+msgid "%(name)s"
+msgstr "%(name)s"
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
@@ -790,7 +865,7 @@ msgstr "%(name)s zufügen"
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "Haben Sie <a href=\"/password_reset/\">ihr Passwort vergessen</a>?"
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
msgid "Welcome,"
msgstr "Willkommen,"
@@ -802,22 +877,22 @@ msgstr "Löschen"
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
msgid ""
-"Deleting the %(object_name)s '%(object)s' would result in deleting related "
-"objects, but your account doesn't have permission to delete the following "
-"types of objects:"
+"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
+"related objects, but your account doesn't have permission to delete the "
+"following types of objects:"
msgstr ""
-"Die Löschung des %(object_name)s '%(object)s' hätte die Löschung von "
+"Die Löschung des %(object_name)s '%(escaped_object)s' hätte die Löschung von "
"abhängigen Daten zur Folge, aber Sie haben nicht die nötigen Rechte um die "
"folgenden abhängigen Daten zu löschen:"
#: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format
msgid ""
-"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
-"the following related items will be deleted:"
+"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
+"All of the following related items will be deleted:"
msgstr ""
-"Sind Sie sicher, das Sie %(object_name)s \"%(object)s\" löschen wollen? Es "
-"werden zusätzlich die folgenden abhängigen Daten mit gelöscht:"
+"Sind Sie sicher, das Sie %(object_name)s \"%(escaped_object)s\" löschen "
+"wollen? Es werden zusätzlich die folgenden abhängigen Daten mit gelöscht:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure"
@@ -825,13 +900,33 @@ msgstr "Ja, ich bin sicher"
#: contrib/admin/templates/admin/filter.html:2
#, python-format
-msgid " By %(title)s "
-msgstr " Nach %(title)s "
+msgid " By %(filter_title)s "
+msgstr " Nach %(filter_title)s "
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
msgstr "Los"
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "1 result"
+msgid_plural "%(counter)s results"
+msgstr[0] ""
+msgstr[1] ""
+
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "%(full_result_count)s total"
+msgstr "%(full_result_count)s gesamt"
+
+#: contrib/admin/templates/admin/pagination.html:10
+msgid "Show all"
+msgstr "Zeige alle"
+
+#: contrib/admin/templates/admin/filters.html:4
+msgid "Filter"
+msgstr "Filter"
+
#: contrib/admin/templates/admin/change_form.html:21
msgid "View on site"
msgstr "Im Web Anzeigen"
@@ -866,6 +961,40 @@ msgstr "Sichern und weiter bearbeiten"
msgid "Save"
msgstr "Sichern"
+#: contrib/admin/templates/admin/invalid_setup.html:8
+msgid ""
+"Something's wrong with your database installation. Make sure the appropriate "
+"database tables have been created, and make sure the database is readable by "
+"the appropriate user."
+msgstr ""
+"Irgendetwas ist falsch mit der Datenbankkonfiguration. Bitte sicherstellen, "
+"das die richtigen Datenbanktabellen angelegt wurden und bitte sicherstellen, "
+"das die Datenbank vom verwendeten Datenbankbenutzer auch lesbar ist."
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:6
+msgid ""
+"First, enter a username and password. Then, you'll be able to edit more user "
+"options."
+msgstr ""
+"Zuerst einen Benutzer und ein Passwort eingeben. Danach können weitere "
+"Optionen für den Benutzer geändert werden."
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:12
+msgid "Username"
+msgstr "Benutzername"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:18
+msgid "Password"
+msgstr "Passwort"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:23
+msgid "Password (again)"
+msgstr "Kennwort (wiederholen)"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:24
+msgid "Enter the same password as above, for verification."
+msgstr "Bitte das gleiche Passwort zur Prüfung nochmal eingeben."
+
#: contrib/admin/templates/registration/password_change_done.html:4
#: contrib/admin/templates/registration/password_change_form.html:4
#: contrib/admin/templates/registration/password_change_form.html:6
@@ -1093,11 +1222,11 @@ msgstr ""
"Hier muss entweder ein absoluter Pfad oder eine komplette URL mit http:// am "
"Anfang stehen."
-#: contrib/redirects/models.py:12
+#: contrib/redirects/models.py:13
msgid "redirect"
msgstr "Umleitung"
-#: contrib/redirects/models.py:13
+#: contrib/redirects/models.py:14
msgid "redirects"
msgstr "Umleitungen"
@@ -1125,11 +1254,11 @@ msgstr "Name der Vorlage"
#: contrib/flatpages/models.py:13
msgid ""
-"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
-"use 'flatpages/default'."
+"Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
+"will use 'flatpages/default.html'."
msgstr ""
-"Beispiel: 'flatpages/contact_page'. Wenn dieses Feld nicht gefüllt ist, wird "
-"'flatpages/default' als Standard gewählt."
+"Beispiel: 'flatpages/contact_page.html'. Wenn dieses Feld nicht gefüllt ist, "
+"wird 'flatpages/default.html' als Standard gewählt."
#: contrib/flatpages/models.py:14
msgid "registration required"
@@ -1148,80 +1277,108 @@ msgstr "Webseite"
msgid "flat pages"
msgstr "Webseiten"
-#: contrib/auth/models.py:13 contrib/auth/models.py:26
+#: contrib/auth/views.py:39
+msgid "Logged out"
+msgstr "Abgemeldet"
+
+#: contrib/auth/models.py:38 contrib/auth/models.py:57
msgid "name"
msgstr "Name"
-#: contrib/auth/models.py:15
+#: contrib/auth/models.py:40
msgid "codename"
msgstr "Codename"
-#: contrib/auth/models.py:17
+#: contrib/auth/models.py:42
msgid "permission"
msgstr "Berechtigung"
-#: contrib/auth/models.py:18 contrib/auth/models.py:27
+#: contrib/auth/models.py:43 contrib/auth/models.py:58
msgid "permissions"
msgstr "Berechtigungen"
-#: contrib/auth/models.py:29
+#: contrib/auth/models.py:60
msgid "group"
msgstr "Gruppe"
-#: contrib/auth/models.py:30 contrib/auth/models.py:65
+#: contrib/auth/models.py:61 contrib/auth/models.py:100
msgid "groups"
msgstr "Gruppen"
-#: contrib/auth/models.py:55
+#: contrib/auth/models.py:90
msgid "username"
msgstr "Benutzername"
-#: contrib/auth/models.py:56
+#: contrib/auth/models.py:90
+msgid ""
+"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
+"digits and underscores)."
+msgstr ""
+"Erforderlich. 30 Zeichen oder weniger. Alphanumerische Zeichen (Buchstaben, "
+"Ziffern und Unterstriche sind erlaubt)."
+
+#: contrib/auth/models.py:91
msgid "first name"
msgstr "Vorname"
-#: contrib/auth/models.py:57
+#: contrib/auth/models.py:92
msgid "last name"
msgstr "Nachname"
-#: contrib/auth/models.py:58
+#: contrib/auth/models.py:93
msgid "e-mail address"
msgstr "eMail-Adresse"
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "password"
msgstr "Kennwort"
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "Use '[algo]$[salt]$[hexdigest]'"
msgstr "Im Format '[algo]$[salt]$[hexdigest]'"
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "staff status"
msgstr "Administrator"
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "Designates whether the user can log into this admin site."
msgstr ""
"Gibt an, ob der Benutzer sich an der Administrationsseite anmelden kann."
-#: contrib/auth/models.py:61
+#: contrib/auth/models.py:96
msgid "active"
msgstr "Aktiv"
-#: contrib/auth/models.py:62
+#: contrib/auth/models.py:96
+msgid ""
+"Designates whether this user can log into the Django admin. Unselect this "
+"instead of deleting accounts."
+msgstr ""
+"Gibt an, ob der Benutzer sich an der Administrationsseite anmelden kann. "
+"Anstelle Benutzer zu löschen, kann das hier auch einfach abgeschaltet werden."
+
+#: contrib/auth/models.py:97
msgid "superuser status"
msgstr "Hauptadmin."
-#: contrib/auth/models.py:63
+#: contrib/auth/models.py:97
+msgid ""
+"Designates that this user has all permissions without explicitly assigning "
+"them."
+msgstr ""
+"Bestimmt, das dieser Benutzer alle Berechtigungen hat, ohne diese einzeln "
+"zuweisen zu müssen."
+
+#: contrib/auth/models.py:98
msgid "last login"
msgstr "letzte Anmeldung"
-#: contrib/auth/models.py:64
+#: contrib/auth/models.py:99
msgid "date joined"
msgstr "Mitglied seit"
-#: contrib/auth/models.py:66
+#: contrib/auth/models.py:101
msgid ""
"In addition to the permissions manually assigned, this user will also get "
"all permissions granted to each group he/she is in."
@@ -1229,39 +1386,39 @@ msgstr ""
"Zusätzlich zu den manuell angelegten Rechten erhält dieser Benutzer auch "
"alle Rechte, die seine zugewiesenen Gruppen haben."
-#: contrib/auth/models.py:67
+#: contrib/auth/models.py:102
msgid "user permissions"
msgstr "Berechtigungen"
-#: contrib/auth/models.py:70
+#: contrib/auth/models.py:105
msgid "user"
msgstr "Benutzer"
-#: contrib/auth/models.py:71
+#: contrib/auth/models.py:106
msgid "users"
msgstr "Benutzer"
-#: contrib/auth/models.py:76
+#: contrib/auth/models.py:111
msgid "Personal info"
msgstr "Persönliche Infos"
-#: contrib/auth/models.py:77
+#: contrib/auth/models.py:112
msgid "Permissions"
msgstr "Berechtigungen"
-#: contrib/auth/models.py:78
+#: contrib/auth/models.py:113
msgid "Important dates"
msgstr "Wichtige Daten"
-#: contrib/auth/models.py:79
+#: contrib/auth/models.py:114
msgid "Groups"
msgstr "Gruppen"
-#: contrib/auth/models.py:219
+#: contrib/auth/models.py:256
msgid "message"
msgstr "Mitteilung"
-#: contrib/auth/forms.py:30
+#: contrib/auth/forms.py:52
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in."
@@ -1269,35 +1426,55 @@ msgstr ""
"Der Webbrowser scheint keine Cookies aktiviert zu haben. Cookies sind für "
"die Anmeldung zwingend notwendig."
-#: contrib/contenttypes/models.py:25
+#: contrib/auth/forms.py:61
+msgid "This account is inactive."
+msgstr "Dieser Benutzer ist inaktiv."
+
+#: contrib/auth/forms.py:84
+msgid ""
+"That e-mail address doesn't have an associated user acount. Are you sure "
+"you've registered?"
+msgstr ""
+"Die Email-Adresse hat keinen Benutzer zugeordnet. Sicher, das die Adresse "
+"hier angemeldet ist?"
+
+#: contrib/auth/forms.py:116
+msgid "The two 'new password' fields didn't match."
+msgstr "Die zwei Passwörter sind nicht gleich."
+
+#: contrib/auth/forms.py:123
+msgid "Your old password was entered incorrectly. Please enter it again."
+msgstr "Das alte Passwort war falsch. Bitte neu eingeben."
+
+#: contrib/contenttypes/models.py:20
msgid "python model class name"
msgstr "Python Model-Klassenname"
-#: contrib/contenttypes/models.py:28
+#: contrib/contenttypes/models.py:23
msgid "content type"
msgstr "Inhaltstyp"
-#: contrib/contenttypes/models.py:29
+#: contrib/contenttypes/models.py:24
msgid "content types"
msgstr "Inhaltstypen"
-#: contrib/sessions/models.py:35
+#: contrib/sessions/models.py:51
msgid "session key"
msgstr "Sitzungs-ID"
-#: contrib/sessions/models.py:36
+#: contrib/sessions/models.py:52
msgid "session data"
msgstr "Sitzungsdaten"
-#: contrib/sessions/models.py:37
+#: contrib/sessions/models.py:53
msgid "expire date"
msgstr "Verfallsdatum"
-#: contrib/sessions/models.py:41
+#: contrib/sessions/models.py:57
msgid "session"
msgstr "Sitzung"
-#: contrib/sessions/models.py:42
+#: contrib/sessions/models.py:58
msgid "sessions"
msgstr "Sitzungen"
@@ -1317,18 +1494,6 @@ msgstr "Website"
msgid "sites"
msgstr "Websites"
-#: utils/translation.py:360
-msgid "DATE_FORMAT"
-msgstr "j. N Y"
-
-#: utils/translation.py:361
-msgid "DATETIME_FORMAT"
-msgstr "j. N Y, H:i"
-
-#: utils/translation.py:362
-msgid "TIME_FORMAT"
-msgstr "H:i"
-
#: utils/dates.py:6
msgid "Monday"
msgstr "Montag"
@@ -1517,119 +1682,159 @@ msgid_plural "minutes"
msgstr[0] "Minute"
msgstr[1] "Minuten"
-#: conf/global_settings.py:37
+#: utils/translation/trans_real.py:362
+msgid "DATE_FORMAT"
+msgstr "j. N Y"
+
+#: utils/translation/trans_real.py:363
+msgid "DATETIME_FORMAT"
+msgstr "j. N Y, H:i"
+
+#: utils/translation/trans_real.py:364
+msgid "TIME_FORMAT"
+msgstr "H:i"
+
+#: utils/translation/trans_real.py:380
+msgid "YEAR_MONTH_FORMAT"
+msgstr "F Y"
+
+#: utils/translation/trans_real.py:381
+msgid "MONTH_DAY_FORMAT"
+msgstr "j. F"
+
+#: conf/global_settings.py:39
+msgid "Arabic"
+msgstr "Arabisch"
+
+#: conf/global_settings.py:40
msgid "Bengali"
msgstr "Bengali"
-#: conf/global_settings.py:38
+#: conf/global_settings.py:41
msgid "Czech"
msgstr "Tschechisch"
-#: conf/global_settings.py:39
+#: conf/global_settings.py:42
msgid "Welsh"
msgstr "Walisisch"
-#: conf/global_settings.py:40
+#: conf/global_settings.py:43
msgid "Danish"
msgstr "Dänisch"
-#: conf/global_settings.py:41
+#: conf/global_settings.py:44
msgid "German"
msgstr "Deutsch"
-#: conf/global_settings.py:42
+#: conf/global_settings.py:45
msgid "Greek"
msgstr "Griechisch"
-#: conf/global_settings.py:43
+#: conf/global_settings.py:46
msgid "English"
msgstr "Englisch"
-#: conf/global_settings.py:44
+#: conf/global_settings.py:47
msgid "Spanish"
msgstr "Spanisch"
-#: conf/global_settings.py:45
+#: conf/global_settings.py:48
+msgid "Argentinean Spanish"
+msgstr "Argentinisches Spanisch"
+
+#: conf/global_settings.py:49
+msgid "Finnish"
+msgstr "Finnisch"
+
+#: conf/global_settings.py:50
msgid "French"
msgstr "Französisch"
-#: conf/global_settings.py:46
+#: conf/global_settings.py:51
msgid "Galician"
msgstr "Galicisch"
-#: conf/global_settings.py:47
+#: conf/global_settings.py:52
msgid "Hungarian"
-msgstr ""
+msgstr "Ungarisch"
-#: conf/global_settings.py:48
+#: conf/global_settings.py:53
msgid "Hebrew"
msgstr "Hebräisch"
-#: conf/global_settings.py:49
+#: conf/global_settings.py:54
msgid "Icelandic"
msgstr "Isländisch"
-#: conf/global_settings.py:50
+#: conf/global_settings.py:55
msgid "Italian"
msgstr "Italienisch"
-#: conf/global_settings.py:51
+#: conf/global_settings.py:56
msgid "Japanese"
msgstr "Japanisch"
-#: conf/global_settings.py:52
+#: conf/global_settings.py:57
msgid "Dutch"
msgstr "Holländisch"
-#: conf/global_settings.py:53
+#: conf/global_settings.py:58
msgid "Norwegian"
msgstr "Norwegisch"
-#: conf/global_settings.py:54
+#: conf/global_settings.py:59
msgid "Brazilian"
msgstr "Brasilianisch"
-#: conf/global_settings.py:55
+#: conf/global_settings.py:60
msgid "Romanian"
msgstr "Rumänisch"
-#: conf/global_settings.py:56
+#: conf/global_settings.py:61
msgid "Russian"
msgstr "Russisch"
-#: conf/global_settings.py:57
+#: conf/global_settings.py:62
msgid "Slovak"
msgstr "Slowakisch"
-#: conf/global_settings.py:58
+#: conf/global_settings.py:63
msgid "Slovenian"
msgstr "Slowenisch"
-#: conf/global_settings.py:59
+#: conf/global_settings.py:64
msgid "Serbian"
msgstr "Serbisch"
-#: conf/global_settings.py:60
+#: conf/global_settings.py:65
msgid "Swedish"
msgstr "Schwedisch"
-#: conf/global_settings.py:61
+#: conf/global_settings.py:66
+msgid "Tamil"
+msgstr "Tamilisch"
+
+#: conf/global_settings.py:67
+msgid "Turkish"
+msgstr "Türkisch"
+
+#: conf/global_settings.py:68
msgid "Ukrainian"
msgstr "Ukrainisch"
-#: conf/global_settings.py:62
+#: conf/global_settings.py:69
msgid "Simplified Chinese"
msgstr "Vereinfachtes Chinesisch"
-#: conf/global_settings.py:63
+#: conf/global_settings.py:70
msgid "Traditional Chinese"
msgstr "Traditionelles Chinesisch"
-#: core/validators.py:60
+#: core/validators.py:63
msgid "This value must contain only letters, numbers and underscores."
msgstr "Dieser Wert darf nur Buchstaben, Ziffern und Unterstriche enthalten."
-#: core/validators.py:64
+#: core/validators.py:67
msgid ""
"This value must contain only letters, numbers, underscores, dashes or "
"slashes."
@@ -1637,65 +1842,85 @@ msgstr ""
"Dieser Wert darf nur Buchstaben, Ziffern, Unterstriche und Schrägstriche "
"enthalten."
-#: core/validators.py:72
+#: core/validators.py:71
+msgid "This value must contain only letters, numbers, underscores or hyphens."
+msgstr ""
+"Dieser Wert darf nur Buchstaben, Ziffern, Unterstriche und Bindestriche "
+"enthalten."
+
+#: core/validators.py:75
msgid "Uppercase letters are not allowed here."
msgstr "Großbuchstaben sind hier nicht erlaubt."
-#: core/validators.py:76
+#: core/validators.py:79
msgid "Lowercase letters are not allowed here."
msgstr "Kleinbuchstaben sind hier nicht erlaubt."
-#: core/validators.py:83
+#: core/validators.py:86
msgid "Enter only digits separated by commas."
msgstr "Hier sind nur durch Komma getrennte Ziffern erlaubt."
-#: core/validators.py:95
+#: core/validators.py:98
msgid "Enter valid e-mail addresses separated by commas."
msgstr "Bitte mit Komma getrennte, gültige eMail-Adressen eingeben."
-#: core/validators.py:99
+#: core/validators.py:102
msgid "Please enter a valid IP address."
msgstr "Bitte eine gültige IP-Adresse eingeben."
-#: core/validators.py:103
+#: core/validators.py:106
msgid "Empty values are not allowed here."
msgstr "Dieses Feld darf nicht leer sein."
-#: core/validators.py:107
+#: core/validators.py:110
msgid "Non-numeric characters aren't allowed here."
msgstr "Nichtnumerische Zeichen sind hier nicht erlaubt."
-#: core/validators.py:111
+#: core/validators.py:114
msgid "This value can't be comprised solely of digits."
msgstr "Dieser Wert darf nicht nur aus Ziffern bestehen."
-#: core/validators.py:116
+#: core/validators.py:119
msgid "Enter a whole number."
msgstr "Bitte eine ganze Zahl eingeben."
-#: core/validators.py:120
+#: core/validators.py:123
msgid "Only alphabetical characters are allowed here."
msgstr "Nur alphabetische Zeichen sind hier erlaubt."
-#: core/validators.py:124
+#: core/validators.py:138
+msgid "Year must be 1900 or later."
+msgstr "Das Jahr muss 1900 oder später sein."
+
+#: core/validators.py:142
+#, python-format
+msgid "Invalid date: %s."
+msgstr "Ungültiges Datum: %s"
+
+#: core/validators.py:146 db/models/fields/__init__.py:415
msgid "Enter a valid date in YYYY-MM-DD format."
msgstr "Bitte ein gültiges Datum im Format JJJJ-MM-TT eingeben."
-#: core/validators.py:128
+#: core/validators.py:151
msgid "Enter a valid time in HH:MM format."
msgstr "Bitte eine gültige Zeit im Format SS:MM eingeben."
-#: core/validators.py:132 db/models/fields/__init__.py:468
+#: core/validators.py:155 db/models/fields/__init__.py:477
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr ""
"Bitte eine gültige Datums- und Zeitangabe im Format JJJJ-MM-TT SS:MM "
"eingeben."
-#: core/validators.py:136
+#: core/validators.py:160
msgid "Enter a valid e-mail address."
msgstr "Bitte eine gültige eMail-Adresse eingeben"
-#: core/validators.py:148
+#: core/validators.py:172 core/validators.py:401 forms/__init__.py:661
+msgid "No file was submitted. Check the encoding type on the form."
+msgstr ""
+"Es wurde keine Datei geschickt. Eventuell ist das Formular-Encoding falsch."
+
+#: core/validators.py:176
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
@@ -1703,27 +1928,27 @@ msgstr ""
"Bitte ein Bild hochladen. Die Datei, die hochgeladen wurde, ist kein Bild "
"oder ist defekt."
-#: core/validators.py:155
+#: core/validators.py:183
#, python-format
msgid "The URL %s does not point to a valid image."
msgstr "Die URL %s zeigt nicht auf ein gültiges Bild."
-#: core/validators.py:159
+#: core/validators.py:187
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr ""
"Telefonnummern müssen im Format XXX-XXX-XXXX sein. \"%s\" ist ungültig."
-#: core/validators.py:167
+#: core/validators.py:195
#, python-format
msgid "The URL %s does not point to a valid QuickTime video."
msgstr "Die URL %s zeigt nicht auf ein gültiges QuickTime video."
-#: core/validators.py:171
+#: core/validators.py:199
msgid "A valid URL is required."
msgstr "Eine gültige URL ist hier verlangt."
-#: core/validators.py:185
+#: core/validators.py:213
#, python-format
msgid ""
"Valid HTML is required. Specific errors are:\n"
@@ -1732,71 +1957,71 @@ msgstr ""
"Bitte gültiges HTML eingeben. Fehler sind:\n"
"%s"
-#: core/validators.py:192
+#: core/validators.py:220
#, python-format
msgid "Badly formed XML: %s"
msgstr "Ungültiges XML: %s"
-#: core/validators.py:202
+#: core/validators.py:230
#, python-format
msgid "Invalid URL: %s"
msgstr "Ungültige URL: %s"
-#: core/validators.py:206 core/validators.py:208
+#: core/validators.py:234 core/validators.py:236
#, python-format
msgid "The URL %s is a broken link."
msgstr "Die URL %s funktioniert nicht."
-#: core/validators.py:214
+#: core/validators.py:242
msgid "Enter a valid U.S. state abbreviation."
msgstr "Bitte eine gültige Abkürzung für einen US-Staat eingeben."
-#: core/validators.py:229
+#: core/validators.py:256
#, python-format
msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Keine Schimpfworte! Das Wort %s ist hier nicht gern gesehen!"
msgstr[1] "Keine Schimpfworte! Die Wörter %s sind hier nicht gern gesehen!"
-#: core/validators.py:236
+#: core/validators.py:263
#, python-format
msgid "This field must match the '%s' field."
msgstr "Dieses Feld muss zum Feld '%s' passen."
-#: core/validators.py:255
+#: core/validators.py:282
msgid "Please enter something for at least one field."
msgstr "Bitte mindestens eines der Felder ausfüllen."
-#: core/validators.py:264 core/validators.py:275
+#: core/validators.py:291 core/validators.py:302
msgid "Please enter both fields or leave them both empty."
msgstr "Bitte entweder beide Felder ausfüllen, oder beide leer lassen."
-#: core/validators.py:282
+#: core/validators.py:309
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
msgstr ""
"Dieses Feld muss gefüllt sein, wenn Feld %(field)s den Wert %(value)s hat."
-#: core/validators.py:294
+#: core/validators.py:321
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
msgstr ""
"Dieses Feld muss gefüllt sein, wenn Feld %(field)s nicht %(value)s ist."
-#: core/validators.py:313
+#: core/validators.py:340
msgid "Duplicate values are not allowed."
msgstr "Doppelte Werte sind hier nicht erlaubt."
-#: core/validators.py:336
+#: core/validators.py:363
#, python-format
msgid "This value must be a power of %s."
msgstr "Dieser Wert muss eine Potenz von %s sein."
-#: core/validators.py:347
+#: core/validators.py:374
msgid "Please enter a valid decimal number."
msgstr "Bitte eine gültige Dezimalzahl eingeben."
-#: core/validators.py:349
+#: core/validators.py:378
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
@@ -1804,7 +2029,16 @@ msgid_plural ""
msgstr[0] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffer eingeben."
msgstr[1] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffern eingeben."
-#: core/validators.py:352
+#: core/validators.py:381
+#, python-format
+msgid ""
+"Please enter a valid decimal number with a whole part of at most %s digit."
+msgid_plural ""
+"Please enter a valid decimal number with a whole part of at most %s digits."
+msgstr[0] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffer eingeben."
+msgstr[1] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffern eingeben."
+
+#: core/validators.py:384
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
@@ -1814,39 +2048,39 @@ msgstr[0] ""
msgstr[1] ""
"Bitte eine gültige Dezimalzahl mit maximal %s Dezimalstellen eingeben."
-#: core/validators.py:362
+#: core/validators.py:394
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr ""
"Bitte sicherstellen, daß die hochgeladene Datei mindestens %s Bytes gross "
"ist."
-#: core/validators.py:363
+#: core/validators.py:395
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr ""
"Bitte sicherstellen, daß die hochgeladene Datei maximal %s Bytes gross ist."
-#: core/validators.py:376
+#: core/validators.py:412
msgid "The format for this field is wrong."
msgstr "Das Format für dieses Feld ist falsch."
-#: core/validators.py:391
+#: core/validators.py:427
msgid "This field is invalid."
msgstr "Dieses Feld ist ungültig."
-#: core/validators.py:426
+#: core/validators.py:463
#, python-format
msgid "Could not retrieve anything from %s."
msgstr "Konnte nichts von %s empfangen."
-#: core/validators.py:429
+#: core/validators.py:466
#, python-format
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr "Die URL %(url)s lieferte den falschen Content-Type '%(contenttype)s'."
-#: core/validators.py:462
+#: core/validators.py:499
#, python-format
msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
@@ -1855,7 +2089,7 @@ msgstr ""
"Bitte das ungeschlossene %(tag)s Tag in Zeile %(line)s schließen. Die Zeile "
"beginnt mit \"%(start)s\"."
-#: core/validators.py:466
+#: core/validators.py:503
#, python-format
msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line "
@@ -1864,7 +2098,7 @@ msgstr ""
"In Zeile %(line)s ist Text, der nicht in dem Kontext erlaubt ist. Die Zeile "
"beginnt mit \"%(start)s\"."
-#: core/validators.py:471
+#: core/validators.py:508
#, python-format
msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
@@ -1873,7 +2107,7 @@ msgstr ""
"Das Attribute %(attr)s in Zeile %(line)s ist ungültig. Die Zeile beginnt mit "
"\"%(start)s\"."
-#: core/validators.py:476
+#: core/validators.py:513
#, python-format
msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
@@ -1882,7 +2116,7 @@ msgstr ""
"<%(tag)s> in Zeile %(line)s ist ungültig. Die Zeile beginnt mit \"%(start)s"
"\"."
-#: core/validators.py:480
+#: core/validators.py:517
#, python-format
msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line "
@@ -1891,7 +2125,7 @@ msgstr ""
"Ein Tag in Zeile %(line)s hat eines oder mehrere Pflichtattribute nicht. Die "
"Zeile beginnt mit \"%(start)s\"."
-#: core/validators.py:485
+#: core/validators.py:522
#, python-format
msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
@@ -1900,6 +2134,21 @@ msgstr ""
"Das Attribut %(attr)s in Zeile %(line)s hat einen ungültigen Wert. Die Zeile "
"beginnt mit \"%(start)s\"."
+#: views/generic/create_update.py:43
+#, python-format
+msgid "The %(verbose_name)s was created successfully."
+msgstr "%(verbose_name)s wurde erfolgreich angelegt."
+
+#: views/generic/create_update.py:117
+#, python-format
+msgid "The %(verbose_name)s was updated successfully."
+msgstr "%(verbose_name)s wurde erfolgreich aktualisiert."
+
+#: views/generic/create_update.py:184
+#, python-format
+msgid "The %(verbose_name)s was deleted."
+msgstr "%(verbose_name)s wurde gelöscht"
+
#: db/models/manipulators.py:302
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
@@ -1913,44 +2162,44 @@ msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "Ein '%(optname)s' mit diesem '%(fieldname)s' existiert bereits."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
-#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
+#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562
#: forms/__init__.py:346
msgid "This field is required."
msgstr "Dieses Feld ist zwingend."
-#: db/models/fields/__init__.py:337
+#: db/models/fields/__init__.py:340
msgid "This value must be an integer."
msgstr "Dieser Wert muss eine Ganzzahl sein."
-#: db/models/fields/__init__.py:369
+#: db/models/fields/__init__.py:372
msgid "This value must be either True or False."
msgstr "Dieser Wert muss wahr oder falsch sein."
-#: db/models/fields/__init__.py:385
+#: db/models/fields/__init__.py:388
msgid "This field cannot be null."
msgstr "Dieses Feld darf nicht leer sein."
-#: db/models/fields/__init__.py:562
+#: db/models/fields/__init__.py:571
msgid "Enter a valid filename."
msgstr "Bitte einen gültigen Dateinamen eingeben"
-#: db/models/fields/related.py:43
+#: db/models/fields/related.py:51
#, python-format
msgid "Please enter a valid %s."
msgstr "Bitte ein gültiges '%s' eingeben."
-#: db/models/fields/related.py:579
+#: db/models/fields/related.py:618
msgid "Separate multiple IDs with commas."
msgstr "Mehrere IDs können mit Komma getrennt werden."
-#: db/models/fields/related.py:581
+#: db/models/fields/related.py:620
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
" Um mehr als eine Selektion zu treffen, \"Strg\", oder auf dem Mac \"Command"
"\", beim Klicken gedrückt halten."
-#: db/models/fields/related.py:625
+#: db/models/fields/related.py:664
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
msgid_plural ""
@@ -1960,39 +2209,39 @@ msgstr[0] ""
msgstr[1] ""
"Bitte gültige IDs für %(self)s eingeben. Die Werte %(value)r sind ungültig."
-#: forms/__init__.py:380
+#: forms/__init__.py:381
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Bitte sicherstellen, das der Text weniger als %s Zeichen hat."
msgstr[1] "Bitte sicherstellen, das der Text weniger als %s Zeichen hat."
-#: forms/__init__.py:385
+#: forms/__init__.py:386
msgid "Line breaks are not allowed here."
msgstr "Zeilenumbrüche sind hier nicht erlaubt."
-#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
+#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr ""
"Bitte eine gültige Auswahl treffen; '%(data)s' ist nicht in %(choices)s."
-#: forms/__init__.py:645
+#: forms/__init__.py:663
msgid "The submitted file is empty."
msgstr "Die ausgewählte Datei ist leer."
-#: forms/__init__.py:699
+#: forms/__init__.py:719
msgid "Enter a whole number between -32,768 and 32,767."
msgstr "Bitte eine ganze Zahl zwischen -32.768 und 32.767 eingeben."
-#: forms/__init__.py:708
+#: forms/__init__.py:729
msgid "Enter a positive number."
msgstr "Bitte eine ganze, positive Zahl eingeben."
-#: forms/__init__.py:717
+#: forms/__init__.py:739
msgid "Enter a whole number between 0 and 32,767."
msgstr "Bitte eine ganze Zahl zwischen 0 und 32.767 eingeben."
-#: template/defaultfilters.py:379
+#: template/defaultfilters.py:401
msgid "yes,no,maybe"
msgstr "Ja,Nein,Vielleicht"
diff --git a/django/conf/locale/en/LC_MESSAGES/django.mo b/django/conf/locale/en/LC_MESSAGES/django.mo
index 0a4947bfc1..6c4dbe4b4e 100644
--- a/django/conf/locale/en/LC_MESSAGES/django.mo
+++ b/django/conf/locale/en/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/en/LC_MESSAGES/django.po b/django/conf/locale/en/LC_MESSAGES/django.po
index 625c3b04f1..feba39f7cd 100644
--- a/django/conf/locale/en/LC_MESSAGES/django.po
+++ b/django/conf/locale/en/LC_MESSAGES/django.po
@@ -3,12 +3,11 @@
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
-#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-05-16 10:10+0200\n"
+"POT-Creation-Date: 2006-09-25 15:43+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -73,7 +72,7 @@ msgstr ""
msgid "is public"
msgstr ""
-#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
+#: contrib/comments/models.py:85 contrib/admin/views/doc.py:304
msgid "IP address"
msgstr ""
@@ -200,12 +199,12 @@ msgstr ""
msgid "No voting for yourself"
msgstr ""
-#: contrib/comments/views/comments.py:28
+#: contrib/comments/views/comments.py:27
msgid ""
"This rating is required because you've entered at least one other rating."
msgstr ""
-#: contrib/comments/views/comments.py:112
+#: contrib/comments/views/comments.py:111
#, python-format
msgid ""
"This comment was posted by a user who has posted fewer than %(count)s "
@@ -220,7 +219,7 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
-#: contrib/comments/views/comments.py:117
+#: contrib/comments/views/comments.py:116
#, python-format
msgid ""
"This comment was posted by a sketchy user:\n"
@@ -228,22 +227,22 @@ msgid ""
"%(text)s"
msgstr ""
-#: contrib/comments/views/comments.py:189
+#: contrib/comments/views/comments.py:188
#: contrib/comments/views/comments.py:280
msgid "Only POSTs are allowed"
msgstr ""
-#: contrib/comments/views/comments.py:193
+#: contrib/comments/views/comments.py:192
#: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted"
msgstr ""
-#: contrib/comments/views/comments.py:197
+#: contrib/comments/views/comments.py:196
#: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)"
msgstr ""
-#: contrib/comments/views/comments.py:207
+#: contrib/comments/views/comments.py:206
#: contrib/comments/views/comments.py:292
msgid ""
"The comment form had an invalid 'target' parameter -- the object ID was "
@@ -262,18 +261,9 @@ msgid "Username:"
msgstr ""
#: contrib/comments/templates/comments/form.html:6
-#: contrib/admin/templates/admin/login.html:20
-msgid "Password:"
-msgstr ""
-
-#: contrib/comments/templates/comments/form.html:6
-msgid "Forgotten your password?"
-msgstr ""
-
-#: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:3
@@ -291,6 +281,15 @@ msgstr ""
msgid "Log out"
msgstr ""
+#: contrib/comments/templates/comments/form.html:8
+#: contrib/admin/templates/admin/login.html:20
+msgid "Password:"
+msgstr ""
+
+#: contrib/comments/templates/comments/form.html:8
+msgid "Forgotten your password?"
+msgstr ""
+
#: contrib/comments/templates/comments/form.html:12
msgid "Ratings"
msgstr ""
@@ -309,13 +308,13 @@ msgstr ""
msgid "Post a photo"
msgstr ""
-#: contrib/comments/templates/comments/form.html:27
+#: contrib/comments/templates/comments/form.html:28
#: contrib/comments/templates/comments/freeform.html:5
msgid "Comment:"
msgstr ""
-#: contrib/comments/templates/comments/form.html:32
-#: contrib/comments/templates/comments/freeform.html:9
+#: contrib/comments/templates/comments/form.html:35
+#: contrib/comments/templates/comments/freeform.html:10
msgid "Preview comment"
msgstr ""
@@ -331,7 +330,7 @@ msgid ""
msgstr ""
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
-#: contrib/admin/filterspecs.py:143
+#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169
msgid "All"
msgstr ""
@@ -395,214 +394,283 @@ msgstr ""
msgid "log entries"
msgstr ""
-#: contrib/admin/templatetags/admin_list.py:228
+#: contrib/admin/templatetags/admin_list.py:230
msgid "All dates"
msgstr ""
-#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
-#: contrib/auth/forms.py:41
+#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:59
msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
msgstr ""
-#: contrib/admin/views/decorators.py:23
+#: contrib/admin/views/decorators.py:24
#: contrib/admin/templates/admin/login.html:25
msgid "Log in"
msgstr ""
-#: contrib/admin/views/decorators.py:61
+#: contrib/admin/views/decorators.py:62
msgid ""
"Please log in again, because your session has expired. Don't worry: Your "
"submission has been saved."
msgstr ""
-#: contrib/admin/views/decorators.py:68
+#: contrib/admin/views/decorators.py:69
msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
msgstr ""
-#: contrib/admin/views/decorators.py:82
+#: contrib/admin/views/decorators.py:83
msgid "Usernames cannot contain the '@' character."
msgstr ""
-#: contrib/admin/views/decorators.py:84
+#: contrib/admin/views/decorators.py:85
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
msgstr ""
-#: contrib/admin/views/main.py:226
+#: contrib/admin/views/main.py:223
msgid "Site administration"
msgstr ""
-#: contrib/admin/views/main.py:260
+#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:17
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr ""
-#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
+#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347
+#: contrib/admin/views/auth.py:22
msgid "You may edit it again below."
msgstr ""
-#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
+#: contrib/admin/views/main.py:271 contrib/admin/views/main.py:356
#, python-format
msgid "You may add another %s below."
msgstr ""
-#: contrib/admin/views/main.py:290
+#: contrib/admin/views/main.py:289
#, python-format
msgid "Add %s"
msgstr ""
-#: contrib/admin/views/main.py:336
+#: contrib/admin/views/main.py:335
#, python-format
msgid "Added %s."
msgstr ""
-#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
+#: contrib/admin/views/main.py:339
msgid "and"
msgstr ""
-#: contrib/admin/views/main.py:338
+#: contrib/admin/views/main.py:337
#, python-format
msgid "Changed %s."
msgstr ""
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:339
#, python-format
msgid "Deleted %s."
msgstr ""
-#: contrib/admin/views/main.py:343
+#: contrib/admin/views/main.py:342
msgid "No fields changed."
msgstr ""
-#: contrib/admin/views/main.py:346
+#: contrib/admin/views/main.py:345
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr ""
-#: contrib/admin/views/main.py:354
+#: contrib/admin/views/main.py:353
#, python-format
msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr ""
-#: contrib/admin/views/main.py:392
+#: contrib/admin/views/main.py:391
#, python-format
msgid "Change %s"
msgstr ""
-#: contrib/admin/views/main.py:470
+#: contrib/admin/views/main.py:473
#, python-format
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
msgstr ""
-#: contrib/admin/views/main.py:475
+#: contrib/admin/views/main.py:478
#, python-format
msgid "One or more %(fieldname)s in %(name)s:"
msgstr ""
-#: contrib/admin/views/main.py:508
+#: contrib/admin/views/main.py:511
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr ""
-#: contrib/admin/views/main.py:511
+#: contrib/admin/views/main.py:514
msgid "Are you sure?"
msgstr ""
-#: contrib/admin/views/main.py:533
+#: contrib/admin/views/main.py:536
#, python-format
msgid "Change history: %s"
msgstr ""
-#: contrib/admin/views/main.py:565
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s"
msgstr ""
-#: contrib/admin/views/main.py:565
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s to change"
msgstr ""
-#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
-#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
-#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
+#: contrib/admin/views/main.py:758
+msgid "Database error"
+msgstr ""
+
+#: contrib/admin/views/doc.py:46 contrib/admin/views/doc.py:48
+#: contrib/admin/views/doc.py:50
+msgid "tag:"
+msgstr ""
+
+#: contrib/admin/views/doc.py:77 contrib/admin/views/doc.py:79
+#: contrib/admin/views/doc.py:81
+msgid "filter:"
+msgstr ""
+
+#: contrib/admin/views/doc.py:135 contrib/admin/views/doc.py:137
+#: contrib/admin/views/doc.py:139
+msgid "view:"
+msgstr ""
+
+#: contrib/admin/views/doc.py:164
+#, python-format
+msgid "App %r not found"
+msgstr ""
+
+#: contrib/admin/views/doc.py:171
+#, python-format
+msgid "Model %r not found in app %r"
+msgstr ""
+
+#: contrib/admin/views/doc.py:183
+#, python-format
+msgid "the related `%s.%s` object"
+msgstr ""
+
+#: contrib/admin/views/doc.py:183 contrib/admin/views/doc.py:205
+#: contrib/admin/views/doc.py:219 contrib/admin/views/doc.py:224
+msgid "model:"
+msgstr ""
+
+#: contrib/admin/views/doc.py:214
+#, python-format
+msgid "related `%s.%s` objects"
+msgstr ""
+
+#: contrib/admin/views/doc.py:219
+#, python-format
+msgid "all %s"
+msgstr ""
+
+#: contrib/admin/views/doc.py:224
+#, python-format
+msgid "number of %s"
+msgstr ""
+
+#: contrib/admin/views/doc.py:229
+#, python-format
+msgid "Fields on %s objects"
+msgstr ""
+
+#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:303 contrib/admin/views/doc.py:309
+#: contrib/admin/views/doc.py:310 contrib/admin/views/doc.py:312
msgid "Integer"
msgstr ""
-#: contrib/admin/views/doc.py:278
+#: contrib/admin/views/doc.py:292
msgid "Boolean (Either True or False)"
msgstr ""
-#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
+#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:311
#, python-format
msgid "String (up to %(maxlength)s)"
msgstr ""
-#: contrib/admin/views/doc.py:280
+#: contrib/admin/views/doc.py:294
msgid "Comma-separated integers"
msgstr ""
-#: contrib/admin/views/doc.py:281
+#: contrib/admin/views/doc.py:295
msgid "Date (without time)"
msgstr ""
-#: contrib/admin/views/doc.py:282
+#: contrib/admin/views/doc.py:296
msgid "Date (with time)"
msgstr ""
-#: contrib/admin/views/doc.py:283
+#: contrib/admin/views/doc.py:297
msgid "E-mail address"
msgstr ""
-#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
+#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:302
msgid "File path"
msgstr ""
-#: contrib/admin/views/doc.py:285
+#: contrib/admin/views/doc.py:300
msgid "Decimal number"
msgstr ""
-#: contrib/admin/views/doc.py:291
+#: contrib/admin/views/doc.py:306
msgid "Boolean (Either True, False or None)"
msgstr ""
-#: contrib/admin/views/doc.py:292
+#: contrib/admin/views/doc.py:307
msgid "Relation to parent model"
msgstr ""
-#: contrib/admin/views/doc.py:293
+#: contrib/admin/views/doc.py:308
msgid "Phone number"
msgstr ""
-#: contrib/admin/views/doc.py:298
+#: contrib/admin/views/doc.py:313
msgid "Text"
msgstr ""
-#: contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:314
msgid "Time"
msgstr ""
-#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
+#: contrib/admin/views/doc.py:315 contrib/flatpages/models.py:7
msgid "URL"
msgstr ""
-#: contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:316
msgid "U.S. state (two uppercase letters)"
msgstr ""
-#: contrib/admin/views/doc.py:302
+#: contrib/admin/views/doc.py:317
msgid "XML text"
msgstr ""
+#: contrib/admin/views/doc.py:343
+#, python-format
+msgid "%s does not appear to be a urlpattern object"
+msgstr ""
+
+#: contrib/admin/views/auth.py:28
+msgid "Add user"
+msgstr ""
+
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:3
@@ -613,7 +681,7 @@ msgstr ""
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:3
@@ -634,9 +702,10 @@ msgstr ""
#: contrib/admin/templates/admin/object_history.html:5
#: contrib/admin/templates/admin/500.html:4
#: contrib/admin/templates/admin/change_list.html:6
-#: contrib/admin/templates/admin/base.html:28
+#: contrib/admin/templates/admin/base.html:30
#: contrib/admin/templates/admin/delete_confirmation.html:6
#: contrib/admin/templates/admin/change_form.html:13
+#: contrib/admin/templates/admin/invalid_setup.html:4
#: contrib/admin/templates/registration/password_change_done.html:4
#: contrib/admin/templates/registration/password_reset_form.html:4
#: contrib/admin/templates/registration/logged_out.html:4
@@ -713,6 +782,11 @@ msgstr ""
msgid "Models available in the %(name)s application."
msgstr ""
+#: contrib/admin/templates/admin/index.html:18
+#, python-format
+msgid "%(name)s"
+msgstr ""
+
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
msgid "Add"
@@ -747,7 +821,7 @@ msgstr ""
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr ""
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
msgid "Welcome,"
msgstr ""
@@ -759,16 +833,16 @@ msgstr ""
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
msgid ""
-"Deleting the %(object_name)s '%(object)s' would result in deleting related "
-"objects, but your account doesn't have permission to delete the following "
-"types of objects:"
+"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
+"related objects, but your account doesn't have permission to delete the "
+"following types of objects:"
msgstr ""
#: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format
msgid ""
-"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
-"the following related items will be deleted:"
+"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
+"All of the following related items will be deleted:"
msgstr ""
#: contrib/admin/templates/admin/delete_confirmation.html:26
@@ -777,13 +851,33 @@ msgstr ""
#: contrib/admin/templates/admin/filter.html:2
#, python-format
-msgid " By %(title)s "
+msgid " By %(filter_title)s "
msgstr ""
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
msgstr ""
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "1 result"
+msgid_plural "%(counter)s results"
+msgstr[0] ""
+msgstr[1] ""
+
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "%(full_result_count)s total"
+msgstr ""
+
+#: contrib/admin/templates/admin/pagination.html:10
+msgid "Show all"
+msgstr ""
+
+#: contrib/admin/templates/admin/filters.html:4
+msgid "Filter"
+msgstr ""
+
#: contrib/admin/templates/admin/change_form.html:21
msgid "View on site"
msgstr ""
@@ -818,6 +912,35 @@ msgstr ""
msgid "Save"
msgstr ""
+#: contrib/admin/templates/admin/invalid_setup.html:8
+msgid ""
+"Something's wrong with your database installation. Make sure the appropriate "
+"database tables have been created, and make sure the database is readable by "
+"the appropriate user."
+msgstr ""
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:6
+msgid ""
+"First, enter a username and password. Then, you'll be able to edit more user "
+"options."
+msgstr ""
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:12
+msgid "Username"
+msgstr ""
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:18
+msgid "Password"
+msgstr ""
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:23
+msgid "Password (again)"
+msgstr ""
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:24
+msgid "Enter the same password as above, for verification."
+msgstr ""
+
#: contrib/admin/templates/registration/password_change_done.html:4
#: contrib/admin/templates/registration/password_change_form.html:4
#: contrib/admin/templates/registration/password_change_form.html:6
@@ -1018,11 +1141,11 @@ msgid ""
"'http://'."
msgstr ""
-#: contrib/redirects/models.py:12
+#: contrib/redirects/models.py:13
msgid "redirect"
msgstr ""
-#: contrib/redirects/models.py:13
+#: contrib/redirects/models.py:14
msgid "redirects"
msgstr ""
@@ -1049,8 +1172,8 @@ msgstr ""
#: contrib/flatpages/models.py:13
msgid ""
-"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
-"use 'flatpages/default'."
+"Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
+"will use 'flatpages/default.html'."
msgstr ""
#: contrib/flatpages/models.py:14
@@ -1069,151 +1192,177 @@ msgstr ""
msgid "flat pages"
msgstr ""
-#: contrib/auth/models.py:13 contrib/auth/models.py:26
+#: contrib/auth/views.py:39
+msgid "Logged out"
+msgstr ""
+
+#: contrib/auth/models.py:38 contrib/auth/models.py:57
msgid "name"
msgstr ""
-#: contrib/auth/models.py:15
+#: contrib/auth/models.py:40
msgid "codename"
msgstr ""
-#: contrib/auth/models.py:17
+#: contrib/auth/models.py:42
msgid "permission"
msgstr ""
-#: contrib/auth/models.py:18 contrib/auth/models.py:27
+#: contrib/auth/models.py:43 contrib/auth/models.py:58
msgid "permissions"
msgstr ""
-#: contrib/auth/models.py:29
+#: contrib/auth/models.py:60
msgid "group"
msgstr ""
-#: contrib/auth/models.py:30 contrib/auth/models.py:65
+#: contrib/auth/models.py:61 contrib/auth/models.py:100
msgid "groups"
msgstr ""
-#: contrib/auth/models.py:55
+#: contrib/auth/models.py:90
msgid "username"
msgstr ""
-#: contrib/auth/models.py:56
+#: contrib/auth/models.py:90
+msgid ""
+"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
+"digits and underscores)."
+msgstr ""
+
+#: contrib/auth/models.py:91
msgid "first name"
msgstr ""
-#: contrib/auth/models.py:57
+#: contrib/auth/models.py:92
msgid "last name"
msgstr ""
-#: contrib/auth/models.py:58
+#: contrib/auth/models.py:93
msgid "e-mail address"
msgstr ""
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "password"
msgstr ""
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "Use '[algo]$[salt]$[hexdigest]'"
msgstr ""
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "staff status"
msgstr ""
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "Designates whether the user can log into this admin site."
msgstr ""
-#: contrib/auth/models.py:61
+#: contrib/auth/models.py:96
msgid "active"
msgstr ""
-#: contrib/auth/models.py:62
+#: contrib/auth/models.py:96
+msgid ""
+"Designates whether this user can log into the Django admin. Unselect this "
+"instead of deleting accounts."
+msgstr ""
+
+#: contrib/auth/models.py:97
msgid "superuser status"
msgstr ""
-#: contrib/auth/models.py:63
+#: contrib/auth/models.py:97
+msgid ""
+"Designates that this user has all permissions without explicitly assigning "
+"them."
+msgstr ""
+
+#: contrib/auth/models.py:98
msgid "last login"
msgstr ""
-#: contrib/auth/models.py:64
+#: contrib/auth/models.py:99
msgid "date joined"
msgstr ""
-#: contrib/auth/models.py:66
+#: contrib/auth/models.py:101
msgid ""
"In addition to the permissions manually assigned, this user will also get "
"all permissions granted to each group he/she is in."
msgstr ""
-#: contrib/auth/models.py:67
+#: contrib/auth/models.py:102
msgid "user permissions"
msgstr ""
-#: contrib/auth/models.py:70
+#: contrib/auth/models.py:105
msgid "user"
msgstr ""
-#: contrib/auth/models.py:71
+#: contrib/auth/models.py:106
msgid "users"
msgstr ""
-#: contrib/auth/models.py:76
+#: contrib/auth/models.py:111
msgid "Personal info"
msgstr ""
-#: contrib/auth/models.py:77
+#: contrib/auth/models.py:112
msgid "Permissions"
msgstr ""
-#: contrib/auth/models.py:78
+#: contrib/auth/models.py:113
msgid "Important dates"
msgstr ""
-#: contrib/auth/models.py:79
+#: contrib/auth/models.py:114
msgid "Groups"
msgstr ""
-#: contrib/auth/models.py:219
+#: contrib/auth/models.py:256
msgid "message"
msgstr ""
-#: contrib/auth/forms.py:30
+#: contrib/auth/forms.py:52
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in."
msgstr ""
-#: contrib/contenttypes/models.py:25
+#: contrib/auth/forms.py:61
+msgid "This account is inactive."
+msgstr ""
+
+#: contrib/contenttypes/models.py:20
msgid "python model class name"
msgstr ""
-#: contrib/contenttypes/models.py:28
+#: contrib/contenttypes/models.py:23
msgid "content type"
msgstr ""
-#: contrib/contenttypes/models.py:29
+#: contrib/contenttypes/models.py:24
msgid "content types"
msgstr ""
-#: contrib/sessions/models.py:35
+#: contrib/sessions/models.py:51
msgid "session key"
msgstr ""
-#: contrib/sessions/models.py:36
+#: contrib/sessions/models.py:52
msgid "session data"
msgstr ""
-#: contrib/sessions/models.py:37
+#: contrib/sessions/models.py:53
msgid "expire date"
msgstr ""
-#: contrib/sessions/models.py:41
+#: contrib/sessions/models.py:57
msgid "session"
msgstr ""
-#: contrib/sessions/models.py:42
+#: contrib/sessions/models.py:58
msgid "sessions"
msgstr ""
@@ -1233,18 +1382,6 @@ msgstr ""
msgid "sites"
msgstr ""
-#: utils/translation.py:360
-msgid "DATE_FORMAT"
-msgstr "N j, Y"
-
-#: utils/translation.py:361
-msgid "DATETIME_FORMAT"
-msgstr "N j, Y, P"
-
-#: utils/translation.py:362
-msgid "TIME_FORMAT"
-msgstr "P"
-
#: utils/dates.py:6
msgid "Monday"
msgstr ""
@@ -1433,275 +1570,332 @@ msgid_plural "minutes"
msgstr[0] ""
msgstr[1] ""
-#: conf/global_settings.py:37
+#: utils/translation/trans_real.py:362
+msgid "DATE_FORMAT"
+msgstr "N j, Y"
+
+#: utils/translation/trans_real.py:363
+msgid "DATETIME_FORMAT"
+msgstr "N j, Y, P"
+
+#: utils/translation/trans_real.py:364
+msgid "TIME_FORMAT"
+msgstr "P"
+
+#: utils/translation/trans_real.py:380
+msgid "YEAR_MONTH_FORMAT"
+msgstr "F Y"
+
+#: utils/translation/trans_real.py:381
+msgid "MONTH_DAY_FORMAT"
+msgstr "F j"
+
+#: conf/global_settings.py:39
+msgid "Arabic"
+msgstr ""
+
+#: conf/global_settings.py:40
msgid "Bengali"
msgstr ""
-#: conf/global_settings.py:38
+#: conf/global_settings.py:41
msgid "Czech"
msgstr ""
-#: conf/global_settings.py:39
+#: conf/global_settings.py:42
msgid "Welsh"
msgstr ""
-#: conf/global_settings.py:40
+#: conf/global_settings.py:43
msgid "Danish"
msgstr ""
-#: conf/global_settings.py:41
+#: conf/global_settings.py:44
msgid "German"
msgstr ""
-#: conf/global_settings.py:42
+#: conf/global_settings.py:45
msgid "Greek"
msgstr ""
-#: conf/global_settings.py:43
+#: conf/global_settings.py:46
msgid "English"
msgstr ""
-#: conf/global_settings.py:44
+#: conf/global_settings.py:47
msgid "Spanish"
msgstr ""
-#: conf/global_settings.py:45
+#: conf/global_settings.py:48
+msgid "Argentinean Spanish"
+msgstr ""
+
+#: conf/global_settings.py:49
+msgid "Finnish"
+msgstr ""
+
+#: conf/global_settings.py:50
msgid "French"
msgstr ""
-#: conf/global_settings.py:46
+#: conf/global_settings.py:51
msgid "Galician"
msgstr ""
-#: conf/global_settings.py:47
+#: conf/global_settings.py:52
msgid "Hungarian"
msgstr ""
-#: conf/global_settings.py:48
+#: conf/global_settings.py:53
msgid "Hebrew"
msgstr ""
-#: conf/global_settings.py:49
+#: conf/global_settings.py:54
msgid "Icelandic"
msgstr ""
-#: conf/global_settings.py:50
+#: conf/global_settings.py:55
msgid "Italian"
msgstr ""
-#: conf/global_settings.py:51
+#: conf/global_settings.py:56
msgid "Japanese"
msgstr ""
-#: conf/global_settings.py:52
+#: conf/global_settings.py:57
msgid "Dutch"
msgstr ""
-#: conf/global_settings.py:53
+#: conf/global_settings.py:58
msgid "Norwegian"
msgstr ""
-#: conf/global_settings.py:54
+#: conf/global_settings.py:59
msgid "Brazilian"
msgstr ""
-#: conf/global_settings.py:55
+#: conf/global_settings.py:60
msgid "Romanian"
msgstr ""
-#: conf/global_settings.py:56
+#: conf/global_settings.py:61
msgid "Russian"
msgstr ""
-#: conf/global_settings.py:57
+#: conf/global_settings.py:62
msgid "Slovak"
msgstr ""
-#: conf/global_settings.py:58
+#: conf/global_settings.py:63
msgid "Slovenian"
msgstr ""
-#: conf/global_settings.py:59
+#: conf/global_settings.py:64
msgid "Serbian"
msgstr ""
-#: conf/global_settings.py:60
+#: conf/global_settings.py:65
msgid "Swedish"
msgstr ""
-#: conf/global_settings.py:61
+#: conf/global_settings.py:66
+msgid "Tamil"
+msgstr ""
+
+#: conf/global_settings.py:67
+msgid "Turkish"
+msgstr ""
+
+#: conf/global_settings.py:68
msgid "Ukrainian"
msgstr ""
-#: conf/global_settings.py:62
+#: conf/global_settings.py:69
msgid "Simplified Chinese"
msgstr ""
-#: conf/global_settings.py:63
+#: conf/global_settings.py:70
msgid "Traditional Chinese"
msgstr ""
-#: core/validators.py:60
+#: core/validators.py:63
msgid "This value must contain only letters, numbers and underscores."
msgstr ""
-#: core/validators.py:64
+#: core/validators.py:67
msgid ""
"This value must contain only letters, numbers, underscores, dashes or "
"slashes."
msgstr ""
-#: core/validators.py:72
+#: core/validators.py:71
+msgid "This value must contain only letters, numbers, underscores or hyphens."
+msgstr ""
+
+#: core/validators.py:75
msgid "Uppercase letters are not allowed here."
msgstr ""
-#: core/validators.py:76
+#: core/validators.py:79
msgid "Lowercase letters are not allowed here."
msgstr ""
-#: core/validators.py:83
+#: core/validators.py:86
msgid "Enter only digits separated by commas."
msgstr ""
-#: core/validators.py:95
+#: core/validators.py:98
msgid "Enter valid e-mail addresses separated by commas."
msgstr ""
-#: core/validators.py:99
+#: core/validators.py:102
msgid "Please enter a valid IP address."
msgstr ""
-#: core/validators.py:103
+#: core/validators.py:106
msgid "Empty values are not allowed here."
msgstr ""
-#: core/validators.py:107
+#: core/validators.py:110
msgid "Non-numeric characters aren't allowed here."
msgstr ""
-#: core/validators.py:111
+#: core/validators.py:114
msgid "This value can't be comprised solely of digits."
msgstr ""
-#: core/validators.py:116
+#: core/validators.py:119
msgid "Enter a whole number."
msgstr ""
-#: core/validators.py:120
+#: core/validators.py:123
msgid "Only alphabetical characters are allowed here."
msgstr ""
-#: core/validators.py:124
+#: core/validators.py:138
+msgid "Year must be 1900 or later."
+msgstr ""
+
+#: core/validators.py:142
+#, python-format
+msgid "Invalid date: %s."
+msgstr ""
+
+#: core/validators.py:146 db/models/fields/__init__.py:415
msgid "Enter a valid date in YYYY-MM-DD format."
msgstr ""
-#: core/validators.py:128
+#: core/validators.py:151
msgid "Enter a valid time in HH:MM format."
msgstr ""
-#: core/validators.py:132 db/models/fields/__init__.py:468
+#: core/validators.py:155 db/models/fields/__init__.py:477
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr ""
-#: core/validators.py:136
+#: core/validators.py:160
msgid "Enter a valid e-mail address."
msgstr ""
-#: core/validators.py:148
+#: core/validators.py:172 core/validators.py:401 forms/__init__.py:661
+msgid "No file was submitted. Check the encoding type on the form."
+msgstr ""
+
+#: core/validators.py:176
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
msgstr ""
-#: core/validators.py:155
+#: core/validators.py:183
#, python-format
msgid "The URL %s does not point to a valid image."
msgstr ""
-#: core/validators.py:159
+#: core/validators.py:187
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr ""
-#: core/validators.py:167
+#: core/validators.py:195
#, python-format
msgid "The URL %s does not point to a valid QuickTime video."
msgstr ""
-#: core/validators.py:171
+#: core/validators.py:199
msgid "A valid URL is required."
msgstr ""
-#: core/validators.py:185
+#: core/validators.py:213
#, python-format
msgid ""
"Valid HTML is required. Specific errors are:\n"
"%s"
msgstr ""
-#: core/validators.py:192
+#: core/validators.py:220
#, python-format
msgid "Badly formed XML: %s"
msgstr ""
-#: core/validators.py:202
+#: core/validators.py:230
#, python-format
msgid "Invalid URL: %s"
msgstr ""
-#: core/validators.py:206 core/validators.py:208
+#: core/validators.py:234 core/validators.py:236
#, python-format
msgid "The URL %s is a broken link."
msgstr ""
-#: core/validators.py:214
+#: core/validators.py:242
msgid "Enter a valid U.S. state abbreviation."
msgstr ""
-#: core/validators.py:229
+#: core/validators.py:256
#, python-format
msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] ""
msgstr[1] ""
-#: core/validators.py:236
+#: core/validators.py:263
#, python-format
msgid "This field must match the '%s' field."
msgstr ""
-#: core/validators.py:255
+#: core/validators.py:282
msgid "Please enter something for at least one field."
msgstr ""
-#: core/validators.py:264 core/validators.py:275
+#: core/validators.py:291 core/validators.py:302
msgid "Please enter both fields or leave them both empty."
msgstr ""
-#: core/validators.py:282
+#: core/validators.py:309
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
msgstr ""
-#: core/validators.py:294
+#: core/validators.py:321
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
msgstr ""
-#: core/validators.py:313
+#: core/validators.py:340
msgid "Duplicate values are not allowed."
msgstr ""
-#: core/validators.py:336
+#: core/validators.py:363
#, python-format
msgid "This value must be a power of %s."
msgstr ""
-#: core/validators.py:347
+#: core/validators.py:374
msgid "Please enter a valid decimal number."
msgstr ""
-#: core/validators.py:349
+#: core/validators.py:378
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
@@ -1709,7 +1903,16 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
-#: core/validators.py:352
+#: core/validators.py:381
+#, python-format
+msgid ""
+"Please enter a valid decimal number with a whole part of at most %s digit."
+msgid_plural ""
+"Please enter a valid decimal number with a whole part of at most %s digits."
+msgstr[0] ""
+msgstr[1] ""
+
+#: core/validators.py:384
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
@@ -1717,77 +1920,92 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
-#: core/validators.py:362
+#: core/validators.py:394
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr ""
-#: core/validators.py:363
+#: core/validators.py:395
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr ""
-#: core/validators.py:376
+#: core/validators.py:412
msgid "The format for this field is wrong."
msgstr ""
-#: core/validators.py:391
+#: core/validators.py:427
msgid "This field is invalid."
msgstr ""
-#: core/validators.py:426
+#: core/validators.py:463
#, python-format
msgid "Could not retrieve anything from %s."
msgstr ""
-#: core/validators.py:429
+#: core/validators.py:466
#, python-format
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr ""
-#: core/validators.py:462
+#: core/validators.py:499
#, python-format
msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
"\"%(start)s\".)"
msgstr ""
-#: core/validators.py:466
+#: core/validators.py:503
#, python-format
msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line "
"starts with \"%(start)s\".)"
msgstr ""
-#: core/validators.py:471
+#: core/validators.py:508
#, python-format
msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
"(start)s\".)"
msgstr ""
-#: core/validators.py:476
+#: core/validators.py:513
#, python-format
msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
"(start)s\".)"
msgstr ""
-#: core/validators.py:480
+#: core/validators.py:517
#, python-format
msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line "
"starts with \"%(start)s\".)"
msgstr ""
-#: core/validators.py:485
+#: core/validators.py:522
#, python-format
msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
"starts with \"%(start)s\".)"
msgstr ""
+#: views/generic/create_update.py:43
+#, python-format
+msgid "The %(verbose_name)s was created successfully."
+msgstr ""
+
+#: views/generic/create_update.py:117
+#, python-format
+msgid "The %(verbose_name)s was updated successfully."
+msgstr ""
+
+#: views/generic/create_update.py:184
+#, python-format
+msgid "The %(verbose_name)s was deleted."
+msgstr ""
+
#: db/models/manipulators.py:302
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
@@ -1799,42 +2017,42 @@ msgid "%(optname)s with this %(fieldname)s already exists."
msgstr ""
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
-#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
+#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562
#: forms/__init__.py:346
msgid "This field is required."
msgstr ""
-#: db/models/fields/__init__.py:337
+#: db/models/fields/__init__.py:340
msgid "This value must be an integer."
msgstr ""
-#: db/models/fields/__init__.py:369
+#: db/models/fields/__init__.py:372
msgid "This value must be either True or False."
msgstr ""
-#: db/models/fields/__init__.py:385
+#: db/models/fields/__init__.py:388
msgid "This field cannot be null."
msgstr ""
-#: db/models/fields/__init__.py:562
+#: db/models/fields/__init__.py:571
msgid "Enter a valid filename."
msgstr ""
-#: db/models/fields/related.py:43
+#: db/models/fields/related.py:51
#, python-format
msgid "Please enter a valid %s."
msgstr ""
-#: db/models/fields/related.py:579
+#: db/models/fields/related.py:618
msgid "Separate multiple IDs with commas."
msgstr ""
-#: db/models/fields/related.py:581
+#: db/models/fields/related.py:620
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
-#: db/models/fields/related.py:625
+#: db/models/fields/related.py:664
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
msgid_plural ""
@@ -1842,38 +2060,38 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
-#: forms/__init__.py:380
+#: forms/__init__.py:381
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
msgstr[0] ""
msgstr[1] ""
-#: forms/__init__.py:385
+#: forms/__init__.py:386
msgid "Line breaks are not allowed here."
msgstr ""
-#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
+#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr ""
-#: forms/__init__.py:645
+#: forms/__init__.py:663
msgid "The submitted file is empty."
msgstr ""
-#: forms/__init__.py:699
+#: forms/__init__.py:719
msgid "Enter a whole number between -32,768 and 32,767."
msgstr ""
-#: forms/__init__.py:708
+#: forms/__init__.py:729
msgid "Enter a positive number."
msgstr ""
-#: forms/__init__.py:717
+#: forms/__init__.py:739
msgid "Enter a whole number between 0 and 32,767."
msgstr ""
-#: template/defaultfilters.py:379
+#: template/defaultfilters.py:401
msgid "yes,no,maybe"
msgstr ""
diff --git a/django/conf/locale/es_AR/LC_MESSAGES/django.mo b/django/conf/locale/es_AR/LC_MESSAGES/django.mo
index f550fca3db..dd96bf99ce 100644
--- a/django/conf/locale/es_AR/LC_MESSAGES/django.mo
+++ b/django/conf/locale/es_AR/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/es_AR/LC_MESSAGES/django.po b/django/conf/locale/es_AR/LC_MESSAGES/django.po
index 8af7c42e5e..e5169e9c4a 100644
--- a/django/conf/locale/es_AR/LC_MESSAGES/django.po
+++ b/django/conf/locale/es_AR/LC_MESSAGES/django.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-06-19 11:19-0300\n"
-"PO-Revision-Date: 2006-05-16 10:05-0300\n"
+"POT-Creation-Date: 2006-08-18 18:57-0300\n"
+"PO-Revision-Date: 2006-08-21 18:06-0300\n"
"Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
@@ -17,15 +17,15 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: contrib/contenttypes/models.py:25
+#: contrib/contenttypes/models.py:20
msgid "python model class name"
msgstr "nombre de la clase python del modelo"
-#: contrib/contenttypes/models.py:28
+#: contrib/contenttypes/models.py:23
msgid "content type"
msgstr "tipo de contenido"
-#: contrib/contenttypes/models.py:29
+#: contrib/contenttypes/models.py:24
msgid "content types"
msgstr "tipos de contenido"
@@ -33,79 +33,103 @@ msgstr "tipos de contenido"
msgid "Logged out"
msgstr "Sesión cerrada"
-#: contrib/auth/models.py:13 contrib/auth/models.py:26
+#: contrib/auth/models.py:38 contrib/auth/models.py:57
msgid "name"
msgstr "nombre"
-#: contrib/auth/models.py:15
+#: contrib/auth/models.py:40
msgid "codename"
msgstr "nombre en código"
-#: contrib/auth/models.py:17
+#: contrib/auth/models.py:42
msgid "permission"
msgstr "permiso"
-#: contrib/auth/models.py:18 contrib/auth/models.py:27
+#: contrib/auth/models.py:43 contrib/auth/models.py:58
msgid "permissions"
msgstr "permisos"
-#: contrib/auth/models.py:29
+#: contrib/auth/models.py:60
msgid "group"
msgstr "grupo"
-#: contrib/auth/models.py:30 contrib/auth/models.py:65
+#: contrib/auth/models.py:61 contrib/auth/models.py:100
msgid "groups"
msgstr "grupos"
-#: contrib/auth/models.py:55
+#: contrib/auth/models.py:90
msgid "username"
msgstr "nombre de usuario"
-#: contrib/auth/models.py:56
+#: contrib/auth/models.py:90
+msgid ""
+"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
+"digits and underscores)."
+msgstr ""
+"Requerido. Longitud máxima 30 caracteres alfanuméricos (letras, dígitos y "
+"guiones bajos)."
+
+#: contrib/auth/models.py:91
msgid "first name"
msgstr "nombre"
-#: contrib/auth/models.py:57
+#: contrib/auth/models.py:92
msgid "last name"
msgstr "apellido"
-#: contrib/auth/models.py:58
+#: contrib/auth/models.py:93
msgid "e-mail address"
msgstr "dirección de correo"
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "password"
msgstr "contraseña"
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "Use '[algo]$[salt]$[hexdigest]'"
msgstr "Use '[algoritmo]$[salt]$[hexdigest]'"
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "staff status"
msgstr "es staff"
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "Designates whether the user can log into this admin site."
msgstr "Indica si el usuario puede ingresar a este sitio de administración."
-#: contrib/auth/models.py:61
+#: contrib/auth/models.py:96
msgid "active"
msgstr "activo"
-#: contrib/auth/models.py:62
+#: contrib/auth/models.py:96
+msgid ""
+"Designates whether this user can log into the Django admin. Unselect this "
+"instead of deleting accounts."
+msgstr ""
+"Indica si el usuario puede ingresar al sitio de administración Django."
+"Desactive este campo en lugar de eliminar usuarios."
+
+#: contrib/auth/models.py:97
msgid "superuser status"
msgstr "es superusuario"
-#: contrib/auth/models.py:63
+#: contrib/auth/models.py:97
+msgid ""
+"Designates that this user has all permissions without explicitly assigning "
+"them."
+msgstr ""
+"Indica que este usuario posee todos los permisos, sin asignarle los mismos "
+"explícitamente."
+
+#: contrib/auth/models.py:98
msgid "last login"
msgstr "último registro"
-#: contrib/auth/models.py:64
+#: contrib/auth/models.py:99
msgid "date joined"
msgstr "fecha de creación"
-#: contrib/auth/models.py:66
+#: contrib/auth/models.py:101
msgid ""
"In addition to the permissions manually assigned, this user will also get "
"all permissions granted to each group he/she is in."
@@ -113,39 +137,39 @@ msgstr ""
"Además de los permisos asignados manualmente, este usuario también poseerá "
"todos los permisos de los grupos a los que pertenezca."
-#: contrib/auth/models.py:67
+#: contrib/auth/models.py:102
msgid "user permissions"
msgstr "permisos de usuario"
-#: contrib/auth/models.py:70
+#: contrib/auth/models.py:105
msgid "user"
msgstr "usuario"
-#: contrib/auth/models.py:71
+#: contrib/auth/models.py:106
msgid "users"
msgstr "usuarios"
-#: contrib/auth/models.py:76
+#: contrib/auth/models.py:111
msgid "Personal info"
msgstr "Información personal"
-#: contrib/auth/models.py:77
+#: contrib/auth/models.py:112
msgid "Permissions"
msgstr "Permisos"
-#: contrib/auth/models.py:78
+#: contrib/auth/models.py:113
msgid "Important dates"
msgstr "Fechas importantes"
-#: contrib/auth/models.py:79
+#: contrib/auth/models.py:114
msgid "Groups"
msgstr "Grupos"
-#: contrib/auth/models.py:219
+#: contrib/auth/models.py:256
msgid "message"
msgstr "mensaje"
-#: contrib/auth/forms.py:30
+#: contrib/auth/forms.py:52
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in."
@@ -153,8 +177,7 @@ msgstr ""
"Su navegador Web aparenta no tener cookies activas. Las cookies son un "
"requerimiento para poder ingresar."
-#: contrib/auth/forms.py:36 contrib/auth/forms.py:43
-#: contrib/admin/views/decorators.py:9
+#: contrib/auth/forms.py:59 contrib/admin/views/decorators.py:10
msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
@@ -162,7 +185,7 @@ msgstr ""
"Por favor ingrese un nombre de usuario y una contraseña correctos. Note que "
"ambos campos son sensibles a mayúsculas/minúsculas."
-#: contrib/auth/forms.py:45
+#: contrib/auth/forms.py:61
msgid "This account is inactive."
msgstr "Esta cuenta está inactiva"
@@ -255,7 +278,7 @@ msgstr "fecha/hora de envío"
msgid "is public"
msgstr "es público"
-#: contrib/comments/models.py:85 contrib/admin/views/doc.py:292
+#: contrib/comments/models.py:85 contrib/admin/views/doc.py:304
msgid "IP address"
msgstr "Dirección IP"
@@ -392,12 +415,12 @@ msgstr "ID de comentario no válido"
msgid "No voting for yourself"
msgstr "No puedes votarte tú mismo"
-#: contrib/comments/views/comments.py:28
+#: contrib/comments/views/comments.py:27
msgid ""
"This rating is required because you've entered at least one other rating."
msgstr "Se precisa esta puntuación porque ha introducido al menos otra más."
-#: contrib/comments/views/comments.py:112
+#: contrib/comments/views/comments.py:111
#, python-format
msgid ""
"This comment was posted by a user who has posted fewer than %(count)s "
@@ -420,7 +443,7 @@ msgstr[1] ""
"\n"
"%(text)s"
-#: contrib/comments/views/comments.py:117
+#: contrib/comments/views/comments.py:116
#, fuzzy, python-format
msgid ""
"This comment was posted by a sketchy user:\n"
@@ -431,24 +454,24 @@ msgstr ""
"\n"
"%(text)s"
-#: contrib/comments/views/comments.py:189
+#: contrib/comments/views/comments.py:188
#: contrib/comments/views/comments.py:280
msgid "Only POSTs are allowed"
msgstr "Sólo se admiten POSTs"
-#: contrib/comments/views/comments.py:193
+#: contrib/comments/views/comments.py:192
#: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted"
msgstr "No se proporcionó uno o más de los siguientes campos requeridos"
-#: contrib/comments/views/comments.py:197
+#: contrib/comments/views/comments.py:196
#: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)"
msgstr ""
"Alguien está jugando con el formulario de comentarios (violación de "
"seguridad)"
-#: contrib/comments/views/comments.py:207
+#: contrib/comments/views/comments.py:206
#: contrib/comments/views/comments.py:292
msgid ""
"The comment form had an invalid 'target' parameter -- the object ID was "
@@ -467,12 +490,12 @@ msgid "Your name:"
msgstr "Su nombre:"
#: contrib/comments/templates/comments/freeform.html:5
-#: contrib/comments/templates/comments/form.html:27
+#: contrib/comments/templates/comments/form.html:28
msgid "Comment:"
msgstr "Comentario:"
-#: contrib/comments/templates/comments/freeform.html:9
-#: contrib/comments/templates/comments/form.html:32
+#: contrib/comments/templates/comments/freeform.html:10
+#: contrib/comments/templates/comments/form.html:35
msgid "Preview comment"
msgstr "Previsualizar comentario"
@@ -483,19 +506,10 @@ msgid "Username:"
msgstr "Usuario:"
#: contrib/comments/templates/comments/form.html:6
-#: contrib/admin/templates/admin/login.html:20
-msgid "Password:"
-msgstr "Contraseña:"
-
-#: contrib/comments/templates/comments/form.html:6
-msgid "Forgotten your password?"
-msgstr "Olvidó su contraseña?"
-
-#: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
#: contrib/admin/templates/admin/change_form.html:10
-#: contrib/admin/templates/admin/base.html:24
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/registration/password_change_done.html:3
#: contrib/admin/templates/registration/password_change_form.html:3
@@ -512,6 +526,15 @@ msgstr "Olvidó su contraseña?"
msgid "Log out"
msgstr "Cerrar sesión"
+#: contrib/comments/templates/comments/form.html:8
+#: contrib/admin/templates/admin/login.html:20
+msgid "Password:"
+msgstr "Contraseña:"
+
+#: contrib/comments/templates/comments/form.html:8
+msgid "Forgotten your password?"
+msgstr "Olvidó su contraseña?"
+
#: contrib/comments/templates/comments/form.html:12
msgid "Ratings"
msgstr "Calificaciones"
@@ -530,7 +553,7 @@ msgstr "Opcional"
msgid "Post a photo"
msgstr "Enviar una foto"
-#: contrib/flatpages/models.py:7 contrib/admin/views/doc.py:303
+#: contrib/flatpages/models.py:7 contrib/admin/views/doc.py:315
msgid "URL"
msgstr "URL"
@@ -559,11 +582,11 @@ msgstr "nombre de plantilla"
#: contrib/flatpages/models.py:13
msgid ""
-"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
-"use 'flatpages/default'."
+"Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
+"will use 'flatpages/default.html'."
msgstr ""
-"Ejemplo: 'flatpages/contact_page'. Si no lo proporciona, el sistema usará "
-"'flatpages/default'."
+"Ejemplo: 'flatpages/contact_page.html'. Si no lo proporciona, el sistema "
+"usará 'flatpages/default.html'."
#: contrib/flatpages/models.py:14
msgid "registration required"
@@ -581,23 +604,23 @@ msgstr "página estática"
msgid "flat pages"
msgstr "páginas estáticas"
-#: contrib/sessions/models.py:35
+#: contrib/sessions/models.py:51
msgid "session key"
msgstr "clave de sesión"
-#: contrib/sessions/models.py:36
+#: contrib/sessions/models.py:52
msgid "session data"
msgstr "datos de sesión"
-#: contrib/sessions/models.py:37
+#: contrib/sessions/models.py:53
msgid "expire date"
msgstr "fecha de caducidad"
-#: contrib/sessions/models.py:41
+#: contrib/sessions/models.py:57
msgid "session"
msgstr "sesión"
-#: contrib/sessions/models.py:42
+#: contrib/sessions/models.py:58
msgid "sessions"
msgstr "sesiones"
@@ -695,12 +718,12 @@ msgstr "entradas de registro"
msgid "All dates"
msgstr "Todas las fechas"
-#: contrib/admin/views/decorators.py:23
+#: contrib/admin/views/decorators.py:24
#: contrib/admin/templates/admin/login.html:25
msgid "Log in"
msgstr "Identificarse"
-#: contrib/admin/views/decorators.py:61
+#: contrib/admin/views/decorators.py:62
msgid ""
"Please log in again, because your session has expired. Don't worry: Your "
"submission has been saved."
@@ -708,7 +731,7 @@ msgstr ""
"Por favor, identifíquese de nuevo porque su sesión ha caducado. No se "
"preocupe: se ha guardado su envío."
-#: contrib/admin/views/decorators.py:68
+#: contrib/admin/views/decorators.py:69
msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
@@ -716,187 +739,253 @@ msgstr ""
"Parece que su navegador no está configurado para aceptar cookies. Actívelas "
"por favor, recargue esta página, e inténtelo de nuevo."
-#: contrib/admin/views/decorators.py:82
+#: contrib/admin/views/decorators.py:83
msgid "Usernames cannot contain the '@' character."
msgstr "Los nombres de usuario no pueden contener el carácter '@'."
-#: contrib/admin/views/decorators.py:84
+#: contrib/admin/views/decorators.py:85
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
msgstr ""
"Su dirección de correo no es su nombre de usuario. Pruebe con '%s' en su "
"lugar."
-#: contrib/admin/views/main.py:226
+#: contrib/admin/views/main.py:223
msgid "Site administration"
msgstr "Sitio administrativo"
-#: contrib/admin/views/main.py:260
+#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:14
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
-msgstr "Se añadió con éxito el %(name)s \"%(obj)s\"."
+msgstr "Se agregó con éxito el %(name)s \"%(obj)s\"."
-#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
+#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347
+#: contrib/admin/views/auth.py:19
msgid "You may edit it again below."
-msgstr "Puede editarlo de nuevo abajo."
+msgstr "Puede modificarlo nuevamente abajo."
-#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
+#: contrib/admin/views/main.py:271 contrib/admin/views/main.py:356
#, python-format
msgid "You may add another %s below."
msgstr "Puede agregar otro %s abajo."
-#: contrib/admin/views/main.py:290
+#: contrib/admin/views/main.py:289
#, python-format
msgid "Add %s"
msgstr "Agregar %s"
-#: contrib/admin/views/main.py:336
+#: contrib/admin/views/main.py:335
#, python-format
msgid "Added %s."
msgstr "Agregado %s."
-#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
+#: contrib/admin/views/main.py:339
msgid "and"
msgstr "y"
-#: contrib/admin/views/main.py:338
+#: contrib/admin/views/main.py:337
#, python-format
msgid "Changed %s."
msgstr "Modifica %s."
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:339
#, python-format
msgid "Deleted %s."
msgstr "Elimina %s."
-#: contrib/admin/views/main.py:343
+#: contrib/admin/views/main.py:342
msgid "No fields changed."
-msgstr "No ha cambiado ningún campo."
+msgstr "No ha modificado ningún campo."
-#: contrib/admin/views/main.py:346
+#: contrib/admin/views/main.py:345
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr "Se modificó con éxito el %(name)s \"%(obj)s."
-#: contrib/admin/views/main.py:354
+#: contrib/admin/views/main.py:353
#, python-format
msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr ""
-"Se agregó con éxito el %(name)s \"%(obj)s. Puede editarlo de nuevo abajo."
+"Se agregó con éxito el %(name)s \"%(obj)s. Puede modificarlo nuevamente "
+"abajo."
-#: contrib/admin/views/main.py:392
+#: contrib/admin/views/main.py:391
#, python-format
msgid "Change %s"
msgstr "Modificar %s"
-#: contrib/admin/views/main.py:470
+#: contrib/admin/views/main.py:473
#, python-format
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
msgstr "Uno o más %(fieldname)s en %(name)s: %(obj)s"
-#: contrib/admin/views/main.py:475
+#: contrib/admin/views/main.py:478
#, python-format
msgid "One or more %(fieldname)s in %(name)s:"
msgstr "Uno o más %(fieldname)s en %(name)s:"
-#: contrib/admin/views/main.py:508
+#: contrib/admin/views/main.py:511
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "Se eliminó con éxito el %(name)s \"%(obj)s\"."
-#: contrib/admin/views/main.py:511
+#: contrib/admin/views/main.py:514
msgid "Are you sure?"
msgstr "¿Está seguro?"
-#: contrib/admin/views/main.py:533
+#: contrib/admin/views/main.py:536
#, python-format
msgid "Change history: %s"
msgstr "Historia de modificaciones: %s"
-#: contrib/admin/views/main.py:567
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s"
msgstr "Seleccione %s"
-#: contrib/admin/views/main.py:567
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s to change"
msgstr "Seleccione %s a modificar"
-#: contrib/admin/views/main.py:743
+#: contrib/admin/views/main.py:756
msgid "Database error"
msgstr "Error de base de datos"
-#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:289
-#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:297
-#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:300
+#: contrib/admin/views/doc.py:46 contrib/admin/views/doc.py:48
+#: contrib/admin/views/doc.py:50
+msgid "tag:"
+msgstr "etiqueta:"
+
+#: contrib/admin/views/doc.py:77 contrib/admin/views/doc.py:79
+#: contrib/admin/views/doc.py:81
+msgid "filter:"
+msgstr "Filtrar:"
+
+#: contrib/admin/views/doc.py:135 contrib/admin/views/doc.py:137
+#: contrib/admin/views/doc.py:139
+msgid "view:"
+msgstr "ver:"
+
+#: contrib/admin/views/doc.py:164
+#, python-format
+msgid "App %r not found"
+msgstr "App %r no encontrada"
+
+#: contrib/admin/views/doc.py:171
+#, python-format
+msgid "Model %r not found in app %r"
+msgstr "Modelo %r no encontrado en app %r"
+
+#: contrib/admin/views/doc.py:183
+#, python-format
+msgid "the related `%s.%s` object"
+msgstr "El objeto relacionado `%s.%s`"
+
+#: contrib/admin/views/doc.py:183 contrib/admin/views/doc.py:205
+#: contrib/admin/views/doc.py:219 contrib/admin/views/doc.py:224
+msgid "model:"
+msgstr "modelo:"
+
+#: contrib/admin/views/doc.py:214
+#, python-format
+msgid "related `%s.%s` objects"
+msgstr "objetos relacionados `%s.%s`"
+
+#: contrib/admin/views/doc.py:219
+#, python-format
+msgid "all %s"
+msgstr "todos %s"
+
+#: contrib/admin/views/doc.py:224
+#, python-format
+msgid "number of %s"
+msgstr "número de %s"
+
+#: contrib/admin/views/doc.py:229
+#, python-format
+msgid "Fields on %s objects"
+msgstr "Capos en %s objetos"
+
+#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:303 contrib/admin/views/doc.py:309
+#: contrib/admin/views/doc.py:310 contrib/admin/views/doc.py:312
msgid "Integer"
msgstr "Entero"
-#: contrib/admin/views/doc.py:280
+#: contrib/admin/views/doc.py:292
msgid "Boolean (Either True or False)"
msgstr "Booleano (Verdadero o Falso)"
-#: contrib/admin/views/doc.py:281 contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:311
#, python-format
msgid "String (up to %(maxlength)s)"
msgstr "Cadena (máximo %(maxlength)s)"
-#: contrib/admin/views/doc.py:282
+#: contrib/admin/views/doc.py:294
msgid "Comma-separated integers"
msgstr "Enteros separados por comas"
-#: contrib/admin/views/doc.py:283
+#: contrib/admin/views/doc.py:295
msgid "Date (without time)"
msgstr "Fecha (sin hora)"
-#: contrib/admin/views/doc.py:284
+#: contrib/admin/views/doc.py:296
msgid "Date (with time)"
msgstr "Fecha (con hora)"
-#: contrib/admin/views/doc.py:285
+#: contrib/admin/views/doc.py:297
msgid "E-mail address"
msgstr "Dirección de correo electrónico"
-#: contrib/admin/views/doc.py:286 contrib/admin/views/doc.py:287
-#: contrib/admin/views/doc.py:290
+#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:302
msgid "File path"
msgstr "Ruta de archivo"
-#: contrib/admin/views/doc.py:288
+#: contrib/admin/views/doc.py:300
msgid "Decimal number"
msgstr "Número decimal"
-#: contrib/admin/views/doc.py:294
+#: contrib/admin/views/doc.py:306
msgid "Boolean (Either True, False or None)"
msgstr "Booleano (Verdadero, Falso o Nulo)"
-#: contrib/admin/views/doc.py:295
+#: contrib/admin/views/doc.py:307
msgid "Relation to parent model"
msgstr "Relación con el modelo padre"
-#: contrib/admin/views/doc.py:296
+#: contrib/admin/views/doc.py:308
msgid "Phone number"
msgstr "Número de teléfono"
-#: contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:313
msgid "Text"
msgstr "Texto"
-#: contrib/admin/views/doc.py:302
+#: contrib/admin/views/doc.py:314
msgid "Time"
msgstr "Hora"
-#: contrib/admin/views/doc.py:304
+#: contrib/admin/views/doc.py:316
msgid "U.S. state (two uppercase letters)"
msgstr "Estado de los EEUU (dos letras mayúsculas)"
-#: contrib/admin/views/doc.py:305
+#: contrib/admin/views/doc.py:317
msgid "XML text"
msgstr "Texto XML"
+#: contrib/admin/views/doc.py:339
+#, python-format
+msgid "%s does not appear to be a urlpattern object"
+msgstr "%s no parece ser un objeto urlpattern"
+
+#: contrib/admin/views/auth.py:25
+msgid "Add user"
+msgstr "Agregar usuario"
+
#: contrib/admin/templates/widget/file.html:2
msgid "Currently:"
msgstr "Actualmente"
@@ -916,7 +1005,7 @@ msgstr "Hora:"
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
#: contrib/admin/templates/admin/change_form.html:10
-#: contrib/admin/templates/admin/base.html:24
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/registration/password_change_done.html:3
#: contrib/admin/templates/registration/password_change_form.html:3
@@ -927,7 +1016,7 @@ msgstr "Documentación"
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
#: contrib/admin/templates/admin/change_form.html:10
-#: contrib/admin/templates/admin/base.html:24
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/registration/password_change_done.html:3
#: contrib/admin/templates/registration/password_change_form.html:3
@@ -948,7 +1037,7 @@ msgstr "Cambiar contraseña"
#: contrib/admin/templates/admin/change_list.html:6
#: contrib/admin/templates/admin/500.html:4
#: contrib/admin/templates/admin/change_form.html:13
-#: contrib/admin/templates/admin/base.html:29
+#: contrib/admin/templates/admin/base.html:30
#: contrib/admin/templates/admin/delete_confirmation.html:6
#: contrib/admin/templates/admin/invalid_setup.html:4
#: contrib/admin/templates/registration/password_change_done.html:4
@@ -996,8 +1085,8 @@ msgstr "Agregar %(name)s"
#: contrib/admin/templates/admin/filter.html:2
#, python-format
-msgid " By %(title)s "
-msgstr " Por %(title)s "
+msgid " By %(filter_title)s "
+msgstr " Por %(filter_title)s "
#: contrib/admin/templates/admin/500.html:4
msgid "Server error"
@@ -1053,6 +1142,11 @@ msgstr "Administración de Django"
msgid "Models available in the %(name)s application."
msgstr "Modelos disponibles en la aplicación %(name)s."
+#: contrib/admin/templates/admin/index.html:18
+#, python-format
+msgid "%(name)s"
+msgstr "%(name)s"
+
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
msgid "Add"
@@ -1113,7 +1207,7 @@ msgstr "Ordenación"
msgid "Order:"
msgstr "Orden:"
-#: contrib/admin/templates/admin/base.html:24
+#: contrib/admin/templates/admin/base.html:25
msgid "Welcome,"
msgstr "Bienvenido,"
@@ -1125,22 +1219,22 @@ msgstr "Eliminar"
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
msgid ""
-"Deleting the %(object_name)s '%(object)s' would result in deleting related "
-"objects, but your account doesn't have permission to delete the following "
-"types of objects:"
+"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
+"related objects, but your account doesn't have permission to delete the "
+"following types of objects:"
msgstr ""
-"Eliminar el %(object_name)s '%(object)s' provocaría la eliminación de "
-"objetos relacionados, pero su cuenta no tiene permiso para eliminar los "
+"Eliminar el %(object_name)s '%(escaped_object)s' provocaría la eliminación "
+"de objetos relacionados, pero su cuenta no tiene permiso para eliminar los "
"siguientes tipos de objetos:"
#: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format
msgid ""
-"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
-"the following related items will be deleted:"
+"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
+"All of the following related items will be deleted:"
msgstr ""
-"¿Está seguro de que quiere eliminar los %(object_name)s \"%(object)s\"? Se "
-"eliminarán los siguientes objetos relacionados:"
+"¿Está seguro de que quiere eliminar los %(object_name)s \"%(escaped_object)s"
+"\"? Se eliminarán los siguientes objetos relacionados:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure"
@@ -1172,6 +1266,30 @@ msgstr ""
"tablas de la misma hayan sido creadas, y asegúrese de que el usuario "
"apropiado tenga permisos de escritura en la base de datos."
+#: contrib/admin/templates/admin/auth/user/add_form.html:6
+msgid ""
+"First, enter a username and password. Then, you'll be able to edit more user "
+"options."
+msgstr ""
+"Primero, ingrese un nombre de usuario y una contraseña. Luego podrá "
+"configurar opciones adicionales."
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:12
+msgid "Username"
+msgstr "Nombre de usuario:"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:18
+msgid "Password"
+msgstr "Contraseña:"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:23
+msgid "Password (again)"
+msgstr "Contraseña (de nuevo)"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:24
+msgid "Enter the same password as above, for verification."
+msgstr "Para verificación, ingrese la misma contraseña que ingresó arriba."
+
#: contrib/admin/templates/registration/password_change_done.html:4
#: contrib/admin/templates/registration/password_change_form.html:4
#: contrib/admin/templates/registration/password_change_form.html:6
@@ -1359,26 +1477,6 @@ msgid "As above, but opens the admin page in a new window."
msgstr ""
"Como antes, pero abre la página de administración en una nueva ventana."
-#: utils/translation.py:363
-msgid "DATE_FORMAT"
-msgstr "j N Y"
-
-#: utils/translation.py:364
-msgid "DATETIME_FORMAT"
-msgstr "j N Y P"
-
-#: utils/translation.py:365
-msgid "TIME_FORMAT"
-msgstr "P"
-
-#: utils/translation.py:381
-msgid "YEAR_MONTH_FORMAT"
-msgstr "F Y"
-
-#: utils/translation.py:382
-msgid "MONTH_DAY_FORMAT"
-msgstr "j \\de F"
-
#: utils/dates.py:6
msgid "Monday"
msgstr "Lunes"
@@ -1567,115 +1665,143 @@ msgid_plural "minutes"
msgstr[0] "minuto"
msgstr[1] "minutos"
-#: conf/global_settings.py:37
+#: utils/translation/trans_real.py:362
+msgid "DATE_FORMAT"
+msgstr "j N Y"
+
+#: utils/translation/trans_real.py:363
+msgid "DATETIME_FORMAT"
+msgstr "j N Y P"
+
+#: utils/translation/trans_real.py:364
+msgid "TIME_FORMAT"
+msgstr "P"
+
+#: utils/translation/trans_real.py:380
+msgid "YEAR_MONTH_FORMAT"
+msgstr "F Y"
+
+#: utils/translation/trans_real.py:381
+msgid "MONTH_DAY_FORMAT"
+msgstr "j \\de F"
+
+#: conf/global_settings.py:39
+msgid "Arabic"
+msgstr "Árabe"
+
+#: conf/global_settings.py:40
msgid "Bengali"
msgstr "Bengalí"
-#: conf/global_settings.py:38
+#: conf/global_settings.py:41
msgid "Czech"
msgstr "Checo"
-#: conf/global_settings.py:39
+#: conf/global_settings.py:42
msgid "Welsh"
msgstr "Galés"
-#: conf/global_settings.py:40
+#: conf/global_settings.py:43
msgid "Danish"
msgstr "Danés"
-#: conf/global_settings.py:41
+#: conf/global_settings.py:44
msgid "German"
msgstr "Alemán"
-#: conf/global_settings.py:42
+#: conf/global_settings.py:45
msgid "Greek"
msgstr "Griego"
-#: conf/global_settings.py:43
+#: conf/global_settings.py:46
msgid "English"
msgstr "Inglés"
-#: conf/global_settings.py:44
+#: conf/global_settings.py:47
msgid "Spanish"
msgstr "Español"
-#: conf/global_settings.py:45
+#: conf/global_settings.py:48
msgid "Argentinean Spanish"
msgstr "Español Argentino"
-#: conf/global_settings.py:46
+#: conf/global_settings.py:49
msgid "French"
msgstr "Francés"
-#: conf/global_settings.py:47
+#: conf/global_settings.py:50
msgid "Galician"
msgstr "Gallego"
-#: conf/global_settings.py:48
+#: conf/global_settings.py:51
msgid "Hungarian"
msgstr "Húngaro"
-#: conf/global_settings.py:49
+#: conf/global_settings.py:52
msgid "Hebrew"
msgstr "Hebreo"
-#: conf/global_settings.py:50
+#: conf/global_settings.py:53
msgid "Icelandic"
msgstr "Islandés"
-#: conf/global_settings.py:51
+#: conf/global_settings.py:54
msgid "Italian"
msgstr "Italiano"
-#: conf/global_settings.py:52
+#: conf/global_settings.py:55
msgid "Japanese"
msgstr "Japonés"
-#: conf/global_settings.py:53
+#: conf/global_settings.py:56
msgid "Dutch"
msgstr "Holandés"
-#: conf/global_settings.py:54
+#: conf/global_settings.py:57
msgid "Norwegian"
msgstr "Noruego"
-#: conf/global_settings.py:55
+#: conf/global_settings.py:58
msgid "Brazilian"
msgstr "Brasileño"
-#: conf/global_settings.py:56
+#: conf/global_settings.py:59
msgid "Romanian"
msgstr "Rumano"
-#: conf/global_settings.py:57
+#: conf/global_settings.py:60
msgid "Russian"
msgstr "Ruso"
-#: conf/global_settings.py:58
+#: conf/global_settings.py:61
msgid "Slovak"
msgstr "Eslovaco"
-#: conf/global_settings.py:59
+#: conf/global_settings.py:62
msgid "Slovenian"
msgstr "Esloveno"
-#: conf/global_settings.py:60
+#: conf/global_settings.py:63
msgid "Serbian"
msgstr "Serbio"
-#: conf/global_settings.py:61
+#: conf/global_settings.py:64
msgid "Swedish"
msgstr "Sueco"
-#: conf/global_settings.py:62
+#: conf/global_settings.py:65
+msgid "Tamil"
+msgstr "Tamil"
+
+#: conf/global_settings.py:66
msgid "Ukrainian"
msgstr "Ucraniano"
-#: conf/global_settings.py:63
+#: conf/global_settings.py:67
msgid "Simplified Chinese"
msgstr "Chino simplificado"
-#: conf/global_settings.py:64
+#: conf/global_settings.py:68
msgid "Traditional Chinese"
msgstr "Chino tradicional"
@@ -1691,47 +1817,51 @@ msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "Ya existe %(optname)s con este %(fieldname)s."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
-#: db/models/fields/__init__.py:545 db/models/fields/__init__.py:556
+#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562
#: forms/__init__.py:346
msgid "This field is required."
msgstr "Este campo es obligatorio."
-#: db/models/fields/__init__.py:337
+#: db/models/fields/__init__.py:340
msgid "This value must be an integer."
msgstr "Este valor debe ser un número entero."
-#: db/models/fields/__init__.py:369
+#: db/models/fields/__init__.py:372
msgid "This value must be either True or False."
msgstr "Este valor debe ser True o False."
-#: db/models/fields/__init__.py:385
+#: db/models/fields/__init__.py:388
msgid "This field cannot be null."
msgstr "Este campo no puede ser nulo."
-#: db/models/fields/__init__.py:471 core/validators.py:135
+#: db/models/fields/__init__.py:415 core/validators.py:127
+msgid "Enter a valid date in YYYY-MM-DD format."
+msgstr "Introduzca una fecha válida en formato AAAA-MM-DD."
+
+#: db/models/fields/__init__.py:477 core/validators.py:135
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr "Introduzca una fecha/hora válida en formato YYYY-MM-DD HH:MM."
-#: db/models/fields/__init__.py:565
+#: db/models/fields/__init__.py:571
msgid "Enter a valid filename."
msgstr "Introduzca un nombre de achivo válido"
-#: db/models/fields/related.py:43
+#: db/models/fields/related.py:51
#, python-format
msgid "Please enter a valid %s."
msgstr "Por favor, introduzca un %s válido."
-#: db/models/fields/related.py:579
+#: db/models/fields/related.py:618
msgid "Separate multiple IDs with commas."
msgstr " Separe múltiples IDs con comas."
-#: db/models/fields/related.py:581
+#: db/models/fields/related.py:620
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
"Pulse \"Control\", o \"Command\" en un Mac, para seleccionar más de uno."
-#: db/models/fields/related.py:625
+#: db/models/fields/related.py:664
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
msgid_plural ""
@@ -1754,29 +1884,29 @@ msgstr[1] "Asegúrese de que su texto tiene menos de %s caracteres."
msgid "Line breaks are not allowed here."
msgstr "No se permiten saltos de línea."
-#: forms/__init__.py:485 forms/__init__.py:558 forms/__init__.py:597
+#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "Seleccione una opción válida; '%(data)s' no está en %(choices)s."
-#: forms/__init__.py:659 core/validators.py:151 core/validators.py:379
+#: forms/__init__.py:661 core/validators.py:151 core/validators.py:379
msgid "No file was submitted. Check the encoding type on the form."
msgstr ""
"No se envió un archivo. Verifique el tipo de codificación en el formulario."
-#: forms/__init__.py:661
+#: forms/__init__.py:663
msgid "The submitted file is empty."
msgstr "El archivo enviado está vacío."
-#: forms/__init__.py:717
+#: forms/__init__.py:719
msgid "Enter a whole number between -32,768 and 32,767."
msgstr "Introduzca un número entero entre -32,768 y 32,767."
-#: forms/__init__.py:727
+#: forms/__init__.py:729
msgid "Enter a positive number."
msgstr "Introduzca un número positivo."
-#: forms/__init__.py:737
+#: forms/__init__.py:739
msgid "Enter a whole number between 0 and 32,767."
msgstr "Introduzca un número entero entre 0 y 32,767."
@@ -1832,10 +1962,6 @@ msgstr "Introduzca un número entero."
msgid "Only alphabetical characters are allowed here."
msgstr "Sólo se admiten caracteres alfabéticos."
-#: core/validators.py:127
-msgid "Enter a valid date in YYYY-MM-DD format."
-msgstr "Introduzca una fecha válida en formato AAAA-MM-DD."
-
#: core/validators.py:131
msgid "Enter a valid time in HH:MM format."
msgstr "Introduzca una hora válida en formato HH:MM."
@@ -2066,18 +2192,28 @@ msgstr ""
"El atributo \"%(attr)s\" de la línea %(line)s tiene un valor que no es "
"válido. (La línea empieza por \"%(start)s\".)"
-#: template/defaultfilters.py:389
+#: template/defaultfilters.py:401
msgid "yes,no,maybe"
msgstr "si,no,tal vez"
-#, fuzzy
+#: views/generic/create_update.py:43
+#, python-format
+msgid "The %(verbose_name)s was created successfully."
+msgstr "Se creó con éxito el %(verbose_name)."
+
+#: views/generic/create_update.py:117
+#, python-format
+msgid "The %(verbose_name)s was updated successfully."
+msgstr "Se actualizó con éxito el %(verbose_name)s."
+
+#: views/generic/create_update.py:184
+#, python-format
+msgid "The %(verbose_name)s was deleted."
+msgstr "Se eliminó el %(verbose_name)s."
+
#~ msgid "%(content_type_name)s"
#~ msgstr "tipos de contenido"
-#, fuzzy
-#~ msgid "%(myname)s"
-#~ msgstr "Agregar %(name)s"
-
#~ msgid "%(result_count)s result"
#~ msgid_plural "%(counter)s results"
#~ msgstr[0] "un resultado"
diff --git a/django/conf/locale/fi/LC_MESSAGES/django.mo b/django/conf/locale/fi/LC_MESSAGES/django.mo
new file mode 100644
index 0000000000..1e690716fd
--- /dev/null
+++ b/django/conf/locale/fi/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/fi/LC_MESSAGES/django.po b/django/conf/locale/fi/LC_MESSAGES/django.po
new file mode 100644
index 0000000000..9b91982e6b
--- /dev/null
+++ b/django/conf/locale/fi/LC_MESSAGES/django.po
@@ -0,0 +1,2031 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-08-05 14:41+0300\n"
+"PO-Revision-Date: 2006-08-12 23:41+0300\n"
+"Last-Translator: Antti Kaihola <antti.kaihola@ambitone.com>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: db/models/manipulators.py:302
+#, python-format
+msgid "%(object)s with this %(type)s already exists for the given %(field)s."
+msgstr ""
+
+#: db/models/fields/related.py:51
+#, python-format
+msgid "Please enter a valid %s."
+msgstr "Syöttämäsi %s ei kelpaa."
+
+#: db/models/fields/related.py:618
+msgid "Separate multiple IDs with commas."
+msgstr "Erottele tunnisteet pilkuilla."
+
+#: db/models/fields/related.py:620
+msgid ""
+"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
+msgstr ""
+" Pidä \"Ctrl\"-näppäin (tai Macin \"Command\") pohjassa valitaksesi useita "
+"vaihtoehtoja."
+
+#: db/models/fields/related.py:664
+#, python-format
+msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
+msgid_plural ""
+"Please enter valid %(self)s IDs. The values %(value)r are invalid."
+msgstr[0] "Syöttämäsi %(self)s-tunniste %(value)r ei kelpaa."
+msgstr[1] "Syöttämäsi %(self)s-tunnisteet %(value)r eivät kelpaa."
+
+#: db/models/fields/__init__.py:40
+#, python-format
+msgid "%(optname)s with this %(fieldname)s already exists."
+msgstr "%(optname)s, jolla on tämä %(fieldname)s, on jo olemassa."
+
+#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
+#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562
+#: forms/__init__.py:346
+msgid "This field is required."
+msgstr "Tämä kenttä vaaditaan."
+
+#: db/models/fields/__init__.py:340
+msgid "This value must be an integer."
+msgstr "Tarvitaan kokonaisluku."
+
+#: db/models/fields/__init__.py:372
+msgid "This value must be either True or False."
+msgstr "Tarvitaan tosi (True) tai epätosi (False)."
+
+#: db/models/fields/__init__.py:388
+msgid "This field cannot be null."
+msgstr "Tämän kentän arvo ei voi olla \"null\"."
+
+#: db/models/fields/__init__.py:415 core/validators.py:127
+msgid "Enter a valid date in YYYY-MM-DD format."
+msgstr "Päivämäärän pitää olla muodossa VVVV-KK-PP."
+
+#: db/models/fields/__init__.py:477 core/validators.py:135
+msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
+msgstr "Ajankohdan pitää olla muodossa VVVV-KK-PP TT:MM."
+
+#: db/models/fields/__init__.py:571
+msgid "Enter a valid filename."
+msgstr "Tiedostonimi ei kelpaa."
+
+#: conf/global_settings.py:39
+msgid "Arabic"
+msgstr "arabia"
+
+#: conf/global_settings.py:40
+msgid "Bengali"
+msgstr "bengali"
+
+#: conf/global_settings.py:41
+msgid "Czech"
+msgstr "tšekki"
+
+#: conf/global_settings.py:42
+msgid "Welsh"
+msgstr ""
+
+#: conf/global_settings.py:43
+msgid "Danish"
+msgstr "tanska"
+
+#: conf/global_settings.py:44
+msgid "German"
+msgstr "saksa"
+
+#: conf/global_settings.py:45
+msgid "Greek"
+msgstr "kreikka"
+
+#: conf/global_settings.py:46
+msgid "English"
+msgstr "englanti"
+
+#: conf/global_settings.py:47
+msgid "Spanish"
+msgstr "espanja"
+
+#: conf/global_settings.py:48
+msgid "Argentinean Spanish"
+msgstr "Argentiinan espanja"
+
+#: conf/global_settings.py:49
+msgid "French"
+msgstr "ranska"
+
+#: conf/global_settings.py:50
+msgid "Galician"
+msgstr ""
+
+#: conf/global_settings.py:51
+msgid "Hungarian"
+msgstr "unkari"
+
+#: conf/global_settings.py:52
+msgid "Hebrew"
+msgstr "heprea"
+
+#: conf/global_settings.py:53
+msgid "Icelandic"
+msgstr "islanti"
+
+#: conf/global_settings.py:54
+msgid "Italian"
+msgstr "italia"
+
+#: conf/global_settings.py:55
+msgid "Japanese"
+msgstr "japani"
+
+#: conf/global_settings.py:56
+msgid "Dutch"
+msgstr "hollanti"
+
+#: conf/global_settings.py:57
+msgid "Norwegian"
+msgstr "norja"
+
+#: conf/global_settings.py:58
+msgid "Brazilian"
+msgstr ""
+
+#: conf/global_settings.py:59
+msgid "Romanian"
+msgstr "romania"
+
+#: conf/global_settings.py:60
+msgid "Russian"
+msgstr "venäjä"
+
+#: conf/global_settings.py:61
+msgid "Slovak"
+msgstr ""
+
+#: conf/global_settings.py:62
+msgid "Slovenian"
+msgstr ""
+
+#: conf/global_settings.py:63
+msgid "Serbian"
+msgstr ""
+
+#: conf/global_settings.py:64
+msgid "Swedish"
+msgstr "ruotsi"
+
+#: conf/global_settings.py:65
+msgid "Tamil"
+msgstr ""
+
+#: conf/global_settings.py:66
+msgid "Ukrainian"
+msgstr ""
+
+#: conf/global_settings.py:67
+msgid "Simplified Chinese"
+msgstr ""
+
+#: conf/global_settings.py:68
+msgid "Traditional Chinese"
+msgstr ""
+
+#: core/validators.py:63
+msgid "This value must contain only letters, numbers and underscores."
+msgstr "Tässä voidaan käyttää vain kirjaimia (a-z), numeroita (0-9) ja alaviivoja (_)."
+
+#: core/validators.py:67
+msgid ""
+"This value must contain only letters, numbers, underscores, dashes or "
+"slashes."
+msgstr "Tässä voidaan käyttää vain kirjaimia (a-z), numeroita (0-9) sekä ala-, tavu- ja kauttaviivoja (_ - /)."
+
+#: core/validators.py:75
+msgid "Uppercase letters are not allowed here."
+msgstr "Versaalit (ABC) eivät kelpaa tässä."
+
+#: core/validators.py:79
+msgid "Lowercase letters are not allowed here."
+msgstr "Pienet kirjaimet (abc) eivät kelpaa tässä."
+
+#: core/validators.py:86
+msgid "Enter only digits separated by commas."
+msgstr "Vain pilkulla erotetut luvut kelpaavat tässä."
+
+#: core/validators.py:98
+msgid "Enter valid e-mail addresses separated by commas."
+msgstr "Syötä sähköpostiosoitteita pilkuilla erotettuina."
+
+#: core/validators.py:102
+msgid "Please enter a valid IP address."
+msgstr "IP-osoite ei kelpaa."
+
+#: core/validators.py:106
+msgid "Empty values are not allowed here."
+msgstr "Tätä kohtaa ei voi jättää tyhjäksi."
+
+#: core/validators.py:110
+msgid "Non-numeric characters aren't allowed here."
+msgstr "Vain numerot (0-9) kelpaavat tässä."
+
+#: core/validators.py:114
+msgid "This value can't be comprised solely of digits."
+msgstr "Tarvitaan vähintään yksi merkki, joka ei ole numero (0-9)."
+
+#: core/validators.py:119
+msgid "Enter a whole number."
+msgstr "Syötä kokonaisluku."
+
+#: core/validators.py:123
+msgid "Only alphabetical characters are allowed here."
+msgstr "Vain kirjaimet kelpaavat tässä."
+
+#: core/validators.py:131
+msgid "Enter a valid time in HH:MM format."
+msgstr "Ajan täytyy olla muodossa TT:MM."
+
+#: core/validators.py:139
+msgid "Enter a valid e-mail address."
+msgstr "Syötä kelvollinen sähköpostiosoite."
+
+#: core/validators.py:151 core/validators.py:379 forms/__init__.py:661
+msgid "No file was submitted. Check the encoding type on the form."
+msgstr "Tiedostoa ei lähetetty. Tarkista lomakkeen koodaus (encoding)."
+
+#: core/validators.py:155
+msgid ""
+"Upload a valid image. The file you uploaded was either not an image or a "
+"corrupted image."
+msgstr "Kuva ei kelpaa. Lähettämäsi tiedosto ei ole kuva, tai tiedosto on vioittunut."
+
+#: core/validators.py:162
+#, python-format
+msgid "The URL %s does not point to a valid image."
+msgstr "Osoittessa %s ei ole kelpaavaa kuvaa."
+
+#: core/validators.py:166
+#, python-format
+msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
+msgstr "Puhelinnumeron tulee olla muodossa XXX-XXX-XXXX. \"%s\" ei kelpaa."
+
+#: core/validators.py:174
+#, python-format
+msgid "The URL %s does not point to a valid QuickTime video."
+msgstr "Osoitteessa %s ei ole kelpaavaa QuickTime-videota."
+
+#: core/validators.py:178
+msgid "A valid URL is required."
+msgstr "URL-osoite ei kelpaa."
+
+#: core/validators.py:192
+#, python-format
+msgid ""
+"Valid HTML is required. Specific errors are:\n"
+"%s"
+msgstr ""
+"HTML-koodi ei kelpaa. Virheilmoitus on:\n"
+"%s"
+
+#: core/validators.py:199
+#, python-format
+msgid "Badly formed XML: %s"
+msgstr "Vääränmuotoinen XML: %s"
+
+#: core/validators.py:209
+#, python-format
+msgid "Invalid URL: %s"
+msgstr "URL-osoite %s ei kelpaa."
+
+#: core/validators.py:213 core/validators.py:215
+#, python-format
+msgid "The URL %s is a broken link."
+msgstr "Osoite %s on katkennut linkki."
+
+#: core/validators.py:221
+msgid "Enter a valid U.S. state abbreviation."
+msgstr "Syötä USA:n osavaltion lyhenne."
+
+#: core/validators.py:236
+#, python-format
+msgid "Watch your mouth! The word %s is not allowed here."
+msgid_plural "Watch your mouth! The words %s are not allowed here."
+msgstr[0] "Sanaa \"%s\" ei saa käyttää tässä."
+msgstr[1] "Sanoja \"%s\" ei saa käyttää tässä."
+
+#: core/validators.py:243
+#, python-format
+msgid "This field must match the '%s' field."
+msgstr ""
+
+#: core/validators.py:262
+msgid "Please enter something for at least one field."
+msgstr "Täytä ainakin yksi kenttä."
+
+#: core/validators.py:271 core/validators.py:282
+msgid "Please enter both fields or leave them both empty."
+msgstr "Täytä tai jätä tyhjäksi kummatkin kentät."
+
+#: core/validators.py:289
+#, python-format
+msgid "This field must be given if %(field)s is %(value)s"
+msgstr "Tämä kenttä pitää täyttää, jos %(field)s on %(value)s."
+
+#: core/validators.py:301
+#, python-format
+msgid "This field must be given if %(field)s is not %(value)s"
+msgstr "Tämä kenttä pitää täyttää, jos %(field)s ei ole %(value)s."
+
+#: core/validators.py:320
+msgid "Duplicate values are not allowed."
+msgstr "Samaa arvoa ei voi käyttää kahdesti."
+
+#: core/validators.py:343
+#, python-format
+msgid "This value must be a power of %s."
+msgstr "Tämän luvun on oltava %s:n potenssi."
+
+#: core/validators.py:354
+msgid "Please enter a valid decimal number."
+msgstr "Desimaaliluku ei kelpaa."
+
+#: core/validators.py:356
+#, python-format
+msgid "Please enter a valid decimal number with at most %s total digit."
+msgid_plural ""
+"Please enter a valid decimal number with at most %s total digits."
+msgstr[0] "Desimaaliluvussa saa tässä olla yhteensä vain %s merkitsevä numero. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)."
+msgstr[1] "Desimaaliluvussa saa tässä olla yhteensä vain %s merkitsevää numeroa. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)."
+
+#: core/validators.py:359
+#, python-format
+msgid ""
+"Please enter a valid decimal number with a whole part of at most %s digit."
+msgid_plural ""
+"Please enter a valid decimal number with a whole part of at most %s digits."
+msgstr[0] "Desimaaliluvun kokonaisosassa saa tässä olla vain %s numero. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)."
+msgstr[1] "Desimaaliluvun kokonaisosassa saa tässä olla vain %s numeroa. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)."
+
+#: core/validators.py:362
+#, python-format
+msgid "Please enter a valid decimal number with at most %s decimal place."
+msgid_plural ""
+"Please enter a valid decimal number with at most %s decimal places."
+msgstr[0] "Tässä saa olla vain %s desimaali. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)."
+msgstr[1] "Tässä saa olla vain %s desimaalia. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)."
+
+#: core/validators.py:372
+#, python-format
+msgid "Make sure your uploaded file is at least %s bytes big."
+msgstr "Lähetä vähintään %s tavun kokoinen tiedosto."
+
+#: core/validators.py:373
+#, python-format
+msgid "Make sure your uploaded file is at most %s bytes big."
+msgstr "Lähetä enintään %s tavun kokoinen tiedosto."
+
+#: core/validators.py:390
+msgid "The format for this field is wrong."
+msgstr "Muoto ei kelpaa."
+
+#: core/validators.py:405
+msgid "This field is invalid."
+msgstr "Tämä arvo ei kelpaa."
+
+#: core/validators.py:441
+#, python-format
+msgid "Could not retrieve anything from %s."
+msgstr ""
+
+#: core/validators.py:444
+#, python-format
+msgid ""
+"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
+msgstr "Osoitteesta %(url)s saatiin virheellinen Content-Type '%(contenttype)s'."
+
+#: core/validators.py:477
+#, python-format
+msgid ""
+"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
+"\"%(start)s\".)"
+msgstr "Rivillä %(line)s oleva tagi %(tag)s pitää sulkea. (Rivi alkaa \"%(start)s\")"
+
+#: core/validators.py:481
+#, python-format
+msgid ""
+"Some text starting on line %(line)s is not allowed in that context. (Line "
+"starts with \"%(start)s\".)"
+msgstr "Rivillä %(line)s on tekstiä, joka ei kelpaa tässä yhteydessä. (Rivi alkaa \"%(start)s\")"
+
+#: core/validators.py:486
+#, python-format
+msgid ""
+"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
+"(start)s\".)"
+msgstr "Rivillä %(line)s attribuutti %(attr)s ei kelpaa. (Rivi alkaa \"%(start)s\")"
+
+#: core/validators.py:491
+#, python-format
+msgid ""
+"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
+"(start)s\".)"
+msgstr "Rivillä %(line)s tagi \"<%(tag)s>\" ei kelpaa. (Rivi alkaa \"%(start)s\")"
+
+#: core/validators.py:495
+#, python-format
+msgid ""
+"A tag on line %(line)s is missing one or more required attributes. (Line "
+"starts with \"%(start)s\".)"
+msgstr "Rivillä %(line)s yhdestä tagista puuttuu yksi tai useampi attribuutti. (Rivi alkaa \"%(start)s\")"
+
+#: core/validators.py:500
+#, python-format
+msgid ""
+"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
+"starts with \"%(start)s\".)"
+msgstr "Rivillä %(line)s attribuutin %(attr)s arvo ei kelpaa. (Rivi alkaa \"%(start)s\")"
+
+#: contrib/auth/forms.py:52
+msgid ""
+"Your Web browser doesn't appear to have cookies enabled. Cookies are "
+"required for logging in."
+msgstr "Selaimesi ei salli evästeitä. Sisäänkirjautuminen vaatii evästeen."
+
+#: contrib/auth/forms.py:59 contrib/admin/views/decorators.py:10
+msgid ""
+"Please enter a correct username and password. Note that both fields are case-"
+"sensitive."
+msgstr "Käyttäjätunnus tai salasana ei kelpaa. Huomaa, että isot ja pienet kirjaimet ovat merkitseviä."
+
+#: contrib/auth/forms.py:61
+msgid "This account is inactive."
+msgstr "Tämä käyttäjätili ei ole voimassa."
+
+#: contrib/auth/models.py:38 contrib/auth/models.py:57
+msgid "name"
+msgstr "nimi"
+
+#: contrib/auth/models.py:40
+msgid "codename"
+msgstr "koodinimi"
+
+#: contrib/auth/models.py:42
+msgid "permission"
+msgstr "oikeus"
+
+#: contrib/auth/models.py:43 contrib/auth/models.py:58
+msgid "permissions"
+msgstr "oikeudet"
+
+#: contrib/auth/models.py:60
+msgid "group"
+msgstr "ryhmä"
+
+#: contrib/auth/models.py:61 contrib/auth/models.py:100
+msgid "groups"
+msgstr "ryhmät"
+
+#: contrib/auth/models.py:90
+msgid "username"
+msgstr "tunnus"
+
+#: contrib/auth/models.py:90
+msgid ""
+"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
+"digits and underscores)."
+msgstr " Vaaditaan. Enintään 30 kirjanta (a-z), numeroa (0-9) tai alaviivaa (_)."
+
+#: contrib/auth/models.py:91
+msgid "first name"
+msgstr "etunimi"
+
+#: contrib/auth/models.py:92
+msgid "last name"
+msgstr "sukunimi"
+
+#: contrib/auth/models.py:93
+msgid "e-mail address"
+msgstr "sähköposti"
+
+#: contrib/auth/models.py:94
+msgid "password"
+msgstr "salasana"
+
+#: contrib/auth/models.py:94
+msgid "Use '[algo]$[salt]$[hexdigest]'"
+msgstr "(Salasanaa ei näytetä selväkielisenä)"
+
+#: contrib/auth/models.py:95
+msgid "staff status"
+msgstr "ylläpitäjä"
+
+#: contrib/auth/models.py:95
+msgid "Designates whether the user can log into this admin site."
+msgstr "Ylläpitäjillä on pääsy tähän sivuston ylläpito-osioon."
+
+#: contrib/auth/models.py:96
+msgid "active"
+msgstr "voimassa"
+
+#: contrib/auth/models.py:96
+msgid ""
+"Designates whether this user can log into the Django admin. Unselect this "
+"instead of deleting accounts."
+msgstr "Määrää, voiko käyttäjä kirjautua sisään. Tällä voi estää käyttäjätilin käytön poistamatta sitä."
+
+#: contrib/auth/models.py:97
+msgid "superuser status"
+msgstr "pääkäyttäjä"
+
+#: contrib/auth/models.py:97
+msgid ""
+"Designates that this user has all permissions without explicitly assigning "
+"them."
+msgstr "Antaa käyttäjälle kaikki oikeudet ilman, että niitä täytyy erikseen luetella."
+
+#: contrib/auth/models.py:98
+msgid "last login"
+msgstr "viimeksi kirjautunut"
+
+#: contrib/auth/models.py:99
+msgid "date joined"
+msgstr "liittynyt"
+
+#: contrib/auth/models.py:101
+msgid ""
+"In addition to the permissions manually assigned, this user will also get "
+"all permissions granted to each group he/she is in."
+msgstr ""
+"Tässä valittujen oikeuksien lisäksi käyttäjä saa myös kaikki niiden ryhmien "
+"oikeudet, joiden jäsen hän on."
+
+#: contrib/auth/models.py:102
+msgid "user permissions"
+msgstr "käyttäjän oikeudet"
+
+#: contrib/auth/models.py:105
+msgid "user"
+msgstr "käyttäjä"
+
+#: contrib/auth/models.py:106
+msgid "users"
+msgstr "käyttäjät"
+
+#: contrib/auth/models.py:111
+msgid "Personal info"
+msgstr "Henkilökohtaiset tiedot"
+
+#: contrib/auth/models.py:112
+msgid "Permissions"
+msgstr "Oikeudet"
+
+#: contrib/auth/models.py:113
+msgid "Important dates"
+msgstr "Tärkeät päivämäärät"
+
+#: contrib/auth/models.py:114
+msgid "Groups"
+msgstr "Ryhmät"
+
+#: contrib/auth/models.py:256
+msgid "message"
+msgstr "viesti"
+
+#: contrib/auth/views.py:39
+msgid "Logged out"
+msgstr "Kirjautunut ulos"
+
+#: contrib/admin/models.py:16
+msgid "action time"
+msgstr "tapahtumahetki"
+
+#: contrib/admin/models.py:19
+msgid "object id"
+msgstr "kohteen tunniste"
+
+#: contrib/admin/models.py:20
+msgid "object repr"
+msgstr "kohteen tiedot"
+
+#: contrib/admin/models.py:21
+msgid "action flag"
+msgstr "tapahtumatyyppi"
+
+#: contrib/admin/models.py:22
+msgid "change message"
+msgstr "selitys"
+
+#: contrib/admin/models.py:25
+msgid "log entry"
+msgstr "lokimerkintä"
+
+#: contrib/admin/models.py:26
+msgid "log entries"
+msgstr "lokimerkinnät"
+
+#: contrib/admin/filterspecs.py:40
+#, python-format
+msgid ""
+"<h3>By %s:</h3>\n"
+"<ul>\n"
+msgstr ""
+"<h3>Yksi %s:</h3>\n"
+"<ul>\n"
+
+#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
+#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169
+msgid "All"
+msgstr "Kaikki"
+
+#: contrib/admin/filterspecs.py:109
+msgid "Any date"
+msgstr "Mikä tahansa päivä"
+
+#: contrib/admin/filterspecs.py:110
+msgid "Today"
+msgstr "Tänään"
+
+#: contrib/admin/filterspecs.py:113
+msgid "Past 7 days"
+msgstr "Viimeiset 7 päivää"
+
+#: contrib/admin/filterspecs.py:115
+msgid "This month"
+msgstr "Tässä kuussa"
+
+#: contrib/admin/filterspecs.py:117
+msgid "This year"
+msgstr "Tänä vuonna"
+
+#: contrib/admin/filterspecs.py:143
+msgid "Yes"
+msgstr "Kyllä"
+
+#: contrib/admin/filterspecs.py:143
+msgid "No"
+msgstr "Ei"
+
+#: contrib/admin/filterspecs.py:150
+msgid "Unknown"
+msgstr "Tuntematon"
+
+#: contrib/admin/views/decorators.py:24
+#: contrib/admin/templates/admin/login.html:25
+msgid "Log in"
+msgstr "Kirjaudu sisään"
+
+#: contrib/admin/views/decorators.py:62
+msgid ""
+"Please log in again, because your session has expired. Don't worry: Your "
+"submission has been saved."
+msgstr "Kirjaudu uudelleen sisään, koska istuntosi on mennyt umpeen. Muutoksesi ovat silti tallessa."
+
+#: contrib/admin/views/decorators.py:69
+msgid ""
+"Looks like your browser isn't configured to accept cookies. Please enable "
+"cookies, reload this page, and try again."
+msgstr "Selaimesi ei salli evästeitä. Muuta asetukset sallimaan evästeet, lataa tämä sivu uudelleen ja yritä toistamiseen."
+
+#: contrib/admin/views/decorators.py:83
+msgid "Usernames cannot contain the '@' character."
+msgstr "Käyttäjätunnuksessa ei saa olla '@'-merkkiä."
+
+#: contrib/admin/views/decorators.py:85
+#, python-format
+msgid "Your e-mail address is not your username. Try '%s' instead."
+msgstr "Käyttäjätunnus ei ole sama kuin sähköpostiosoite. Kokeile '%s'."
+
+#: contrib/admin/views/main.py:223
+msgid "Site administration"
+msgstr "Sivuston ylläpito"
+
+#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:14
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was added successfully."
+msgstr "%(name)s \"%(obj)s\" on nyt lisätty."
+
+#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:345
+#: contrib/admin/views/auth.py:19
+msgid "You may edit it again below."
+msgstr "Voit muokata sitä uudelleen alla."
+
+#: contrib/admin/views/main.py:269 contrib/admin/views/main.py:354
+#, python-format
+msgid "You may add another %s below."
+msgstr "Uusi %s on lisättävissä alla."
+
+#: contrib/admin/views/main.py:287
+#, python-format
+msgid "Add %s"
+msgstr "Uusi %s"
+
+#: contrib/admin/views/main.py:333
+#, python-format
+msgid "Added %s."
+msgstr "Lisätty %s."
+
+#: contrib/admin/views/main.py:333 contrib/admin/views/main.py:335
+#: contrib/admin/views/main.py:337
+msgid "and"
+msgstr "ja"
+
+#: contrib/admin/views/main.py:335
+#, python-format
+msgid "Changed %s."
+msgstr "Muokattu: %s."
+
+#: contrib/admin/views/main.py:337
+#, python-format
+msgid "Deleted %s."
+msgstr "Poistettu %s."
+
+#: contrib/admin/views/main.py:340
+msgid "No fields changed."
+msgstr "Ei muutoksia kenttiin."
+
+#: contrib/admin/views/main.py:343
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was changed successfully."
+msgstr "%(name)s \"%(obj)s\" on nyt muutettu."
+
+#: contrib/admin/views/main.py:351
+#, python-format
+msgid ""
+"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
+msgstr "%(name)s \"%(obj)s\" on nyt lisätty. Voit muokata sitä uudelleen alla."
+
+#: contrib/admin/views/main.py:389
+#, python-format
+msgid "Change %s"
+msgstr "Muokkaa: %s"
+
+#: contrib/admin/views/main.py:471
+#, python-format
+msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
+msgstr "Yksi tai useampi %(fieldname)s kohteessa %(name)s: %(obj)s"
+
+#: contrib/admin/views/main.py:476
+#, python-format
+msgid "One or more %(fieldname)s in %(name)s:"
+msgstr "Yksi tai useampi %(fieldname)s kohteessa %(name)s:"
+
+#: contrib/admin/views/main.py:509
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was deleted successfully."
+msgstr "%(name)s \"%(obj)s\" on poistettu."
+
+#: contrib/admin/views/main.py:512
+msgid "Are you sure?"
+msgstr "Oletko varma?"
+
+#: contrib/admin/views/main.py:534
+#, python-format
+msgid "Change history: %s"
+msgstr "Muokkaushistoria: %s"
+
+#: contrib/admin/views/main.py:568
+#, python-format
+msgid "Select %s"
+msgstr "Valitse %s"
+
+#: contrib/admin/views/main.py:568
+#, python-format
+msgid "Select %s to change"
+msgstr "Valitse muokattava %s"
+
+#: contrib/admin/views/main.py:744
+msgid "Database error"
+msgstr "Tietokantavirhe"
+
+#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:303 contrib/admin/views/doc.py:309
+#: contrib/admin/views/doc.py:310 contrib/admin/views/doc.py:312
+msgid "Integer"
+msgstr "Kokonaisluku"
+
+#: contrib/admin/views/doc.py:292
+msgid "Boolean (Either True or False)"
+msgstr "Totuusarvo: joko tosi (True) tai epätosi (False)"
+
+#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:311
+#, python-format
+msgid "String (up to %(maxlength)s)"
+msgstr "Merkkijono (enintään %(maxlength)s merkkiä)"
+
+#: contrib/admin/views/doc.py:294
+msgid "Comma-separated integers"
+msgstr "Pilkulla erotetut kokonaisluvut"
+
+#: contrib/admin/views/doc.py:295
+msgid "Date (without time)"
+msgstr "Päivämäärä"
+
+#: contrib/admin/views/doc.py:296
+msgid "Date (with time)"
+msgstr "Päivämäärä ja kellonaika"
+
+#: contrib/admin/views/doc.py:297
+msgid "E-mail address"
+msgstr "Sähköpostios."
+
+#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:302
+msgid "File path"
+msgstr "Tiedostopolku"
+
+#: contrib/admin/views/doc.py:300
+msgid "Decimal number"
+msgstr "Desimaaliluku"
+
+#: contrib/admin/views/doc.py:304 contrib/comments/models.py:85
+msgid "IP address"
+msgstr "IP-osoite"
+
+#: contrib/admin/views/doc.py:306
+msgid "Boolean (Either True, False or None)"
+msgstr "Totuusarvo: joko tosi (True), epätosi (False) tai ei mikään (None)"
+
+#: contrib/admin/views/doc.py:307
+msgid "Relation to parent model"
+msgstr "Relaatio emomalliin"
+
+#: contrib/admin/views/doc.py:308
+msgid "Phone number"
+msgstr "Puhelinnumero"
+
+#: contrib/admin/views/doc.py:313
+msgid "Text"
+msgstr "Tekstiä"
+
+#: contrib/admin/views/doc.py:314
+msgid "Time"
+msgstr "Kellonaika"
+
+#: contrib/admin/views/doc.py:315 contrib/flatpages/models.py:7
+msgid "URL"
+msgstr "URL-osoite"
+
+#: contrib/admin/views/doc.py:316
+msgid "U.S. state (two uppercase letters)"
+msgstr "USA:n osavaltio (kaksikirjaiminen versaalein)"
+
+#: contrib/admin/views/doc.py:317
+msgid "XML text"
+msgstr "XML-teksti"
+
+#: contrib/admin/views/auth.py:25
+msgid "Add user"
+msgstr "Uusi käyttäjä"
+
+#: contrib/admin/templatetags/admin_list.py:230
+msgid "All dates"
+msgstr "Kaikki päivät"
+
+#: contrib/admin/templates/admin/pagination.html:10
+msgid "Show all"
+msgstr "Näytä kaikki"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/base.html:24
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/registration/password_change_done.html:3
+msgid "Documentation"
+msgstr "Ohjeita"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/base.html:24
+#: contrib/admin/templates/admin_doc/template_filter_index.html:5
+#: contrib/admin/templates/admin_doc/bookmarklets.html:4
+#: contrib/admin/templates/admin_doc/template_tag_index.html:5
+#: contrib/admin/templates/admin_doc/index.html:4
+#: contrib/admin/templates/admin_doc/model_detail.html:3
+#: contrib/admin/templates/admin_doc/missing_docutils.html:4
+#: contrib/admin/templates/admin_doc/template_detail.html:4
+#: contrib/admin/templates/admin_doc/view_index.html:5
+#: contrib/admin/templates/admin_doc/model_index.html:5
+#: contrib/admin/templates/admin_doc/view_detail.html:4
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/registration/password_change_done.html:3
+msgid "Change password"
+msgstr "Vaihda salasana"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/base.html:24
+#: contrib/admin/templates/admin_doc/template_filter_index.html:5
+#: contrib/admin/templates/admin_doc/bookmarklets.html:4
+#: contrib/admin/templates/admin_doc/template_tag_index.html:5
+#: contrib/admin/templates/admin_doc/index.html:4
+#: contrib/admin/templates/admin_doc/model_detail.html:3
+#: contrib/admin/templates/admin_doc/missing_docutils.html:4
+#: contrib/admin/templates/admin_doc/template_detail.html:4
+#: contrib/admin/templates/admin_doc/view_index.html:5
+#: contrib/admin/templates/admin_doc/model_index.html:5
+#: contrib/admin/templates/admin_doc/view_detail.html:4
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/registration/password_change_done.html:3
+#: contrib/comments/templates/comments/form.html:6
+msgid "Log out"
+msgstr "Kirjaudu ulos"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:6
+#: contrib/admin/templates/admin/change_form.html:13
+#: contrib/admin/templates/admin/change_list.html:6
+#: contrib/admin/templates/admin/object_history.html:5
+#: contrib/admin/templates/admin/500.html:4
+#: contrib/admin/templates/admin/invalid_setup.html:4
+#: contrib/admin/templates/admin/base.html:29
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+#: contrib/admin/templates/registration/password_reset_form.html:4
+#: contrib/admin/templates/registration/logged_out.html:4
+#: contrib/admin/templates/registration/password_reset_done.html:4
+#: contrib/admin/templates/registration/password_change_form.html:4
+#: contrib/admin/templates/registration/password_change_done.html:4
+msgid "Home"
+msgstr "Etusivu"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:9
+#: contrib/admin/templates/admin/submit_line.html:3
+msgid "Delete"
+msgstr "Poista"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:14
+#, python-format
+msgid ""
+"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
+"related objects, but your account doesn't have permission to delete the "
+"following types of objects:"
+msgstr "Kohteen '%(escaped_object)s' (%(object_name)s) poisto poistaisi myös siihen liittyviä kohteita, mutta sinulla ei ole oikeutta näiden kohteiden poistamiseen:"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:21
+#, python-format
+msgid ""
+"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
+"All of the following related items will be deleted:"
+msgstr "Haluatko varmasti poistaa kohteen \"%(escaped_object)s\" (%(object_name)s)? Myös seuraavat kohteet poistettaisiin samalla:"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:26
+msgid "Yes, I'm sure"
+msgstr "Kyllä, olen varma"
+
+#: contrib/admin/templates/admin/404.html:4
+#: contrib/admin/templates/admin/404.html:8
+msgid "Page not found"
+msgstr "Sivua ei löydy"
+
+#: contrib/admin/templates/admin/404.html:10
+msgid "We're sorry, but the requested page could not be found."
+msgstr "Pahoittelemme, pyydettyä sivua ei voitu löytää."
+
+#: contrib/admin/templates/admin/change_form.html:15
+#: contrib/admin/templates/admin/index.html:28
+msgid "Add"
+msgstr "Lisää uusi"
+
+#: contrib/admin/templates/admin/change_form.html:20
+#: contrib/admin/templates/admin/object_history.html:5
+msgid "History"
+msgstr "Muokkaushistoria"
+
+#: contrib/admin/templates/admin/change_form.html:21
+msgid "View on site"
+msgstr "Näytä lopputulos"
+
+#: contrib/admin/templates/admin/change_form.html:30
+msgid "Please correct the error below."
+msgid_plural "Please correct the errors below."
+msgstr[0] "Korjaa virhe."
+msgstr[1] "Korjaa virheet."
+
+#: contrib/admin/templates/admin/change_form.html:48
+msgid "Ordering"
+msgstr "Järjestys"
+
+#: contrib/admin/templates/admin/change_form.html:51
+msgid "Order:"
+msgstr "Järjestysnumero:"
+
+#: contrib/admin/templates/admin/filter.html:2
+#, python-format
+msgid " By %(filter_title)s "
+msgstr " %(filter_title)s:"
+
+#: contrib/admin/templates/admin/submit_line.html:4
+msgid "Save as new"
+msgstr "Talleta uutena"
+
+#: contrib/admin/templates/admin/submit_line.html:5
+msgid "Save and add another"
+msgstr "Talleta ja lisää seuraava"
+
+#: contrib/admin/templates/admin/submit_line.html:6
+msgid "Save and continue editing"
+msgstr "Talleta välillä ja jatka muokkaamista"
+
+#: contrib/admin/templates/admin/submit_line.html:7
+msgid "Save"
+msgstr "Talleta ja poistu"
+
+#: contrib/admin/templates/admin/change_list.html:11
+#, python-format
+msgid "Add %(name)s"
+msgstr "Lisää uusi %(name)s"
+
+#: contrib/admin/templates/admin/index.html:17
+#, python-format
+msgid "Models available in the %(name)s application."
+msgstr "Sovelluksen %(name)s mallit."
+
+#: contrib/admin/templates/admin/index.html:18
+#, python-format
+msgid "%(name)s"
+msgstr "%(name)s"
+
+#: contrib/admin/templates/admin/index.html:34
+msgid "Change"
+msgstr "Muokkaa"
+
+#: contrib/admin/templates/admin/index.html:44
+msgid "You don't have permission to edit anything."
+msgstr "Sinulla ei ole oikeutta muokata mitään."
+
+#: contrib/admin/templates/admin/index.html:52
+msgid "Recent Actions"
+msgstr "Viimeisimmät muutokset"
+
+#: contrib/admin/templates/admin/index.html:53
+msgid "My Actions"
+msgstr "Sinun tekemäsi muutokset"
+
+#: contrib/admin/templates/admin/index.html:57
+msgid "None available"
+msgstr "Ei yhtään"
+
+#: contrib/admin/templates/admin/base_site.html:4
+msgid "Django site admin"
+msgstr "Django-sivuston ylläpito"
+
+#: contrib/admin/templates/admin/base_site.html:7
+msgid "Django administration"
+msgstr "Djangon ylläpito"
+
+#: contrib/admin/templates/admin/object_history.html:18
+msgid "Date/time"
+msgstr "Pvm/klo"
+
+#: contrib/admin/templates/admin/object_history.html:19
+msgid "User"
+msgstr "Käyttäjä"
+
+#: contrib/admin/templates/admin/object_history.html:20
+msgid "Action"
+msgstr "Toiminto"
+
+#: contrib/admin/templates/admin/object_history.html:26
+msgid "DATE_WITH_TIME_FULL"
+msgstr "N j, Y, P"
+
+#: contrib/admin/templates/admin/object_history.html:36
+msgid ""
+"This object doesn't have a change history. It probably wasn't added via this "
+"admin site."
+msgstr "Tällä kohteella ei ole muutoshistoriaa. Sitä ei ole lisätty tämän ylläpitosivun avulla."
+
+#: contrib/admin/templates/admin/500.html:4
+msgid "Server error"
+msgstr "Palvelinvirhe"
+
+#: contrib/admin/templates/admin/500.html:6
+msgid "Server error (500)"
+msgstr "Palvelinvirhe (500)"
+
+#: contrib/admin/templates/admin/500.html:9
+msgid "Server Error <em>(500)</em>"
+msgstr "Palvelinvirhe <em>(500)</em>"
+
+#: contrib/admin/templates/admin/invalid_setup.html:8
+msgid ""
+"Something's wrong with your database installation. Make sure the appropriate "
+"database tables have been created, and make sure the database is readable by "
+"the appropriate user."
+msgstr "Tietokanta-asennuksessasi on jotain vialla. Varmistu, että sopivat taulut on luotu ja että oikea käyttäjä voi lukea tietokantaa."
+
+#: contrib/admin/templates/admin/search_form.html:8
+msgid "Go"
+msgstr "Etsi"
+
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "1 result"
+msgid_plural "%(counter)s results"
+msgstr[0] "1 hakutulas"
+msgstr[1] "%(counter)s hakutulosta"
+
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "%(full_result_count)s total"
+msgstr "yhteensä %(full_result_count)s"
+
+#: contrib/admin/templates/admin/filters.html:4
+msgid "Filter"
+msgstr "Suodatin"
+
+#: contrib/admin/templates/admin/login.html:17
+#: contrib/comments/templates/comments/form.html:6
+#: contrib/comments/templates/comments/form.html:8
+msgid "Username:"
+msgstr "Käyttäjätunnus"
+
+#: contrib/admin/templates/admin/login.html:20
+#: contrib/comments/templates/comments/form.html:8
+msgid "Password:"
+msgstr "Salasana:"
+
+#: contrib/admin/templates/admin/login.html:22
+msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
+msgstr "Oletko <a href=\"/password_reset\">unohtanut salasanasi</a>?"
+
+#: contrib/admin/templates/admin/base.html:24
+msgid "Welcome,"
+msgstr "Tervetuloa,"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:6
+msgid ""
+"First, enter a username and password. Then, you'll be able to edit more user "
+"options."
+msgstr "Syötä ensin käyttäjätunnus ja salasana. Sen jälkeen voit muokata muita käyttäjän tietoja."
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:12
+msgid "Username"
+msgstr "Käyttäjätunnus"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:18
+msgid "Password"
+msgstr "Salasana:"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:23
+msgid "Password (again)"
+msgstr "Salasana toistamiseen"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:24
+msgid "Enter the same password as above, for verification."
+msgstr "Syötä sama salasana tarkistuksen vuoksi toistamiseen."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+msgid "Bookmarklets"
+msgstr "Kirjanmerkkiset"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:5
+msgid "Documentation bookmarklets"
+msgstr "Ohjeiden kirjanmerkkiset"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:9
+msgid ""
+"\n"
+"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n"
+"toolbar, or right-click the link and add it to your bookmarks. Now you can\n"
+"select the bookmarklet from any page in the site. Note that some of these\n"
+"bookmarklets require you to be viewing the site from a computer designated\n"
+"as \"internal\" (talk to your system administrator if you aren't sure if\n"
+"your computer is \"internal\").</p>\n"
+msgstr "\n<p class=\"help\">Asenna kirjanmerkkinen raahaamalla linkki kirjanmerkkien työkalupalkkiin tai napsauttamalla linkkiä oikeanpuoleisella hiiren painikkeella ja valitsemalla kirjanmerkkeihin lisäämisen. Sen jälkeen voit valita kirjanmerkkisen miltä tahansa sivuston sivulta. Huomaa, että jotkin näistä kirjanmerkkisistä toimivat vain, jos selaat sivustoa \"paikalliseksi\" määritellyltä tietokoneelta (kysy lisätietoja verkkonne ylläpitäjältä).</p>\n"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:19
+msgid "Documentation for this page"
+msgstr "Tämän sivun ohjeita"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:20
+msgid ""
+"Jumps you from any page to the documentation for the view that generates "
+"that page."
+msgstr "Vie avoinna olevan sivun luoneen näkymän ohjeisiin."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:22
+msgid "Show object ID"
+msgstr "Näytä kohteen tunniste"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:23
+msgid ""
+"Shows the content-type and unique ID for pages that represent a single "
+"object."
+msgstr "Näyttää yksittäistä kohdetta vastaavilla sivuilla kohteen tyypin ja tunnisteen."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:25
+msgid "Edit this object (current window)"
+msgstr "Muokkaa tätä kohdetta (tässä ikkunassa)"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:26
+msgid "Jumps to the admin page for pages that represent a single object."
+msgstr "Siirtyy yksittäistä kohdetta vastaavalta sivulta kohteen ylläpitosivulle."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:28
+msgid "Edit this object (new window)"
+msgstr "Muokkaa tätä kohdetta (uudessa ikkunassa)"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:29
+msgid "As above, but opens the admin page in a new window."
+msgstr "Kuten yllä, mutta avaa ylläpitosivun uuteen ikkunaan."
+
+#: contrib/admin/templates/widget/date_time.html:3
+msgid "Date:"
+msgstr "Pvm:"
+
+#: contrib/admin/templates/widget/date_time.html:4
+msgid "Time:"
+msgstr "Klo:"
+
+#: contrib/admin/templates/widget/file.html:2
+msgid "Currently:"
+msgstr "Tällä hetkellä:"
+
+#: contrib/admin/templates/widget/file.html:3
+msgid "Change:"
+msgstr "Muokkaa:"
+
+#: contrib/admin/templates/registration/password_reset_form.html:4
+#: contrib/admin/templates/registration/password_reset_form.html:6
+#: contrib/admin/templates/registration/password_reset_form.html:10
+#: contrib/admin/templates/registration/password_reset_done.html:4
+msgid "Password reset"
+msgstr "Salasanan nollaus"
+
+#: contrib/admin/templates/registration/password_reset_form.html:12
+msgid ""
+"Forgotten your password? Enter your e-mail address below, and we'll reset "
+"your password and e-mail the new one to you."
+msgstr ""
+"Unohditko salasanasi? Syötä alle sähköpostiosoitteesi, niin \n"
+"lähetämme sinulle uuden salasanan."
+
+#: contrib/admin/templates/registration/password_reset_form.html:16
+msgid "E-mail address:"
+msgstr "Sähköpostiosoite:"
+
+#: contrib/admin/templates/registration/password_reset_form.html:16
+msgid "Reset my password"
+msgstr "Nollaa salasana"
+
+#: contrib/admin/templates/registration/password_reset_email.html:2
+msgid "You're receiving this e-mail because you requested a password reset"
+msgstr "Sait tämän viestin, koska pyysit uutta salasanaa"
+
+#: contrib/admin/templates/registration/password_reset_email.html:3
+#, python-format
+msgid "for your user account at %(site_name)s"
+msgstr "sivuston %(site_name)s käyttäjätilillesi"
+
+#: contrib/admin/templates/registration/password_reset_email.html:5
+#, python-format
+msgid "Your new password is: %(new_password)s"
+msgstr "Uusi salasanasi on: %(new_password)s"
+
+#: contrib/admin/templates/registration/password_reset_email.html:7
+msgid "Feel free to change this password by going to this page:"
+msgstr "Voit vaihtaa salasanan sivulla:"
+
+#: contrib/admin/templates/registration/password_reset_email.html:11
+msgid "Your username, in case you've forgotten:"
+msgstr "Käyttäjätunnuksesi siltä varalta, että olet unohtanut sen:"
+
+#: contrib/admin/templates/registration/password_reset_email.html:13
+msgid "Thanks for using our site!"
+msgstr "Kiitos vierailustasi sivuillemme!"
+
+#: contrib/admin/templates/registration/password_reset_email.html:15
+#, python-format
+msgid "The %(site_name)s team"
+msgstr "%(site_name)s ylläpitäjät"
+
+#: contrib/admin/templates/registration/logged_out.html:8
+msgid "Thanks for spending some quality time with the Web site today."
+msgstr "Kiitos sivuillamme viettämästäsi ajasta."
+
+#: contrib/admin/templates/registration/logged_out.html:10
+msgid "Log in again"
+msgstr "Kirjaudu uudelleen sisään"
+
+#: contrib/admin/templates/registration/password_reset_done.html:6
+#: contrib/admin/templates/registration/password_reset_done.html:10
+msgid "Password reset successful"
+msgstr "Salasanan nollaus onnistui"
+
+#: contrib/admin/templates/registration/password_reset_done.html:12
+msgid ""
+"We've e-mailed a new password to the e-mail address you submitted. You "
+"should be receiving it shortly."
+msgstr ""
+"Uusi salasanasi on lähetetty antamaasi sähköpostiosoitteeseen.\n"
+"Se saapuu tuota pikaa."
+
+#: contrib/admin/templates/registration/password_change_form.html:4
+#: contrib/admin/templates/registration/password_change_form.html:6
+#: contrib/admin/templates/registration/password_change_form.html:10
+#: contrib/admin/templates/registration/password_change_done.html:4
+msgid "Password change"
+msgstr "Salasanan muuttaminen"
+
+#: contrib/admin/templates/registration/password_change_form.html:12
+msgid ""
+"Please enter your old password, for security's sake, and then enter your new "
+"password twice so we can verify you typed it in correctly."
+msgstr ""
+"Syötä vanha salasanasi varmistukseksi, ja syötä sitten uusi salasanasi\n"
+"kaksi kertaa, jotta se tulee varmasti oikein."
+
+#: contrib/admin/templates/registration/password_change_form.html:17
+msgid "Old password:"
+msgstr "Vanha salasana:"
+
+#: contrib/admin/templates/registration/password_change_form.html:19
+msgid "New password:"
+msgstr "Uusi salasana:"
+
+#: contrib/admin/templates/registration/password_change_form.html:21
+msgid "Confirm password:"
+msgstr "Varmista uusi salasana:"
+
+#: contrib/admin/templates/registration/password_change_form.html:23
+msgid "Change my password"
+msgstr "Vaihda salasana"
+
+#: contrib/admin/templates/registration/password_change_done.html:6
+#: contrib/admin/templates/registration/password_change_done.html:10
+msgid "Password change successful"
+msgstr "Salasanan muuttaminen onnistui"
+
+#: contrib/admin/templates/registration/password_change_done.html:12
+msgid "Your password was changed."
+msgstr "Salasanasi on muutettu."
+
+#: contrib/sites/models.py:10
+msgid "domain name"
+msgstr "domain-nimi"
+
+#: contrib/sites/models.py:11
+msgid "display name"
+msgstr "näyttönimi"
+
+#: contrib/sites/models.py:15
+msgid "site"
+msgstr "sivusto"
+
+#: contrib/sites/models.py:16
+msgid "sites"
+msgstr "sivustot"
+
+#: contrib/flatpages/models.py:8
+msgid ""
+"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
+msgstr ""
+"Esimerkki: '/tietoja/yhteystiedot/'. Varmista, että sekä alussa että lopussa "
+"on kauttaviiva."
+
+#: contrib/flatpages/models.py:9
+msgid "title"
+msgstr "otsikko"
+
+#: contrib/flatpages/models.py:10
+msgid "content"
+msgstr "sisältö"
+
+#: contrib/flatpages/models.py:11
+msgid "enable comments"
+msgstr "salli kommentit"
+
+#: contrib/flatpages/models.py:12
+msgid "template name"
+msgstr "mallipohjan nimi"
+
+#: contrib/flatpages/models.py:13
+msgid ""
+"Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
+"will use 'flatpages/default.html'."
+msgstr "Esimerkiksi: 'flatpages/yhteydenotto.html'. Jos tämä jätetään tyhjäksi, käytetään oletuspohjaa 'flatpages/default.html'."
+
+#: contrib/flatpages/models.py:14
+msgid "registration required"
+msgstr "vaaditaan rekisteröityminen"
+
+#: contrib/flatpages/models.py:14
+msgid "If this is checked, only logged-in users will be able to view the page."
+msgstr "Jos tämä kohta on valittu, vain sisäänkirjautuneet käyttäjät näkevät sivun."
+
+#: contrib/flatpages/models.py:18
+msgid "flat page"
+msgstr "tekstisivu"
+
+#: contrib/flatpages/models.py:19
+msgid "flat pages"
+msgstr "tekstisivut"
+
+#: contrib/redirects/models.py:7
+msgid "redirect from"
+msgstr "ohjaa osoitteesta"
+
+#: contrib/redirects/models.py:8
+msgid ""
+"This should be an absolute path, excluding the domain name. Example: '/"
+"events/search/'."
+msgstr ""
+"Tässä on käytettävä absoluuttista polkua ilman verkkotunnusta. Esimerkki: "
+"'\\\n"
+"events/search/'"
+
+#: contrib/redirects/models.py:9
+msgid "redirect to"
+msgstr "ohjaa osoitteeseen"
+
+#: contrib/redirects/models.py:10
+msgid ""
+"This can be either an absolute path (as above) or a full URL starting with "
+"'http://'."
+msgstr ""
+"Tässä on käytettävä joko absoluuttista polkua (kuten yllä) tai täydellistä "
+"'http://'-alkuista URL-osoitetta."
+
+#: contrib/redirects/models.py:13
+msgid "redirect"
+msgstr "edelleenohjaus"
+
+#: contrib/redirects/models.py:14
+msgid "redirects"
+msgstr "edelleenohjaukset"
+
+#: contrib/comments/models.py:67 contrib/comments/models.py:166
+msgid "object ID"
+msgstr "kohteen tunniste"
+
+#: contrib/comments/models.py:68
+msgid "headline"
+msgstr "otsikko"
+
+#: contrib/comments/models.py:69 contrib/comments/models.py:90
+#: contrib/comments/models.py:167
+msgid "comment"
+msgstr "kommentti"
+
+#: contrib/comments/models.py:70
+msgid "rating #1"
+msgstr "1. pisteytys"
+
+#: contrib/comments/models.py:71
+msgid "rating #2"
+msgstr "2. pisteytys"
+
+#: contrib/comments/models.py:72
+msgid "rating #3"
+msgstr "3. pisteytys"
+
+#: contrib/comments/models.py:73
+msgid "rating #4"
+msgstr "4. pisteytys"
+
+#: contrib/comments/models.py:74
+msgid "rating #5"
+msgstr "5. pisteytys"
+
+#: contrib/comments/models.py:75
+msgid "rating #6"
+msgstr "6. pisteytys"
+
+#: contrib/comments/models.py:76
+msgid "rating #7"
+msgstr "7. pisteytys"
+
+#: contrib/comments/models.py:77
+msgid "rating #8"
+msgstr "8. pisteytys"
+
+#: contrib/comments/models.py:82
+msgid "is valid rating"
+msgstr "on sallittu pisteytys"
+
+#: contrib/comments/models.py:83 contrib/comments/models.py:169
+msgid "date/time submitted"
+msgstr "lähetyshetki"
+
+#: contrib/comments/models.py:84 contrib/comments/models.py:170
+msgid "is public"
+msgstr "on julkinen"
+
+#: contrib/comments/models.py:86
+msgid "is removed"
+msgstr "on poistettu"
+
+#: contrib/comments/models.py:86
+msgid ""
+"Check this box if the comment is inappropriate. A \"This comment has been "
+"removed\" message will be displayed instead."
+msgstr ""
+"Rastita jos kommentti on asiaankuulumaton. Kommentin tilalla näytetään\n"
+"viesti \"Tämä kommentti on poistettu\"."
+
+#: contrib/comments/models.py:91
+msgid "comments"
+msgstr "kommentit"
+
+#: contrib/comments/models.py:131 contrib/comments/models.py:207
+msgid "Content object"
+msgstr "Kommentoitu kohde"
+
+#: contrib/comments/models.py:159
+#, python-format
+msgid ""
+"Posted by %(user)s at %(date)s\n"
+"\n"
+"%(comment)s\n"
+"\n"
+"http://%(domain)s%(url)s"
+msgstr ""
+" Kirjoittanut %(user)s, pvm %(date)s\\n\n"
+" \\n\n"
+" %(comment)s\\n\n"
+" \\n\n"
+" http://%(domain)s%(url)s"
+
+#: contrib/comments/models.py:168
+msgid "person's name"
+msgstr "henkilön nimi"
+
+#: contrib/comments/models.py:171
+msgid "ip address"
+msgstr "IP-osoite"
+
+#: contrib/comments/models.py:173
+msgid "approved by staff"
+msgstr "ylläpidon hyväksymä"
+
+#: contrib/comments/models.py:176
+msgid "free comment"
+msgstr "vapaa kommentti"
+
+#: contrib/comments/models.py:177
+msgid "free comments"
+msgstr "vapaat kommentit"
+
+#: contrib/comments/models.py:233
+msgid "score"
+msgstr "pisteet"
+
+#: contrib/comments/models.py:234
+msgid "score date"
+msgstr "pisteytyspäivä"
+
+#: contrib/comments/models.py:237
+msgid "karma score"
+msgstr "karma-pisteytys"
+
+#: contrib/comments/models.py:238
+msgid "karma scores"
+msgstr "karma-pisteytykset"
+
+#: contrib/comments/models.py:242
+#, python-format
+msgid "%(score)d rating by %(user)s"
+msgstr "%(score)d pistettä käyttäjältä %(user)s"
+
+#: contrib/comments/models.py:258
+#, python-format
+msgid ""
+"This comment was flagged by %(user)s:\n"
+"\n"
+"%(text)s"
+msgstr ""
+" %(user)s on merkinnyt tämän kommentin:\\n\n"
+" \\n\n"
+" %(text)s"
+
+#: contrib/comments/models.py:265
+msgid "flag date"
+msgstr "merkintäpäivä"
+
+#: contrib/comments/models.py:268
+msgid "user flag"
+msgstr "käyttäjän merkki"
+
+#: contrib/comments/models.py:269
+msgid "user flags"
+msgstr "käyttäjien merkit"
+
+#: contrib/comments/models.py:273
+#, python-format
+msgid "Flag by %r"
+msgstr "Käyttäjän %r merkki"
+
+#: contrib/comments/models.py:278
+msgid "deletion date"
+msgstr "poistamispäivä"
+
+#: contrib/comments/models.py:280
+msgid "moderator deletion"
+msgstr "valvojan poisto"
+
+#: contrib/comments/models.py:281
+msgid "moderator deletions"
+msgstr "valvojien poistot"
+
+#: contrib/comments/models.py:285
+#, python-format
+msgid "Moderator deletion by %r"
+msgstr "Valvojan %r poisto"
+
+#: contrib/comments/views/karma.py:19
+msgid "Anonymous users cannot vote"
+msgstr "Anonyymit käyttäjät eivät voi äänestää"
+
+#: contrib/comments/views/karma.py:23
+msgid "Invalid comment ID"
+msgstr "Kommentin tunniste on virheellinen"
+
+#: contrib/comments/views/karma.py:25
+msgid "No voting for yourself"
+msgstr "Itseään ei voi äänestää"
+
+#: contrib/comments/views/comments.py:27
+msgid ""
+"This rating is required because you've entered at least one other rating."
+msgstr "Tämä pisteytys on annettava, koska olet syöttänyt ainakin yhden muunkin pisteytyksen."
+
+#: contrib/comments/views/comments.py:111
+#, python-format
+msgid ""
+"This comment was posted by a user who has posted fewer than %(count)s "
+"comment:\n"
+"\n"
+"%(text)s"
+msgid_plural ""
+"This comment was posted by a user who has posted fewer than %(count)s "
+"comments:\n"
+"\n"
+"%(text)s"
+msgstr[0] ""
+msgstr[1] ""
+
+# Mitä "sketchy user" tarkoittaa?
+#: contrib/comments/views/comments.py:116
+#, python-format
+msgid ""
+"This comment was posted by a sketchy user:\n"
+"\n"
+"%(text)s"
+msgstr ""
+"Tämä on \"sketchy\"-käyttäjän kirjoittama kommentti:\n"
+"\n"
+"%(text)s"
+
+#: contrib/comments/views/comments.py:188
+#: contrib/comments/views/comments.py:280
+msgid "Only POSTs are allowed"
+msgstr "Vain POST-kutsut sallittu"
+
+#: contrib/comments/views/comments.py:192
+#: contrib/comments/views/comments.py:284
+msgid "One or more of the required fields wasn't submitted"
+msgstr "Yksi tai useampi vaadittu kenttä on jäänyt täyttämättä"
+
+#: contrib/comments/views/comments.py:196
+#: contrib/comments/views/comments.py:286
+msgid "Somebody tampered with the comment form (security violation)"
+msgstr "Kommenttilomaketta on käpälöity (turvallisuusrike)"
+
+#: contrib/comments/views/comments.py:206
+#: contrib/comments/views/comments.py:292
+msgid ""
+"The comment form had an invalid 'target' parameter -- the object ID was "
+"invalid"
+msgstr "Kommenttilomakkeen 'target'-parametri ei kelpaa -- kohteen ID oli virheellinen"
+
+#: contrib/comments/views/comments.py:257
+#: contrib/comments/views/comments.py:321
+msgid "The comment form didn't provide either 'preview' or 'post'"
+msgstr "Kommenttilomake ei pyytänyt esikatselua tai lähettämistä"
+
+#: contrib/comments/templates/comments/form.html:8
+msgid "Forgotten your password?"
+msgstr "Unohditko salasanasi?"
+
+#: contrib/comments/templates/comments/form.html:12
+msgid "Ratings"
+msgstr "Pisteytykset"
+
+#: contrib/comments/templates/comments/form.html:12
+#: contrib/comments/templates/comments/form.html:23
+msgid "Required"
+msgstr "Vaaditaan"
+
+#: contrib/comments/templates/comments/form.html:12
+#: contrib/comments/templates/comments/form.html:23
+msgid "Optional"
+msgstr "Vapaavalintainen"
+
+#: contrib/comments/templates/comments/form.html:23
+msgid "Post a photo"
+msgstr "Lähetä valokuva"
+
+#: contrib/comments/templates/comments/form.html:28
+#: contrib/comments/templates/comments/freeform.html:5
+msgid "Comment:"
+msgstr "Kommentti:"
+
+#: contrib/comments/templates/comments/form.html:35
+#: contrib/comments/templates/comments/freeform.html:10
+msgid "Preview comment"
+msgstr "Esikatsele kommenttia"
+
+#: contrib/comments/templates/comments/freeform.html:4
+msgid "Your name:"
+msgstr "Nimesi:"
+
+#: contrib/sessions/models.py:51
+msgid "session key"
+msgstr "istunnon avain"
+
+#: contrib/sessions/models.py:52
+msgid "session data"
+msgstr "istunnon tiedot"
+
+#: contrib/sessions/models.py:53
+msgid "expire date"
+msgstr "vanhenee"
+
+#: contrib/sessions/models.py:57
+msgid "session"
+msgstr "istunto"
+
+#: contrib/sessions/models.py:58
+msgid "sessions"
+msgstr "istunnot"
+
+#: contrib/contenttypes/models.py:20
+msgid "python model class name"
+msgstr "mallin python-luokan nimi"
+
+#: contrib/contenttypes/models.py:23
+msgid "content type"
+msgstr "sisältötyyppi"
+
+#: contrib/contenttypes/models.py:24
+msgid "content types"
+msgstr "sisältötyypit"
+
+#: forms/__init__.py:381
+#, python-format
+msgid "Ensure your text is less than %s character."
+msgid_plural "Ensure your text is less than %s characters."
+msgstr[0] "Varmista, että tekstin pituus on vähemmän kuin %s merkki."
+msgstr[1] "Varmista, että teksti pituus on vähemmän kuin %s merkkiä."
+
+#: forms/__init__.py:386
+msgid "Line breaks are not allowed here."
+msgstr "Rivinvaihtoja ei voi käyttää."
+
+#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599
+#, python-format
+msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
+msgstr "Valinta ei kelpaa; '%(data)s' ei löydy vaihtoehtojen %(choices)s joukosta."
+
+#: forms/__init__.py:663
+msgid "The submitted file is empty."
+msgstr "Lähetetty tiedosto on tyhjä."
+
+#: forms/__init__.py:719
+msgid "Enter a whole number between -32,768 and 32,767."
+msgstr "Syötä kokonaisluku väliltä -32768 ja 32767."
+
+#: forms/__init__.py:729
+msgid "Enter a positive number."
+msgstr "Syötä positiivinen kokonaisluku."
+
+#: forms/__init__.py:739
+msgid "Enter a whole number between 0 and 32,767."
+msgstr "Syötä kokonaisluku väliltä 0 ja 32767."
+
+#: utils/dates.py:6
+msgid "Monday"
+msgstr "maanantai"
+
+#: utils/dates.py:6
+msgid "Tuesday"
+msgstr "tiistai"
+
+#: utils/dates.py:6
+msgid "Wednesday"
+msgstr "keskiviikko"
+
+#: utils/dates.py:6
+msgid "Thursday"
+msgstr "torstai"
+
+#: utils/dates.py:6
+msgid "Friday"
+msgstr "perjantai"
+
+#: utils/dates.py:7
+msgid "Saturday"
+msgstr "lauantai"
+
+#: utils/dates.py:7
+msgid "Sunday"
+msgstr "sunnuntai"
+
+#: utils/dates.py:14
+msgid "January"
+msgstr "tammikuu"
+
+#: utils/dates.py:14
+msgid "February"
+msgstr "helmikuu"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "March"
+msgstr "maaliskuu"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "April"
+msgstr "huhtikuu"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "May"
+msgstr "toukokuu"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "June"
+msgstr "kesäkuu"
+
+#: utils/dates.py:15 utils/dates.py:27
+msgid "July"
+msgstr "heinäkuu"
+
+#: utils/dates.py:15
+msgid "August"
+msgstr "elokuu"
+
+#: utils/dates.py:15
+msgid "September"
+msgstr "syyskuu"
+
+#: utils/dates.py:15
+msgid "October"
+msgstr "lokakuu"
+
+#: utils/dates.py:15
+msgid "November"
+msgstr "marraskuu"
+
+#: utils/dates.py:16
+msgid "December"
+msgstr "joulukuu"
+
+#: utils/dates.py:19
+msgid "jan"
+msgstr "tam"
+
+#: utils/dates.py:19
+msgid "feb"
+msgstr "hel"
+
+#: utils/dates.py:19
+msgid "mar"
+msgstr "maa"
+
+#: utils/dates.py:19
+msgid "apr"
+msgstr "huh"
+
+#: utils/dates.py:19
+msgid "may"
+msgstr "tou"
+
+#: utils/dates.py:19
+msgid "jun"
+msgstr "kes"
+
+#: utils/dates.py:20
+msgid "jul"
+msgstr "hei"
+
+#: utils/dates.py:20
+msgid "aug"
+msgstr "elo"
+
+#: utils/dates.py:20
+msgid "sep"
+msgstr "syy"
+
+#: utils/dates.py:20
+msgid "oct"
+msgstr "lok"
+
+#: utils/dates.py:20
+msgid "nov"
+msgstr "mar"
+
+#: utils/dates.py:20
+msgid "dec"
+msgstr "jou"
+
+#: utils/dates.py:27
+msgid "Jan."
+msgstr "tammi"
+
+#: utils/dates.py:27
+msgid "Feb."
+msgstr "helmi"
+
+#: utils/dates.py:28
+msgid "Aug."
+msgstr "elo"
+
+#: utils/dates.py:28
+msgid "Sept."
+msgstr "syys"
+
+#: utils/dates.py:28
+msgid "Oct."
+msgstr "loka"
+
+#: utils/dates.py:28
+msgid "Nov."
+msgstr "marras"
+
+#: utils/dates.py:28
+msgid "Dec."
+msgstr "joulu"
+
+#: utils/timesince.py:12
+msgid "year"
+msgid_plural "years"
+msgstr[0] ""
+msgstr[1] ""
+
+#: utils/timesince.py:13
+msgid "month"
+msgid_plural "months"
+msgstr[0] ""
+msgstr[1] ""
+
+#: utils/timesince.py:14
+msgid "week"
+msgid_plural "weeks"
+msgstr[0] ""
+msgstr[1] ""
+
+#: utils/timesince.py:15
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: utils/timesince.py:16
+msgid "hour"
+msgid_plural "hours"
+msgstr[0] ""
+msgstr[1] ""
+
+#: utils/timesince.py:17
+msgid "minute"
+msgid_plural "minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: utils/translation/trans_real.py:362
+msgid "DATE_FORMAT"
+msgstr "j.n.Y"
+
+#: utils/translation/trans_real.py:363
+msgid "DATETIME_FORMAT"
+msgstr "j.n.Y G:i"
+
+#: utils/translation/trans_real.py:364
+msgid "TIME_FORMAT"
+msgstr "G:i"
+
+#: utils/translation/trans_real.py:380
+msgid "YEAR_MONTH_FORMAT"
+msgstr "N j, Y"
+
+#: utils/translation/trans_real.py:381
+#, fuzzy
+msgid "MONTH_DAY_FORMAT"
+msgstr "N j, Y"
+
+#: template/defaultfilters.py:401
+msgid "yes,no,maybe"
+msgstr "kyllä,ei,ehkä"
diff --git a/django/conf/locale/fi/LC_MESSAGES/djangojs.mo b/django/conf/locale/fi/LC_MESSAGES/djangojs.mo
new file mode 100644
index 0000000000..34b397e4ba
--- /dev/null
+++ b/django/conf/locale/fi/LC_MESSAGES/djangojs.mo
Binary files differ
diff --git a/django/conf/locale/fi/LC_MESSAGES/djangojs.po b/django/conf/locale/fi/LC_MESSAGES/djangojs.po
new file mode 100644
index 0000000000..35aa82e893
--- /dev/null
+++ b/django/conf/locale/fi/LC_MESSAGES/djangojs.po
@@ -0,0 +1,110 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-12-09 11:51+0100\n"
+"PO-Revision-Date: 2006-08-05 15:27+0300\n"
+"Last-Translator: Antti Kaihola <akaihola@ambitone.com>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: contrib/admin/media/js/SelectFilter2.js:33
+#, perl-format
+msgid "Available %s"
+msgstr "Mahdolliset %s"
+
+#: contrib/admin/media/js/SelectFilter2.js:41
+msgid "Choose all"
+msgstr "Valitse kaikki"
+
+#: contrib/admin/media/js/SelectFilter2.js:46
+msgid "Add"
+msgstr "Lisää uusi"
+
+#: contrib/admin/media/js/SelectFilter2.js:48
+msgid "Remove"
+msgstr "Poista"
+
+#: contrib/admin/media/js/SelectFilter2.js:53
+#, perl-format
+msgid "Chosen %s"
+msgstr "Valitut %s"
+
+#: contrib/admin/media/js/SelectFilter2.js:54
+msgid "Select your choice(s) and click "
+msgstr "Valitse vasemmalta ja napsauta "
+
+#: contrib/admin/media/js/SelectFilter2.js:59
+msgid "Clear all"
+msgstr "Tyhjennä kaikki"
+
+#: contrib/admin/media/js/dateparse.js:26
+#: contrib/admin/media/js/calendar.js:24
+msgid ""
+"January February March April May June July August September October November "
+"December"
+msgstr ""
+"Tammikuu Helmikuu Maaliskuu Huhtikuu Toukokuu Kesäkuu Heinäkuu Elokuu "
+"Syyskuu Lokakuu Marraskuu Joulukuu"
+
+#: contrib/admin/media/js/dateparse.js:27
+msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
+msgstr "Sunnuntai Maanantai Tiistai Keskiviikko Torstai Perjantai Lauantai"
+
+#: contrib/admin/media/js/calendar.js:25
+msgid "S M T W T F S"
+msgstr "S M T K T P L"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
+msgid "Now"
+msgstr "Nyt"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
+msgid "Clock"
+msgstr "Kello"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
+msgid "Choose a time"
+msgstr "Valitse kellonaika"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
+msgid "Midnight"
+msgstr "24"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
+msgid "6 a.m."
+msgstr "06"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
+msgid "Noon"
+msgstr "12"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
+msgid "Cancel"
+msgstr "Peruuta"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
+msgid "Today"
+msgstr "Tänään"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
+msgid "Calendar"
+msgstr "Kalenteri"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
+msgid "Yesterday"
+msgstr "Eilen"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
+msgid "Tomorrow"
+msgstr "Huomenna"
diff --git a/django/conf/locale/ja/LC_MESSAGES/django.mo b/django/conf/locale/ja/LC_MESSAGES/django.mo
index 34b80e976e..e6725c1140 100644
--- a/django/conf/locale/ja/LC_MESSAGES/django.mo
+++ b/django/conf/locale/ja/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/ja/LC_MESSAGES/django.po b/django/conf/locale/ja/LC_MESSAGES/django.po
index dbc3de5f53..a55af3b45d 100644
--- a/django/conf/locale/ja/LC_MESSAGES/django.po
+++ b/django/conf/locale/ja/LC_MESSAGES/django.po
@@ -1,14 +1,13 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# Translation of django.po to japanese.
+# Copyright (C) 2005,2006 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# makoto tsuyuki <mtsuyuki@gmail.com>, 2005,2006.
#
-#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-05-18 00:21+0900\n"
+"POT-Creation-Date: 2006-10-21 20:42+0900\n"
"PO-Revision-Date: 2006-05-18 00:28+0900\n"
"Last-Translator: makoto tsuyuki <mtsuyuki@gmail.com>\n"
"Language-Team: Japanese <django-ja@googlegroups.com>\n"
@@ -16,113 +15,135 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: conf/global_settings.py:37
+#: conf/global_settings.py:39
+msgid "Arabic"
+msgstr "アラビア語"
+
+#: conf/global_settings.py:40
msgid "Bengali"
msgstr "ベンガル語"
-#: conf/global_settings.py:38
+#: conf/global_settings.py:41
msgid "Czech"
msgstr "ãƒã‚§ã‚³èªž"
-#: conf/global_settings.py:39
+#: conf/global_settings.py:42
msgid "Welsh"
msgstr "ウェールズ語"
-#: conf/global_settings.py:40
+#: conf/global_settings.py:43
msgid "Danish"
msgstr "デンマーク語"
-#: conf/global_settings.py:41
+#: conf/global_settings.py:44
msgid "German"
msgstr "ドイツ語"
-#: conf/global_settings.py:42
+#: conf/global_settings.py:45
msgid "Greek"
msgstr "ギリシャ語"
-#: conf/global_settings.py:43
+#: conf/global_settings.py:46
msgid "English"
msgstr "英語"
-#: conf/global_settings.py:44
+#: conf/global_settings.py:47
msgid "Spanish"
msgstr "スペイン語"
-#: conf/global_settings.py:45
+#: conf/global_settings.py:48
+msgid "Argentinean Spanish"
+msgstr "アルゼンãƒãƒ³ã‚¹ãƒšã‚¤ãƒ³èªž"
+
+#: conf/global_settings.py:49
+msgid "Finnish"
+msgstr "フィンランド語"
+
+#: conf/global_settings.py:50
msgid "French"
msgstr "フランス語"
-#: conf/global_settings.py:46
+#: conf/global_settings.py:51
msgid "Galician"
msgstr "ガリシア語"
-#: conf/global_settings.py:47
+#: conf/global_settings.py:52
msgid "Hungarian"
msgstr "ãƒãƒ³ã‚¬ãƒªãƒ¼èªž"
-#: conf/global_settings.py:48
+#: conf/global_settings.py:53
msgid "Hebrew"
msgstr "ヘブライ語"
-#: conf/global_settings.py:49
+#: conf/global_settings.py:54
msgid "Icelandic"
msgstr "アイスランド語"
-#: conf/global_settings.py:50
+#: conf/global_settings.py:55
msgid "Italian"
msgstr "イタリア語"
-#: conf/global_settings.py:51
+#: conf/global_settings.py:56
msgid "Japanese"
msgstr "日本語"
-#: conf/global_settings.py:52
+#: conf/global_settings.py:57
msgid "Dutch"
msgstr "オランダ語"
-#: conf/global_settings.py:53
+#: conf/global_settings.py:58
msgid "Norwegian"
msgstr "ノルウェー語"
-#: conf/global_settings.py:54
+#: conf/global_settings.py:59
+msgid "Polish"
+msgstr "ãƒãƒ¼ãƒ©ãƒ³ãƒ‰èªž"
+
+#: conf/global_settings.py:60
msgid "Brazilian"
msgstr "ブラジル語"
-#: conf/global_settings.py:55
+#: conf/global_settings.py:61
msgid "Romanian"
msgstr "ルーマニア語"
-#: conf/global_settings.py:56
+#: conf/global_settings.py:62
msgid "Russian"
msgstr "ロシア語"
-#: conf/global_settings.py:57
+#: conf/global_settings.py:63
msgid "Slovak"
msgstr "スロãƒã‚­ã‚¢èªž"
-#: conf/global_settings.py:58
-#, fuzzy
+#: conf/global_settings.py:64
msgid "Slovenian"
msgstr "スロヴェニア語"
-#: conf/global_settings.py:59
+#: conf/global_settings.py:65
msgid "Serbian"
msgstr "セルビア語"
-#: conf/global_settings.py:60
+#: conf/global_settings.py:66
msgid "Swedish"
msgstr "スウェーデン語"
-#: conf/global_settings.py:61
-#, fuzzy
+#: conf/global_settings.py:67
+msgid "Tamil"
+msgstr "タミル語"
+
+#: conf/global_settings.py:68
+msgid "Turkish"
+msgstr "トルコ語"
+
+#: conf/global_settings.py:69
msgid "Ukrainian"
msgstr "ウクライナ語"
-#: conf/global_settings.py:62
+#: conf/global_settings.py:70
msgid "Simplified Chinese"
msgstr "簡体字中国語"
-#: conf/global_settings.py:63
+#: conf/global_settings.py:71
msgid "Traditional Chinese"
msgstr "ç¹ä½“字中国語"
@@ -136,7 +157,7 @@ msgstr ""
"<ul>\n"
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
-#: contrib/admin/filterspecs.py:143
+#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169
msgid "All"
msgstr "å…¨ã¦"
@@ -210,10 +231,11 @@ msgid "We're sorry, but the requested page could not be found."
msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ãпޢã—ã®ãƒšãƒ¼ã‚¸ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
#: contrib/admin/templates/admin/500.html:4
-#: contrib/admin/templates/admin/base.html:28
+#: contrib/admin/templates/admin/base.html:30
#: contrib/admin/templates/admin/change_form.html:13
#: contrib/admin/templates/admin/change_list.html:6
#: contrib/admin/templates/admin/delete_confirmation.html:6
+#: contrib/admin/templates/admin/invalid_setup.html:4
#: contrib/admin/templates/admin/object_history.html:5
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
#: contrib/admin/templates/registration/logged_out.html:4
@@ -244,11 +266,11 @@ msgstr ""
"エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚エラーをサイトã®ç®¡ç†è€…ã«ãƒ¡ãƒ¼ãƒ«ã§å ±å‘Šã—ã¾ã—ãŸã®ã§ã€è¿‘ã„"
"ã†ã¡ã«ä¿®æ­£ã•れるã¯ãšã§ã™ã€‚ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。"
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
msgid "Welcome,"
msgstr "よã†ã“ã"
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/admin/change_list.html:5
#: contrib/admin/templates/admin/delete_confirmation.html:3
@@ -259,7 +281,7 @@ msgstr "よã†ã“ã"
msgid "Documentation"
msgstr "ドキュメント"
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/admin/change_list.html:5
#: contrib/admin/templates/admin/delete_confirmation.html:3
@@ -279,7 +301,7 @@ msgstr "ドキュメント"
msgid "Change password"
msgstr "パスワードã®å¤‰æ›´"
-#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/base.html:25
#: contrib/admin/templates/admin/change_form.html:10
#: contrib/admin/templates/admin/change_list.html:5
#: contrib/admin/templates/admin/delete_confirmation.html:3
@@ -296,7 +318,7 @@ msgstr "パスワードã®å¤‰æ›´"
#: contrib/admin/templates/admin_doc/view_index.html:5
#: contrib/admin/templates/registration/password_change_done.html:3
#: contrib/admin/templates/registration/password_change_form.html:3
-#: contrib/comments/templates/comments/form.html:8
+#: contrib/comments/templates/comments/form.html:6
msgid "Log out"
msgstr "ログアウト"
@@ -306,7 +328,7 @@ msgstr "Django サイト管ç†"
#: contrib/admin/templates/admin/base_site.html:7
msgid "Django administration"
-msgstr "Django ã®ç®¡ç†"
+msgstr "Django 管ç†ã‚µã‚¤ãƒˆ"
#: contrib/admin/templates/admin/change_form.html:15
#: contrib/admin/templates/admin/index.html:28
@@ -349,22 +371,22 @@ msgstr "削除"
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
msgid ""
-"Deleting the %(object_name)s '%(object)s' would result in deleting related "
-"objects, but your account doesn't have permission to delete the following "
-"types of objects:"
+"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
+"related objects, but your account doesn't have permission to delete the "
+"following types of objects:"
msgstr ""
-"%(object_name)s '%(object)s' ã®å‰Šé™¤æ™‚ã«é–¢é€£ã¥ã‘られãŸã‚ªãƒ–ジェクトも削除ã—よã†"
-"ã¨ã—ã¾ã—ãŸãŒã€ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã¯ä»¥ä¸‹ã®ã‚¿ã‚¤ãƒ—ã®ã‚ªãƒ–ジェクトを削除ã™ã‚‹ãƒ‘ー"
-"ミッションãŒã‚りã¾ã›ã‚“:"
+"%(object_name)s '%(escaped_object)s' ã®å‰Šé™¤æ™‚ã«é–¢é€£ã¥ã‘られãŸã‚ªãƒ–ジェクトも削"
+"除ã—よã†ã¨ã—ã¾ã—ãŸãŒã€ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã¯ä»¥ä¸‹ã®ã‚¿ã‚¤ãƒ—ã®ã‚ªãƒ–ジェクトを削除"
+"ã™ã‚‹ãƒ‘ーミッションãŒã‚りã¾ã›ã‚“:"
#: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format
msgid ""
-"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
-"the following related items will be deleted:"
+"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
+"All of the following related items will be deleted:"
msgstr ""
-"%(object_name)s \"%(object)s\"を削除ã—ã¾ã™ã‹ï¼Ÿ 関連ã¥ã‘られã¦ã„る以下ã®ã‚ªãƒ–"
-"ジェクトも全ã¦å‰Šé™¤ã•れã¾ã™:"
+"%(object_name)s \"%(escaped_object)s\"を削除ã—ã¾ã™ã‹ï¼Ÿ 関連ã¥ã‘られã¦ã„る以下"
+"ã®ã‚ªãƒ–ジェクトも全ã¦å‰Šé™¤ã•れã¾ã™:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure"
@@ -372,14 +394,23 @@ msgstr "ã¯ã„。"
#: contrib/admin/templates/admin/filter.html:2
#, python-format
-msgid " By %(title)s "
-msgstr "%(title)s ã§çµžã‚Šè¾¼ã‚€"
+msgid " By %(filter_title)s "
+msgstr "%(filter_title)s ã§çµžã‚Šè¾¼ã‚€"
+
+#: contrib/admin/templates/admin/filters.html:4
+msgid "Filter"
+msgstr "フィルタ"
#: contrib/admin/templates/admin/index.html:17
#, python-format
msgid "Models available in the %(name)s application."
msgstr "%(name)s アプリケーションã§åˆ©ç”¨å¯èƒ½ãªãƒ¢ãƒ‡ãƒ«"
+#: contrib/admin/templates/admin/index.html:18
+#, python-format
+msgid "%(name)s"
+msgstr "%(name)s"
+
#: contrib/admin/templates/admin/index.html:34
msgid "Change"
msgstr "変更"
@@ -400,6 +431,15 @@ msgstr "æ“作"
msgid "None available"
msgstr "利用ä¸å¯"
+#: contrib/admin/templates/admin/invalid_setup.html:8
+msgid ""
+"Something's wrong with your database installation. Make sure the appropriate "
+"database tables have been created, and make sure the database is readable by "
+"the appropriate user."
+msgstr ""
+"データベースã®è¨­å®šã«å•題ãŒã‚るよã†ã§ã™ã€‚é©åˆ‡ãªãƒ†ãƒ¼ãƒ–ルãŒä½œã‚‰ã‚Œã¦ã„ã‚‹ã“ã¨ã€é©"
+"切ãªãƒ¦ãƒ¼ã‚¶ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
+
#: contrib/admin/templates/admin/login.html:17
#: contrib/comments/templates/comments/form.html:6
#: contrib/comments/templates/comments/form.html:8
@@ -407,7 +447,7 @@ msgid "Username:"
msgstr "ユーザå:"
#: contrib/admin/templates/admin/login.html:20
-#: contrib/comments/templates/comments/form.html:6
+#: contrib/comments/templates/comments/form.html:8
msgid "Password:"
msgstr "パスワード:"
@@ -416,7 +456,7 @@ msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "<a href=\"/password_reset/\">パスワードをãŠå¿˜ã‚Œã§ã™ã‹</a>?"
#: contrib/admin/templates/admin/login.html:25
-#: contrib/admin/views/decorators.py:23
+#: contrib/admin/views/decorators.py:24
msgid "Log in"
msgstr "ログイン"
@@ -444,10 +484,26 @@ msgstr ""
"ã“ã®ã‚ªãƒ–ジェクトã«ã¯å¤‰æ›´å±¥æ­´ãŒã‚りã¾ã›ã‚“。ãŠãらãã“ã®ç®¡ç†ã‚µã‚¤ãƒˆã§è¿½åŠ ã—ãŸã‚‚"
"ã®ã§ã¯ã‚りã¾ã›ã‚“。"
+#: contrib/admin/templates/admin/pagination.html:10
+msgid "Show all"
+msgstr "全件表示"
+
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
msgstr "検索"
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "1 result"
+msgid_plural "%(counter)s results"
+msgstr[0] "1 ä»¶"
+msgstr[1] "%(counter)s ä»¶"
+
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "%(full_result_count)s total"
+msgstr "å…¨ %(full_result_count)s ä»¶"
+
#: contrib/admin/templates/admin/submit_line.html:4
msgid "Save as new"
msgstr "æ–°è¦ä¿å­˜"
@@ -464,6 +520,30 @@ msgstr "ä¿å­˜ã—ã¦ç·¨é›†ã‚’ç¶šã‘ã‚‹"
msgid "Save"
msgstr "ä¿å­˜"
+#: contrib/admin/templates/admin/auth/user/add_form.html:6
+msgid ""
+"First, enter a username and password. Then, you'll be able to edit more user "
+"options."
+msgstr ""
+"ã¾ãšãƒ¦ãƒ¼ã‚¶åã¨ãƒ‘スワードを登録ã—ã¦ãã ã•ã„。ãã®å¾Œè©³ç´°æƒ…å ±ãŒç·¨é›†å¯èƒ½ã«ãªã‚Šã¾"
+"ã™ã€‚"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:12
+msgid "Username"
+msgstr "ユーザå"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:18
+msgid "Password"
+msgstr "パスワード"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:23
+msgid "Password (again)"
+msgstr "パスワード(確èªç”¨)"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:24
+msgid "Enter the same password as above, for verification."
+msgstr "確èªã®ãŸã‚ã€å†åº¦ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。"
+
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
msgid "Bookmarklets"
msgstr "ブックマークレット"
@@ -572,7 +652,7 @@ msgstr "æ–°ã—ã„パスワード:"
#: contrib/admin/templates/registration/password_change_form.html:21
msgid "Confirm password:"
-msgstr "æ–°ã—ã„パスワード (ã‚‚ã†ä¸€åº¦) :"
+msgstr "æ–°ã—ã„パスワード (確èªç”¨) :"
#: contrib/admin/templates/registration/password_change_form.html:23
msgid "Change my password"
@@ -663,19 +743,32 @@ msgstr "ç¾åœ¨:"
msgid "Change:"
msgstr "変更:"
-#: contrib/admin/templatetags/admin_list.py:228
+#: contrib/admin/templatetags/admin_list.py:230
msgid "All dates"
msgstr "ã„ã¤ã§ã‚‚"
-#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
-#: contrib/auth/forms.py:41
+#: contrib/admin/views/auth.py:17 contrib/admin/views/main.py:257
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was added successfully."
+msgstr "%(name)s \"%(obj)s\" を追加ã—ã¾ã—ãŸã€‚"
+
+#: contrib/admin/views/auth.py:22 contrib/admin/views/main.py:261
+#: contrib/admin/views/main.py:347
+msgid "You may edit it again below."
+msgstr "ç¶šã‘ã¦ç·¨é›†ã§ãã¾ã™ã€‚"
+
+#: contrib/admin/views/auth.py:28
+msgid "Add user"
+msgstr "ユーザを追加"
+
+#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:59
msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
msgstr ""
"æ­£ã—ã„ユーザåã¨ãƒ‘スワードを入力ã—ã¦ãã ã•ã„ (å¤§æ–‡å­—å°æ–‡å­—ã¯åŒºåˆ¥ã—ã¾ã™) 。"
-#: contrib/admin/views/decorators.py:61
+#: contrib/admin/views/decorators.py:62
msgid ""
"Please log in again, because your session has expired. Don't worry: Your "
"submission has been saved."
@@ -683,7 +776,7 @@ msgstr ""
"å†ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ãã ã•ã„ã€‚ãƒ­ã‚°ã‚¤ãƒ³ã‚»ãƒƒã‚·ãƒ§ãƒ³ãŒæœ‰åŠ¹æœŸé–“åˆ‡ã‚Œã—ã¦ã—ã¾ã„ã¾ã—ãŸã€‚å…¥"
"力データã¯å¤±ã‚れã¦ãŠã‚Šã¾ã›ã‚“ã®ã§ã”安心ãã ã•ã„。"
-#: contrib/admin/views/decorators.py:68
+#: contrib/admin/views/decorators.py:69
msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
@@ -691,188 +784,252 @@ msgstr ""
"ブラウザãŒã‚¯ãƒƒã‚­ãƒ¼ã®ä½¿ç”¨ã‚’許å¯ã—ã¦ã„ãªã„よã†ã§ã™ã€‚クッキーã®ä½¿ç”¨ã‚’許å¯ã—ã¦ã€"
"ã‚‚ã†ä¸€åº¦ã“ã®ãƒšãƒ¼ã‚¸ã‚’表示ã—ã¦ãã ã•ã„。"
-#: contrib/admin/views/decorators.py:82
+#: contrib/admin/views/decorators.py:83
msgid "Usernames cannot contain the '@' character."
msgstr "ユーザåã«ã¯ '@' ã‚’å«ã‚られã¾ã›ã‚“。"
-#: contrib/admin/views/decorators.py:84
+#: contrib/admin/views/decorators.py:85
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
msgstr "メールアドレスã¯ãƒ¦ãƒ¼ã‚¶åã§ã¯ã‚りã¾ã›ã‚“。 '%s' を試ã—ã¦ã¿ã¦ãã ã•ã„。"
-#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
-#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
-#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
+#: contrib/admin/views/doc.py:46 contrib/admin/views/doc.py:48
+#: contrib/admin/views/doc.py:50
+msgid "tag:"
+msgstr "ã‚¿ã‚°"
+
+#: contrib/admin/views/doc.py:77 contrib/admin/views/doc.py:79
+#: contrib/admin/views/doc.py:81
+msgid "filter:"
+msgstr "フィルタ"
+
+#: contrib/admin/views/doc.py:135 contrib/admin/views/doc.py:137
+#: contrib/admin/views/doc.py:139
+msgid "view:"
+msgstr "ビュー"
+
+#: contrib/admin/views/doc.py:164
+#, python-format
+msgid "App %r not found"
+msgstr "アプリケーション %r ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
+
+#: contrib/admin/views/doc.py:171
+#, python-format
+msgid "Model %r not found in app %r"
+msgstr "モデル %r ㌠%r アプリケーションã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
+
+#: contrib/admin/views/doc.py:183
+#, python-format
+msgid "the related `%s.%s` object"
+msgstr "`%s.%s` (関連オブジェクト)"
+
+#: contrib/admin/views/doc.py:183 contrib/admin/views/doc.py:205
+#: contrib/admin/views/doc.py:219 contrib/admin/views/doc.py:224
+msgid "model:"
+msgstr "モデル :"
+
+#: contrib/admin/views/doc.py:214
+#, python-format
+msgid "related `%s.%s` objects"
+msgstr "`%s.%s` (関連オブジェクト)"
+
+#: contrib/admin/views/doc.py:219
+#, python-format
+msgid "all %s"
+msgstr "å…¨ã¦ã® %s"
+
+#: contrib/admin/views/doc.py:224
+#, python-format
+msgid "number of %s"
+msgstr "%s ã®æ•°"
+
+#: contrib/admin/views/doc.py:229
+#, python-format
+msgid "Fields on %s objects"
+msgstr "%s ã®ãƒ•ィールド"
+
+#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:303 contrib/admin/views/doc.py:309
+#: contrib/admin/views/doc.py:310 contrib/admin/views/doc.py:312
msgid "Integer"
msgstr "æ•´æ•°"
-#: contrib/admin/views/doc.py:278
+#: contrib/admin/views/doc.py:292
msgid "Boolean (Either True or False)"
msgstr "ブール値 (真: True ã¾ãŸã¯å½: False)"
-#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
+#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:311
#, python-format
msgid "String (up to %(maxlength)s)"
msgstr "文字列 ( %(maxlength)s å­—ã¾ã§ )"
-#: contrib/admin/views/doc.py:280
+#: contrib/admin/views/doc.py:294
msgid "Comma-separated integers"
msgstr "ã‚«ãƒ³ãƒžåŒºåˆ‡ã‚Šã®æ•´æ•°"
-#: contrib/admin/views/doc.py:281
+#: contrib/admin/views/doc.py:295
msgid "Date (without time)"
msgstr "日付"
-#: contrib/admin/views/doc.py:282
+#: contrib/admin/views/doc.py:296
msgid "Date (with time)"
msgstr "日時"
-#: contrib/admin/views/doc.py:283
+#: contrib/admin/views/doc.py:297
msgid "E-mail address"
msgstr "メールアドレス"
-#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
+#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:302
msgid "File path"
msgstr "ファイルã®å ´æ‰€"
-#: contrib/admin/views/doc.py:285
+#: contrib/admin/views/doc.py:300
msgid "Decimal number"
msgstr "10 進数 (å°æ•°å¯)"
-#: contrib/admin/views/doc.py:289 contrib/comments/models.py:85
+#: contrib/admin/views/doc.py:304 contrib/comments/models.py:85
msgid "IP address"
msgstr "IP アドレス"
-#: contrib/admin/views/doc.py:291
+#: contrib/admin/views/doc.py:306
msgid "Boolean (Either True, False or None)"
msgstr "ブール値 (真: True ã€å½: False ã¾ãŸã¯ None)"
-#: contrib/admin/views/doc.py:292
+#: contrib/admin/views/doc.py:307
msgid "Relation to parent model"
msgstr "親モデルã¸ã®ãƒªãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³"
-#: contrib/admin/views/doc.py:293
+#: contrib/admin/views/doc.py:308
msgid "Phone number"
msgstr "電話番å·"
-#: contrib/admin/views/doc.py:298
+#: contrib/admin/views/doc.py:313
msgid "Text"
msgstr "テキスト"
-#: contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:314
msgid "Time"
msgstr "時刻"
-#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
+#: contrib/admin/views/doc.py:315 contrib/flatpages/models.py:7
msgid "URL"
msgstr "URL"
-#: contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:316
msgid "U.S. state (two uppercase letters)"
msgstr "アメリカã®å·ž (大文字二文字ã§)"
-#: contrib/admin/views/doc.py:302
+#: contrib/admin/views/doc.py:317
msgid "XML text"
msgstr "XMLテキスト"
-#: contrib/admin/views/main.py:226
-msgid "Site administration"
-msgstr "サイト管ç†"
-
-#: contrib/admin/views/main.py:260
+#: contrib/admin/views/doc.py:343
#, python-format
-msgid "The %(name)s \"%(obj)s\" was added successfully."
-msgstr "%(name)s \"%(obj)s\" を追加ã—ã¾ã—ãŸã€‚"
+msgid "%s does not appear to be a urlpattern object"
+msgstr "%s ã¯urlpatternオブジェクトã§ã¯ç„¡ã„よã†ã§ã™"
-#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
-msgid "You may edit it again below."
-msgstr "ç¶šã‘ã¦ç·¨é›†ã§ãã¾ã™ã€‚"
+#: contrib/admin/views/main.py:223
+msgid "Site administration"
+msgstr "サイト管ç†"
-#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
+#: contrib/admin/views/main.py:271 contrib/admin/views/main.py:356
#, python-format
msgid "You may add another %s below."
msgstr "ç¶šã‘ã¦åˆ¥ã® %s を追加ã§ãã¾ã™ã€‚"
-#: contrib/admin/views/main.py:290
+#: contrib/admin/views/main.py:289
#, python-format
msgid "Add %s"
msgstr "%s を追加"
-#: contrib/admin/views/main.py:336
+#: contrib/admin/views/main.py:335
#, python-format
msgid "Added %s."
msgstr "%s を追加ã—ã¾ã—ãŸã€‚"
-#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
+#: contrib/admin/views/main.py:339
msgid "and"
msgstr "ã¨"
-#: contrib/admin/views/main.py:338
+#: contrib/admin/views/main.py:337
#, python-format
msgid "Changed %s."
msgstr "%s を変更ã—ã¾ã—ãŸã€‚"
-#: contrib/admin/views/main.py:340
+#: contrib/admin/views/main.py:339
#, python-format
msgid "Deleted %s."
msgstr "%s を削除ã—ã¾ã—ãŸã€‚"
-#: contrib/admin/views/main.py:343
+#: contrib/admin/views/main.py:342
msgid "No fields changed."
msgstr "変更ã¯ã‚りã¾ã›ã‚“ã§ã—ãŸã€‚"
-#: contrib/admin/views/main.py:346
+#: contrib/admin/views/main.py:345
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr "%(name)s \"%(obj)s\" を変更ã—ã¾ã—ãŸã€‚"
-#: contrib/admin/views/main.py:354
+#: contrib/admin/views/main.py:353
#, python-format
msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr "%(name)s \"%(obj)s\" を追加ã—ã¾ã—ãŸã€‚ç¶šã‘ã¦ç·¨é›†ã§ãã¾ã™ã€‚"
-#: contrib/admin/views/main.py:392
+#: contrib/admin/views/main.py:391
#, python-format
msgid "Change %s"
msgstr "%s を変更"
-#: contrib/admin/views/main.py:470
+#: contrib/admin/views/main.py:473
#, python-format
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
msgstr "%(name)s ã« %(fieldname)s ãŒä¸€ã¤ä»¥ä¸Šã‚りã¾ã™: %(obj)s"
-#: contrib/admin/views/main.py:475
+#: contrib/admin/views/main.py:478
#, python-format
msgid "One or more %(fieldname)s in %(name)s:"
msgstr "%(name)s ã« %(fieldname)s ãŒä¸€ã¤ä»¥ä¸Šã‚りã¾ã™:"
-#: contrib/admin/views/main.py:508
+#: contrib/admin/views/main.py:511
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "%(name)s \"%(obj)s\" を削除ã—ã¾ã—ãŸã€‚"
-#: contrib/admin/views/main.py:511
+#: contrib/admin/views/main.py:514
msgid "Are you sure?"
msgstr "よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-#: contrib/admin/views/main.py:533
+#: contrib/admin/views/main.py:536
#, python-format
msgid "Change history: %s"
msgstr "変更履歴: %s"
-#: contrib/admin/views/main.py:565
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s"
msgstr "%s ã‚’é¸æŠž"
-#: contrib/admin/views/main.py:565
+#: contrib/admin/views/main.py:570
#, python-format
msgid "Select %s to change"
msgstr "変更ã™ã‚‹ %s ã‚’é¸æŠž"
-#: contrib/auth/forms.py:30
+#: contrib/admin/views/main.py:758
+msgid "Database error"
+msgstr "データベースエラー"
+
+#: contrib/auth/forms.py:16
+msgid "The two password fields didn't match."
+msgstr "確èªç”¨ãƒ‘スワードãŒä¸€è‡´ã—ã¾ã›ã‚“。"
+
+#: contrib/auth/forms.py:24
+msgid "A user with that username already exists."
+msgstr "åŒã˜ãƒ¦ãƒ¼ã‚¶åãŒæ—¢ã«ç™»éŒ²æ¸ˆã¿ã§ã™ã€‚"
+
+#: contrib/auth/forms.py:52
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in."
@@ -880,83 +1037,117 @@ msgstr ""
"ãŠä½¿ã„ã®ãƒ–ラウザã¯ã‚¯ãƒƒã‚­ãƒ¼ã‚’有効ã«ã—ã¦ã„ãªã„よã†ã§ã™ã€‚ログインã«ã¯ã‚¯ãƒƒã‚­ãƒ¼ãŒ"
"å¿…è¦ã§ã™ã€‚"
-#: contrib/auth/models.py:13 contrib/auth/models.py:26
+#: contrib/auth/forms.py:61
+msgid "This account is inactive."
+msgstr "アカウントãŒç„¡åйã§ã™ã€‚"
+
+#: contrib/auth/forms.py:84
+msgid ""
+"That e-mail address doesn't have an associated user account. Are you sure "
+"you've registered?"
+msgstr "メールアドレスã®ä¸€è‡´ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ã¯ã„ã¾ã›ã‚“。本当ã«ç™»éŒ²ã—ã¾ã—ãŸã‹ï¼Ÿ"
+
+#: contrib/auth/forms.py:116
+msgid "The two 'new password' fields didn't match."
+msgstr "æ–°ã—ã„パスワード(確èªç”¨)ãŒä¸€è‡´ã—ã¾ã›ã‚“。"
+
+#: contrib/auth/forms.py:123
+msgid "Your old password was entered incorrectly. Please enter it again."
+msgstr "å…ƒã®ãƒ‘スワードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚ã‚‚ã†ä¸€åº¦å…¥åŠ›ã—ã¦ãã ã•ã„。"
+
+#: contrib/auth/models.py:38 contrib/auth/models.py:57
msgid "name"
msgstr "åå‰"
-#: contrib/auth/models.py:15
+#: contrib/auth/models.py:40
msgid "codename"
msgstr "コードå"
-#: contrib/auth/models.py:17
-#, fuzzy
+#: contrib/auth/models.py:42
msgid "permission"
msgstr "パーミッション"
-#: contrib/auth/models.py:18 contrib/auth/models.py:27
-#, fuzzy
+#: contrib/auth/models.py:43 contrib/auth/models.py:58
msgid "permissions"
msgstr "パーミッション"
-#: contrib/auth/models.py:29
-#, fuzzy
+#: contrib/auth/models.py:60
msgid "group"
msgstr "グループ"
-#: contrib/auth/models.py:30 contrib/auth/models.py:65
-#, fuzzy
+#: contrib/auth/models.py:61 contrib/auth/models.py:100
msgid "groups"
msgstr "グループ"
-#: contrib/auth/models.py:55
+#: contrib/auth/models.py:90
msgid "username"
msgstr "ユーザå"
-#: contrib/auth/models.py:56
+#: contrib/auth/models.py:90
+msgid ""
+"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
+"digits and underscores)."
+msgstr ""
+"ã“ã®é …ç›®ã¯å¿…é ˆã§ã™ã€‚åŠè§’アルファベットã€åŠè§’æ•°å­—ã€åŠè§’アンダーãƒãƒ¼ã§30文字以"
+"下ã«ã—ã¦ãã ã•ã„。"
+
+#: contrib/auth/models.py:91
msgid "first name"
msgstr "å"
-#: contrib/auth/models.py:57
+#: contrib/auth/models.py:92
msgid "last name"
msgstr "å§“"
-#: contrib/auth/models.py:58
+#: contrib/auth/models.py:93
msgid "e-mail address"
msgstr "メールアドレス"
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "password"
msgstr "パスワード"
-#: contrib/auth/models.py:59
+#: contrib/auth/models.py:94
msgid "Use '[algo]$[salt]$[hexdigest]'"
msgstr "'[アルゴリズム]$[ソルト]$[ダイジェスト(hex)]' å½¢å¼ã‚’使ã£ã¦ä¸‹ã•ã„"
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "staff status"
msgstr "スタッフ権é™"
-#: contrib/auth/models.py:60
+#: contrib/auth/models.py:95
msgid "Designates whether the user can log into this admin site."
msgstr "ユーザãŒç®¡ç†ã‚µã‚¤ãƒˆã«ãƒ­ã‚°ã‚¤ãƒ³å¯èƒ½ã‹ã©ã†ã‹ã‚’示ã—ã¾ã™ã€‚"
-#: contrib/auth/models.py:61
+#: contrib/auth/models.py:96
msgid "active"
msgstr "有効"
-#: contrib/auth/models.py:62
+#: contrib/auth/models.py:96
+msgid ""
+"Designates whether this user can log into the Django admin. Unselect this "
+"instead of deleting accounts."
+msgstr "ユーザãŒç®¡ç†ã‚µã‚¤ãƒˆã«ãƒ­ã‚°ã‚¤ãƒ³å¯èƒ½ã‹ã©ã†ã‹ã‚’示ã—ã¾ã™ã€‚"
+
+#: contrib/auth/models.py:97
msgid "superuser status"
msgstr "スーパーユーザ権é™"
-#: contrib/auth/models.py:63
+#: contrib/auth/models.py:97
+msgid ""
+"Designates that this user has all permissions without explicitly assigning "
+"them."
+msgstr "å…¨ã¦ã®æ¨©é™ã‚’æŒã£ã¦ã„ã‚‹ã¨ã¿ãªã•れã¾ã™ã€‚"
+
+#: contrib/auth/models.py:98
msgid "last login"
msgstr "最終ログイン"
-#: contrib/auth/models.py:64
+#: contrib/auth/models.py:99
msgid "date joined"
msgstr "登録日"
-#: contrib/auth/models.py:66
+#: contrib/auth/models.py:101
msgid ""
"In addition to the permissions manually assigned, this user will also get "
"all permissions granted to each group he/she is in."
@@ -964,42 +1155,42 @@ msgstr ""
"手動ã§ä»˜ä¸Žã—ãŸãƒ‘ーミッションã«åŠ ãˆã€æ‰€å±žã—ã¦ã„るグループã«ä»˜ä¸Žã•れãŸå…¨ã¦ã®"
"パーミッションをç²å¾—ã—ã¾ã™ã€‚"
-#: contrib/auth/models.py:67
-#, fuzzy
+#: contrib/auth/models.py:102
msgid "user permissions"
msgstr "ユーザパーミッション"
-#: contrib/auth/models.py:70
-#, fuzzy
+#: contrib/auth/models.py:105
msgid "user"
msgstr "ユーザ"
-#: contrib/auth/models.py:71
-#, fuzzy
+#: contrib/auth/models.py:106
msgid "users"
msgstr "ユーザ"
-#: contrib/auth/models.py:76
+#: contrib/auth/models.py:111
msgid "Personal info"
msgstr "個人情報"
-#: contrib/auth/models.py:77
+#: contrib/auth/models.py:112
msgid "Permissions"
msgstr "パーミッション"
-#: contrib/auth/models.py:78
+#: contrib/auth/models.py:113
msgid "Important dates"
msgstr "é‡è¦ãªæ—¥ç¨‹"
-#: contrib/auth/models.py:79
+#: contrib/auth/models.py:114
msgid "Groups"
msgstr "グループ"
-#: contrib/auth/models.py:219
-#, fuzzy
+#: contrib/auth/models.py:258
msgid "message"
msgstr "メッセージ"
+#: contrib/auth/views.py:39
+msgid "Logged out"
+msgstr "ログアウト"
+
#: contrib/comments/models.py:67 contrib/comments/models.py:166
msgid "object ID"
msgstr "オブジェクト ID"
@@ -1070,7 +1261,6 @@ msgstr ""
"ãŸã€ã¨è¡¨ç¤ºã•れるよã†ã«ãªã‚Šã¾ã™ã€‚"
#: contrib/comments/models.py:91
-#, fuzzy
msgid "comments"
msgstr "コメント"
@@ -1106,12 +1296,10 @@ msgid "approved by staff"
msgstr "ã‚¹ã‚¿ãƒƒãƒ•ã®æ‰¿èªæ¸ˆã¿"
#: contrib/comments/models.py:176
-#, fuzzy
msgid "free comment"
msgstr "フリーコメント"
#: contrib/comments/models.py:177
-#, fuzzy
msgid "free comments"
msgstr "フリーコメント"
@@ -1124,12 +1312,10 @@ msgid "score date"
msgstr "スコアã•ã‚ŒãŸæ—¥"
#: contrib/comments/models.py:237
-#, fuzzy
msgid "karma score"
msgstr "カルマスコア"
#: contrib/comments/models.py:238
-#, fuzzy
msgid "karma scores"
msgstr "カルマスコア"
@@ -1154,12 +1340,10 @@ msgid "flag date"
msgstr "フラグ日"
#: contrib/comments/models.py:268
-#, fuzzy
msgid "user flag"
msgstr "ユーザフラグ"
#: contrib/comments/models.py:269
-#, fuzzy
msgid "user flags"
msgstr "ユーザフラグ"
@@ -1173,12 +1357,10 @@ msgid "deletion date"
msgstr "削除日"
#: contrib/comments/models.py:280
-#, fuzzy
msgid "moderator deletion"
msgstr "モデレータ削除"
#: contrib/comments/models.py:281
-#, fuzzy
msgid "moderator deletions"
msgstr "モデレータ削除"
@@ -1187,13 +1369,11 @@ msgstr "モデレータ削除"
msgid "Moderator deletion by %r"
msgstr "%r ã«ã‚ˆã‚‹ãƒ¢ãƒ‡ãƒ¬ãƒ¼ã‚¿å‰Šé™¤"
-#: contrib/comments/templates/comments/form.html:6
-#, fuzzy
+#: contrib/comments/templates/comments/form.html:8
msgid "Forgotten your password?"
msgstr "パスワードをãŠå¿˜ã‚Œã§ã™ã‹ï¼Ÿ"
#: contrib/comments/templates/comments/form.html:12
-#, fuzzy
msgid "Ratings"
msgstr "レーティング"
@@ -1211,30 +1391,27 @@ msgstr "オプション"
msgid "Post a photo"
msgstr "写真を登録"
-#: contrib/comments/templates/comments/form.html:27
+#: contrib/comments/templates/comments/form.html:28
#: contrib/comments/templates/comments/freeform.html:5
-#, fuzzy
msgid "Comment:"
msgstr "コメント:"
-#: contrib/comments/templates/comments/form.html:32
-#: contrib/comments/templates/comments/freeform.html:9
-#, fuzzy
+#: contrib/comments/templates/comments/form.html:35
+#: contrib/comments/templates/comments/freeform.html:10
msgid "Preview comment"
msgstr "コメントをプレビュー"
#: contrib/comments/templates/comments/freeform.html:4
-#, fuzzy
msgid "Your name:"
msgstr "ユーザå:"
-#: contrib/comments/views/comments.py:28
+#: contrib/comments/views/comments.py:27
msgid ""
"This rating is required because you've entered at least one other rating."
msgstr ""
"ä»–ã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚’入力ã—ãŸå ´åˆã¯ã€ã“ã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã¯å¿…ãšå…¥åŠ›ã—ã¦ãã ã•ã„。"
-#: contrib/comments/views/comments.py:112
+#: contrib/comments/views/comments.py:111
#, python-format
msgid ""
"This comment was posted by a user who has posted fewer than %(count)s "
@@ -1249,7 +1426,7 @@ msgid_plural ""
msgstr[0] "ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’投稿ã—ãŸãƒ¦ãƒ¼ã‚¶ã®ã‚³ãƒ¡ãƒ³ãƒˆæ•°ã¯ %(count)s 未満ã§ã™ã€‚"
msgstr[1] "ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’投稿ã—ãŸãƒ¦ãƒ¼ã‚¶ã®ã‚³ãƒ¡ãƒ³ãƒˆæ•°ã¯ %(count)s 未満ã§ã™ã€‚"
-#: contrib/comments/views/comments.py:117
+#: contrib/comments/views/comments.py:116
#, python-format
msgid ""
"This comment was posted by a sketchy user:\n"
@@ -1260,22 +1437,22 @@ msgstr ""
"\n"
"%(text)s"
-#: contrib/comments/views/comments.py:189
+#: contrib/comments/views/comments.py:188
#: contrib/comments/views/comments.py:280
msgid "Only POSTs are allowed"
msgstr "POST メソッドã®ã¿æœ‰åйã§ã™ã€‚"
-#: contrib/comments/views/comments.py:193
+#: contrib/comments/views/comments.py:192
#: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted"
msgstr "必須項目ãŒã„ãã¤ã‹å…¥åŠ›ã•れã¦ã„ã¾ã›ã‚“。"
-#: contrib/comments/views/comments.py:197
+#: contrib/comments/views/comments.py:196
#: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)"
msgstr "ã ã‚Œã‹ãŒã‚³ãƒ¡ãƒ³ãƒˆãƒ•ォームを改竄ã—ã¦ã„ã¾ã™ (セキュリティ侵害ã§ã™)"
-#: contrib/comments/views/comments.py:207
+#: contrib/comments/views/comments.py:206
#: contrib/comments/views/comments.py:292
msgid ""
"The comment form had an invalid 'target' parameter -- the object ID was "
@@ -1301,16 +1478,15 @@ msgstr "コメント ID ãŒä¸æ­£ã§ã™"
msgid "No voting for yourself"
msgstr "自分ã«ã¯æŠ•票ã§ãã¾ã›ã‚“。"
-#: contrib/contenttypes/models.py:25
-#, fuzzy
+#: contrib/contenttypes/models.py:20
msgid "python model class name"
msgstr "Python モデルクラスå"
-#: contrib/contenttypes/models.py:28
+#: contrib/contenttypes/models.py:23
msgid "content type"
msgstr "コンテンツタイプ"
-#: contrib/contenttypes/models.py:29
+#: contrib/contenttypes/models.py:24
msgid "content types"
msgstr "コンテンツタイプ"
@@ -1338,11 +1514,11 @@ msgstr "テンプレートå"
#: contrib/flatpages/models.py:13
msgid ""
-"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
-"use 'flatpages/default'."
+"Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
+"will use 'flatpages/default.html'."
msgstr ""
-"例: 'flatpages/contact_page'. 指定ã—ãªã‘れã°ã€ãƒ‡ãƒ•ォルト設定ã®'flatpages/"
-"default' を使ã„ã¾ã™ã€‚"
+"例: 'flatpages/contact_page.html'. 指定ã—ãªã‘れã°ã€ãƒ‡ãƒ•ォルト設定"
+"ã®'flatpages/default.html' を使ã„ã¾ã™ã€‚"
#: contrib/flatpages/models.py:14
msgid "registration required"
@@ -1380,31 +1556,31 @@ msgid ""
"'http://'."
msgstr "上記ã®ã‚ˆã†ãªçµ¶å¯¾ãƒ‘スã‹ã€ 'http://' ã§å§‹ã¾ã‚‹å®Œå…¨ãª URL ã«ã—ã¾ã™ã€‚"
-#: contrib/redirects/models.py:12
+#: contrib/redirects/models.py:13
msgid "redirect"
msgstr "リダイレクト"
-#: contrib/redirects/models.py:13
+#: contrib/redirects/models.py:14
msgid "redirects"
msgstr "リダイレクト"
-#: contrib/sessions/models.py:35
+#: contrib/sessions/models.py:51
msgid "session key"
msgstr "セッションキー"
-#: contrib/sessions/models.py:36
+#: contrib/sessions/models.py:52
msgid "session data"
msgstr "セッションデータ"
-#: contrib/sessions/models.py:37
+#: contrib/sessions/models.py:53
msgid "expire date"
msgstr "有効期é™"
-#: contrib/sessions/models.py:41
+#: contrib/sessions/models.py:57
msgid "session"
msgstr "セッション"
-#: contrib/sessions/models.py:42
+#: contrib/sessions/models.py:58
msgid "sessions"
msgstr "セッション"
@@ -1424,74 +1600,92 @@ msgstr "サイト"
msgid "sites"
msgstr "サイト"
-#: core/validators.py:60
+#: core/validators.py:63
msgid "This value must contain only letters, numbers and underscores."
msgstr "åŠè§’ã®è‹±æ•°å­—ãŠã‚ˆã³ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ä»¥å¤–ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。"
-#: core/validators.py:64
-#, fuzzy
+#: core/validators.py:67
msgid ""
"This value must contain only letters, numbers, underscores, dashes or "
"slashes."
-msgstr "åŠè§’ã®è‹±æ•°å­—ã€ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ã€ãƒ€ãƒƒã‚·ãƒ¥ã€ãƒ©ãƒƒã‚·ãƒ¥ä»¥å¤–ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。"
+msgstr ""
+"åŠè§’ã®è‹±æ•°å­—ã€ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ã€ãƒ€ãƒƒã‚·ãƒ¥ã€ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ä»¥å¤–ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。"
+
+#: core/validators.py:71
+msgid "This value must contain only letters, numbers, underscores or hyphens."
+msgstr "åŠè§’ã®è‹±æ•°å­—ã€ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ã€ãƒã‚¤ãƒ•ン以外ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。"
-#: core/validators.py:72
+#: core/validators.py:75
msgid "Uppercase letters are not allowed here."
msgstr "大文字ã¯ã“ã“ã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。"
-#: core/validators.py:76
+#: core/validators.py:79
msgid "Lowercase letters are not allowed here."
msgstr "å°æ–‡å­—ã¯ã“ã“ã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。"
-#: core/validators.py:83
+#: core/validators.py:86
msgid "Enter only digits separated by commas."
msgstr "ã‚«ãƒ³ãƒžåŒºåˆ‡ã‚Šã®æ•°å­—ã ã‘を入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:95
+#: core/validators.py:98
msgid "Enter valid e-mail addresses separated by commas."
msgstr "ã‚«ãƒ³ãƒžåŒºåˆ‡ã‚Šã®æœ‰åйãªãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:99
+#: core/validators.py:102
msgid "Please enter a valid IP address."
msgstr "有効㪠IP アドレスを入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:103
+#: core/validators.py:106
msgid "Empty values are not allowed here."
msgstr "入力ã¯å¿…é ˆã§ã™ã€‚"
-#: core/validators.py:107
+#: core/validators.py:110
msgid "Non-numeric characters aren't allowed here."
msgstr "数値以外ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。"
-#: core/validators.py:111
+#: core/validators.py:114
msgid "This value can't be comprised solely of digits."
msgstr "数値ã ã‘ã®å€¤ã«ã¯ã§ãã¾ã›ã‚“。"
-#: core/validators.py:116
+#: core/validators.py:119
msgid "Enter a whole number."
msgstr "整数を入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:120
+#: core/validators.py:123
msgid "Only alphabetical characters are allowed here."
msgstr "åŠè§’アルファベット以外使用ã§ãã¾ã›ã‚“。"
-#: core/validators.py:124
+#: core/validators.py:138
+msgid "Year must be 1900 or later."
+msgstr "1900年以é™ã‚’指定ã—ã¦ãã ã•ã„。"
+
+#: core/validators.py:142
+#, python-format
+msgid "Invalid date: %s."
+msgstr "ç„¡åŠ¹ãªæ—¥ä»˜: %s"
+
+#: core/validators.py:146 db/models/fields/__init__.py:424
msgid "Enter a valid date in YYYY-MM-DD format."
msgstr "YYYY-MM-DDå½¢å¼ã§æ—¥ä»˜ã‚’入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:128
+#: core/validators.py:151
msgid "Enter a valid time in HH:MM format."
msgstr "HH:MMå½¢å¼ã§æ™‚刻を入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:132 db/models/fields/__init__.py:468
+#: core/validators.py:155 db/models/fields/__init__.py:486
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr "YYYY-MM-DD HH:MMå½¢å¼ã§æ—¥æ™‚を入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:136
+#: core/validators.py:160
msgid "Enter a valid e-mail address."
msgstr "有効ãªãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:148
+#: core/validators.py:172 core/validators.py:401 forms/__init__.py:662
+msgid "No file was submitted. Check the encoding type on the form."
+msgstr ""
+"ファイルãŒå–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚formã®encoding typeを確èªã—ã¦ãã ã•ã„。"
+
+#: core/validators.py:176
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
@@ -1499,26 +1693,26 @@ msgstr ""
"ç”»åƒã‚’アップロードã—ã¦ãã ã•ã„。アップロードã—ãŸç”»åƒã¯ç”»åƒã§ãªã„ã‹ã€ã¾ãŸã¯å£Š"
"れã¦ã„ã¾ã™ã€‚"
-#: core/validators.py:155
+#: core/validators.py:183
#, python-format
msgid "The URL %s does not point to a valid image."
msgstr "URL ( %s ) ã¯ç”»åƒã§ã¯ã‚りã¾ã›ã‚“。"
-#: core/validators.py:159
+#: core/validators.py:187
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr "電話番å·ã¯ XXX-XXX-XXXX å½¢å¼ã§å…¥åŠ›ã—ã¦ãã ã•ã„。\"%s\" ã¯ç„¡åйã§ã™ã€‚"
-#: core/validators.py:167
+#: core/validators.py:195
#, python-format
msgid "The URL %s does not point to a valid QuickTime video."
msgstr "URL ( %s ) 㯠QuickTime ビデオã§ã¯ã‚りã¾ã›ã‚“。"
-#: core/validators.py:171
+#: core/validators.py:199
msgid "A valid URL is required."
msgstr "æ­£ã—ã„ URL を入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:185
+#: core/validators.py:213
#, python-format
msgid ""
"Valid HTML is required. Specific errors are:\n"
@@ -1527,117 +1721,126 @@ msgstr ""
"有効㪠HTML を入力ã—ã¦ãã ã•ã„。エラー:\n"
"%s"
-#: core/validators.py:192
+#: core/validators.py:220
#, python-format
msgid "Badly formed XML: %s"
msgstr "䏿­£ãª XML ã§ã™: %s"
-#: core/validators.py:202
+#: core/validators.py:230
#, python-format
msgid "Invalid URL: %s"
msgstr "無効ãªURL: %s"
-#: core/validators.py:206 core/validators.py:208
+#: core/validators.py:234 core/validators.py:236
#, python-format
msgid "The URL %s is a broken link."
msgstr "URL ( %s ) ã¯ãƒªãƒ³ã‚¯ãŒå£Šã‚Œã¦ã„ã¾ã™ã€‚"
-#: core/validators.py:214
+#: core/validators.py:242
msgid "Enter a valid U.S. state abbreviation."
msgstr "æ­£ã—ã„米州略称を入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:229
+#: core/validators.py:256
#, python-format
msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "言葉使ã„ã«æ°—を付ã‘ã¦ï¼ %s ã¨ã„ã†è¨€è‘‰ã¯ä½¿ãˆã¾ã›ã‚“。"
msgstr[1] "言葉使ã„ã«æ°—を付ã‘ã¦ï¼ %s ã¨ã„ã†è¨€è‘‰ã¯ä½¿ãˆã¾ã›ã‚“。"
-#: core/validators.py:236
+#: core/validators.py:263
#, python-format
msgid "This field must match the '%s' field."
msgstr "ã“ã®ãƒ•ィールド㯠'%s' フィールドã¨ä¸€è‡´ã›ã­ã°ãªã‚Šã¾ã›ã‚“。"
-#: core/validators.py:255
+#: core/validators.py:282
msgid "Please enter something for at least one field."
msgstr "å°‘ãªãã¨ã‚‚一ã¤ã®ãƒ•ィールドã«ä½•ã‹å…¥åŠ›ã—ã¦ãã ã•ã„。"
-#: core/validators.py:264 core/validators.py:275
+#: core/validators.py:291 core/validators.py:302
msgid "Please enter both fields or leave them both empty."
msgstr "両方ã®ãƒ•ィールドã«å…¥åŠ›ã™ã‚‹ã‹ã€ä¸¡æ–¹ã¨ã‚‚未入力ã«ã—ã¦ãã ã•ã„。"
-#: core/validators.py:282
+#: core/validators.py:309
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
msgstr ""
"%(field)s ã‚’ %(value)s ã«ã™ã‚‹ã®ãªã‚‰ã€ã“ã®ãƒ•ィールドã«å¿…ãšå…¥åŠ›ã—ã¦ãã ã•ã„。"
-#: core/validators.py:294
+#: core/validators.py:321
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
msgstr ""
"%(field)s ã‚’ %(value)s ã«ã—ãªã„ã®ãªã‚‰ã€ã“ã®ãƒ•ィールドã«å¿…ãšå…¥åŠ›ã—ã¦ãã ã•ã„。"
-#: core/validators.py:313
+#: core/validators.py:340
msgid "Duplicate values are not allowed."
msgstr "é‡è¤‡ã™ã‚‹å€¤ã¯èªã‚られã¾ã›ã‚“。"
-#: core/validators.py:336
+#: core/validators.py:363
#, python-format
msgid "This value must be a power of %s."
msgstr "ã“ã®å€¤ã¯ %s ã®ç´¯ä¹—ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。"
-#: core/validators.py:347
+#: core/validators.py:374
msgid "Please enter a valid decimal number."
msgstr "有効㪠10 進数を入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:349
+#: core/validators.py:378
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
"Please enter a valid decimal number with at most %s total digits."
-msgstr[0] "æœ€å¤§æ¡æ•° %s æ¡ä»¥ä¸‹ã®æœ‰åŠ¹ãª 10 進数を入力ã—ã¦ãã ã•ã„。"
-msgstr[1] "æœ€å¤§æ¡æ•° %s æ¡ä»¥ä¸‹ã®æœ‰åŠ¹ãª 10 進数を入力ã—ã¦ãã ã•ã„。"
+msgstr[0] "全体㧠%s æ–‡å­—ä»¥ä¸‹ã®æ•°å­—を入力ã—ã¦ãã ã•ã„。"
+msgstr[1] "全体㧠%s æ–‡å­—ä»¥ä¸‹ã®æ•°å­—を入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:352
+#: core/validators.py:381
+#, python-format
+msgid ""
+"Please enter a valid decimal number with a whole part of at most %s digit."
+msgid_plural ""
+"Please enter a valid decimal number with a whole part of at most %s digits."
+msgstr[0] "整数部㯠%s æ–‡å­—ä»¥ä¸‹ã®æ•°å­—を入力ã—ã¦ãã ã•ã„。"
+msgstr[1] "整数部㯠%s æ–‡å­—ä»¥ä¸‹ã®æ•°å­—を入力ã—ã¦ãã ã•ã„。"
+
+#: core/validators.py:384
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
"Please enter a valid decimal number with at most %s decimal places."
-msgstr[0] "å°æ•°ç‚¹ä»¥ä¸‹ãŒ %s æ¡ã¾ã§ã®æœ‰åŠ¹ãª 10 進数を入力ã—ã¦ãã ã•ã„。"
-msgstr[1] "å°æ•°ç‚¹ä»¥ä¸‹ãŒ %s æ¡ã¾ã§ã®æœ‰åŠ¹ãª 10 進数を入力ã—ã¦ãã ã•ã„。"
+msgstr[0] "å°æ•°éƒ¨ã¯ %s æ–‡å­—ä»¥ä¸‹ã®æ•°å­—を入力ã—ã¦ãã ã•ã„。"
+msgstr[1] "å°æ•°éƒ¨ã¯ %s æ–‡å­—ä»¥ä¸‹ã®æ•°å­—を入力ã—ã¦ãã ã•ã„。"
-#: core/validators.py:362
+#: core/validators.py:394
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr "アップロードã™ã‚‹ãƒ•ァイルã®å¤§ãã•㯠%s ãƒã‚¤ãƒˆä»¥ä¸Šã«ã—ã¦ãã ã•ã„。"
-#: core/validators.py:363
+#: core/validators.py:395
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr "アップロードã™ã‚‹ãƒ•ァイルã®å¤§ãã•㯠%s 最大ãƒã‚¤ãƒˆã¾ã§ã§ã™ã€‚"
-#: core/validators.py:376
+#: core/validators.py:412
msgid "The format for this field is wrong."
msgstr "フィールドã®å½¢å¼ãŒæ­£ã—ãã‚りã¾ã›ã‚“。"
-#: core/validators.py:391
+#: core/validators.py:427
msgid "This field is invalid."
msgstr "ã“ã®ãƒ•ィールドã¯ç„¡åйã§ã™ã€‚"
-#: core/validators.py:426
+#: core/validators.py:463
#, python-format
msgid "Could not retrieve anything from %s."
msgstr "%s ã‹ã‚‰ä½•も検索ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
-#: core/validators.py:429
+#: core/validators.py:466
#, python-format
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr ""
"URL %(url)s ã¯ç„¡åйãªã‚³ãƒ³ãƒ†ãƒ³ãƒ„タイプヘッダ '%(contenttype)s' ã‚’è¿”ã—ã¾ã—ãŸã€‚"
-#: core/validators.py:462
+#: core/validators.py:499
#, python-format
msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
@@ -1646,7 +1849,7 @@ msgstr ""
"%(line)s 行目ã‹ã‚‰å§‹ã¾ã‚‹ %(tag)s ã‚¿ã‚°ã‚’é–‰ã˜ã¦ãã ã•ã„ (\"%(start)s\" ã§å§‹ã¾ã‚‹"
"行ã§ã™)。"
-#: core/validators.py:466
+#: core/validators.py:503
#, python-format
msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line "
@@ -1655,7 +1858,7 @@ msgstr ""
"%(line)s 行目ã‹ã‚‰å§‹ã¾ã‚‹ãƒ†ã‚­ã‚¹ãƒˆã¯ã“ã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã§ã¯ä½¿ãˆã¾ã›ã‚“。 (\"%(start)"
"s\" ã§å§‹ã¾ã‚‹è¡Œã§ã™)。"
-#: core/validators.py:471
+#: core/validators.py:508
#, python-format
msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
@@ -1664,7 +1867,7 @@ msgstr ""
"%(line)s 行目㮠\"%(attr)s\" ã¯ç„¡åйãªã‚¢ãƒˆãƒªãƒ“ュートã§ã™ (\"%(start)s\" ã§å§‹ã¾"
"る行ã§ã™)。"
-#: core/validators.py:476
+#: core/validators.py:513
#, python-format
msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
@@ -1673,7 +1876,7 @@ msgstr ""
"%(line)s 行目㮠\"<%(tag)s>\" ã¯ç„¡åйãªã‚¿ã‚°ã§ã™( \"%(start)s\" ã§å§‹ã¾ã‚‹è¡Œã§"
"ã™)。"
-#: core/validators.py:480
+#: core/validators.py:517
#, python-format
msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line "
@@ -1682,7 +1885,7 @@ msgstr ""
"%(line)s 行目ã®ã‚¿ã‚°ã¯å¿…é ˆã‚¢ãƒˆãƒªãƒ“ãƒ¥ãƒ¼ãƒˆãŒæœªå…¥åŠ›ã§ã™( \"%(start)s\" ã§å§‹ã¾ã‚‹è¡Œ"
"ã§ã™)。"
-#: core/validators.py:485
+#: core/validators.py:522
#, python-format
msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
@@ -1691,61 +1894,56 @@ msgstr ""
"%(line)s 行目㮠\"%(attr)s\" アトリビュートã®å€¤ãŒæ­£ã—ãã‚りã¾ã›ã‚“ (\"%(start)"
"s\" ã§å§‹ã¾ã‚‹è¡Œã§ã™) 。"
-#: db/models/manipulators.py:302
+#: db/models/manipulators.py:305
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
msgstr ""
"%(field)s ã«å…¥åŠ›ã•れãŸã‚‚ã®ã¯ã€ã“ã® %(type)s ã® %(object)s ã«æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚"
-#: db/models/fields/__init__.py:40
+#: db/models/fields/__init__.py:41
#, python-format
msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "%(fieldname)s ã« %(optname)s ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚"
-#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
-#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
-#: forms/__init__.py:346
+#: db/models/fields/__init__.py:115 db/models/fields/__init__.py:266
+#: db/models/fields/__init__.py:560 db/models/fields/__init__.py:571
+#: forms/__init__.py:347
msgid "This field is required."
msgstr "ã“ã®ãƒ•ィールドã¯å¿…é ˆã§ã™ã€‚"
-#: db/models/fields/__init__.py:337
-#, fuzzy
+#: db/models/fields/__init__.py:349
msgid "This value must be an integer."
msgstr "å€¤ã¯æ•´æ•°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。"
-#: db/models/fields/__init__.py:369
-#, fuzzy
+#: db/models/fields/__init__.py:381
msgid "This value must be either True or False."
msgstr "値ã¯çœŸ: True ã¾ãŸã¯å½: False ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。"
-#: db/models/fields/__init__.py:385
-#, fuzzy
+#: db/models/fields/__init__.py:397
msgid "This field cannot be null."
msgstr "ã“ã®ãƒ•ィールドã«ã¯ NULL を指定ã§ãã¾ã›ã‚“。"
-#: db/models/fields/__init__.py:562
+#: db/models/fields/__init__.py:580
msgid "Enter a valid filename."
msgstr "æ­£ã—ã„ファイルåを入力ã—ã¦ãã ã•ã„。"
-#: db/models/fields/related.py:43
+#: db/models/fields/related.py:51
#, python-format
msgid "Please enter a valid %s."
msgstr "æ­£ã—ã„ %s を入力ã—ã¦ãã ã•ã„。"
-#: db/models/fields/related.py:579
-#, fuzzy
+#: db/models/fields/related.py:618
msgid "Separate multiple IDs with commas."
msgstr "複数㮠ID ã¯ã‚«ãƒ³ãƒžã§åŒºåˆ‡ã£ã¦ãã ã•ã„。"
-#: db/models/fields/related.py:581
-#, fuzzy
+#: db/models/fields/related.py:620
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
-"è¤‡æ•°é¸æŠžã™ã‚‹ã¨ãã«ã¯ \"Control\"キーを押ã—ãŸã¾ã¾é¸æŠžã—ã¦ãã ã•ã„。Mac ã§ã¯ "
-"\"Command\" キーを使ã£ã¦ãã ã•ã„。"
+"è¤‡æ•°é¸æŠžã™ã‚‹ã¨ãã«ã¯ Control キーを押ã—ãŸã¾ã¾é¸æŠžã—ã¦ãã ã•ã„。Mac 㯠"
+"Command キーを使ã£ã¦ãã ã•ã„"
-#: db/models/fields/related.py:625
+#: db/models/fields/related.py:664
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
msgid_plural ""
@@ -1753,39 +1951,39 @@ msgid_plural ""
msgstr[0] "æ­£ã—ã„ %(self)s IDを入力ã—ã¦ãã ã•ã„。 %(value)r ã¯ç„¡åйã§ã™ã€‚"
msgstr[1] "æ­£ã—ã„ %(self)s IDを入力ã—ã¦ãã ã•ã„。 %(value)r ã¯ç„¡åйã§ã™ã€‚"
-#: forms/__init__.py:380
+#: forms/__init__.py:382
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "%s 字以下ã§å…¥åŠ›ã—ã¦ãã ã•ã„。"
msgstr[1] "%s 字以下ã§å…¥åŠ›ã—ã¦ãã ã•ã„。"
-#: forms/__init__.py:385
+#: forms/__init__.py:387
msgid "Line breaks are not allowed here."
msgstr "改行ã¯ã§ãã¾ã›ã‚“。"
-#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
+#: forms/__init__.py:488 forms/__init__.py:561 forms/__init__.py:600
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "æ­£ã—ãé¸æŠžã—ã¦ãã ã•ã„。; '%(data)s' 㯠%(choices)s ã«ã‚りã¾ã›ã‚“。"
-#: forms/__init__.py:645
+#: forms/__init__.py:664
msgid "The submitted file is empty."
msgstr "入力ã•れãŸãƒ•ァイルã¯ç©ºã§ã™ã€‚"
-#: forms/__init__.py:699
+#: forms/__init__.py:720
msgid "Enter a whole number between -32,768 and 32,767."
msgstr "-32,768 ã‹ã‚‰ 32,767 ã¾ã§ã®æ•´æ•°ã‚’入力ã—ã¦ãã ã•ã„。"
-#: forms/__init__.py:708
+#: forms/__init__.py:730
msgid "Enter a positive number."
msgstr "æ­£ã®æ•°ã‚’入力ã—ã¦ãã ã•ã„。"
-#: forms/__init__.py:717
+#: forms/__init__.py:740
msgid "Enter a whole number between 0 and 32,767."
msgstr "0 ã‹ã‚‰ 32,767 ã¾ã§ã®æ•´æ•°ã‚’入力ã—ã¦ãã ã•ã„。"
-#: template/defaultfilters.py:383
+#: template/defaultfilters.py:401
msgid "yes,no,maybe"
msgstr "ã¯ã„,ã„ã„ãˆ,ãŸã¶ã‚“"
@@ -1866,7 +2064,6 @@ msgid "December"
msgstr "12月"
#: utils/dates.py:19
-#, fuzzy
msgid "jan"
msgstr "1月"
@@ -1883,7 +2080,6 @@ msgid "apr"
msgstr "4月"
#: utils/dates.py:19
-#, fuzzy
msgid "may"
msgstr "5月"
@@ -1979,18 +2175,41 @@ msgid_plural "minutes"
msgstr[0] "分"
msgstr[1] "分"
-#: utils/translation.py:363
+#: utils/translation/trans_real.py:362
msgid "DATE_FORMAT"
msgstr "Y/m/d"
-#: utils/translation.py:364
+#: utils/translation/trans_real.py:363
msgid "DATETIME_FORMAT"
msgstr "Y/m/d H:i"
-#: utils/translation.py:365
+#: utils/translation/trans_real.py:364
msgid "TIME_FORMAT"
msgstr "H:i"
+#: utils/translation/trans_real.py:380
+msgid "YEAR_MONTH_FORMAT"
+msgstr "Y/m/d"
+
+#: utils/translation/trans_real.py:381
+msgid "MONTH_DAY_FORMAT"
+msgstr "m/d"
+
+#: views/generic/create_update.py:43
+#, python-format
+msgid "The %(verbose_name)s was created successfully."
+msgstr "%(verbose_name)s を作æˆã—ã¾ã—ãŸã€‚"
+
+#: views/generic/create_update.py:117
+#, python-format
+msgid "The %(verbose_name)s was updated successfully."
+msgstr "%(verbose_name)s ã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚"
+
+#: views/generic/create_update.py:184
+#, python-format
+msgid "The %(verbose_name)s was deleted."
+msgstr " %(verbose_name)s を削除ã—ã¾ã—ãŸã€‚"
+
#~ msgid "String (up to 50)"
#~ msgstr "文字列 (50 å­—ã¾ã§)"
diff --git a/django/conf/locale/ja/LC_MESSAGES/djangojs.mo b/django/conf/locale/ja/LC_MESSAGES/djangojs.mo
index dee3150d1e..bddecacb10 100644
--- a/django/conf/locale/ja/LC_MESSAGES/djangojs.mo
+++ b/django/conf/locale/ja/LC_MESSAGES/djangojs.mo
Binary files differ
diff --git a/django/conf/locale/ja/LC_MESSAGES/djangojs.po b/django/conf/locale/ja/LC_MESSAGES/djangojs.po
index 3d91a17f7d..0ec1cadcf5 100644
--- a/django/conf/locale/ja/LC_MESSAGES/djangojs.po
+++ b/django/conf/locale/ja/LC_MESSAGES/djangojs.po
@@ -2,13 +2,13 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
+#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Django 1.0\n"
-"Report-Msgid-Bugs-To: Django-users Japan <django-ja@googlegroups.com>\n"
-"POT-Creation-Date: 2006-05-02 23:06+0900\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-10-06 00:30+0900\n"
"PO-Revision-Date: 2006-05-08 13:39+0900\n"
"Last-Translator: makoto tsuyuki <mtsuyuki@gmail.com>\n"
"Language-Team: Japanese <django-ja@googlegroups.com>\n"
@@ -61,50 +61,58 @@ msgstr "é¸æŠžã—ã¦ã‚¯ãƒªãƒƒã‚¯"
msgid "Clear all"
msgstr "å…¨ã¦ã‚¯ãƒªã‚¢"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
+#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
+#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
+msgid "Show"
+msgstr "表示"
+
+#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
+msgid "Hide"
+msgstr "éžè¡¨ç¤º"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr "ç¾åœ¨"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "時計"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "æ™‚é–“ã‚’é¸æŠž"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "夜中"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "åˆå‰ 6 時"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "æ­£åˆ"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr "キャンセル"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "今日"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "カレンダー"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "昨日"
-#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "明日"
-
diff --git a/django/conf/locale/no/LC_MESSAGES/django.mo b/django/conf/locale/no/LC_MESSAGES/django.mo
index 4f55637235..ee2152b5e1 100644
--- a/django/conf/locale/no/LC_MESSAGES/django.mo
+++ b/django/conf/locale/no/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/no/LC_MESSAGES/django.po b/django/conf/locale/no/LC_MESSAGES/django.po
index 9b3099046d..427879a8f3 100644
--- a/django/conf/locale/no/LC_MESSAGES/django.po
+++ b/django/conf/locale/no/LC_MESSAGES/django.po
@@ -264,7 +264,7 @@ msgstr "Bare POST er tillatt"
#: contrib/comments/views/comments.py:193
#: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted"
-msgstr "En eller flere av feltene som er krevd ble ikke sendt."
+msgstr "En eller flere av feltene som er påkrevd ble ikke sendt."
#: contrib/comments/views/comments.py:197
#: contrib/comments/views/comments.py:286
@@ -371,35 +371,32 @@ msgid "All"
msgstr "Alle"
#: contrib/admin/filterspecs.py:109
-#, fuzzy
msgid "Any date"
-msgstr "Alle datoer"
+msgstr "NÃ¥r som helst"
#: contrib/admin/filterspecs.py:110
-#, fuzzy
msgid "Today"
-msgstr "Mondag"
+msgstr "I dag"
#: contrib/admin/filterspecs.py:113
msgid "Past 7 days"
-msgstr ""
+msgstr "Siste 7 dager"
#: contrib/admin/filterspecs.py:115
msgid "This month"
-msgstr ""
+msgstr "Denne måneden"
#: contrib/admin/filterspecs.py:117
msgid "This year"
-msgstr ""
+msgstr "I år"
#: contrib/admin/filterspecs.py:143
msgid "Yes"
-msgstr ""
+msgstr "Ja"
#: contrib/admin/filterspecs.py:143
-#, fuzzy
msgid "No"
-msgstr "Nov."
+msgstr "Nei"
#: contrib/admin/filterspecs.py:150
msgid "Unknown"
@@ -443,11 +440,13 @@ msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
msgstr ""
+"Vær snill å angi korrekt brukernavn og passord. La merke til at små og "
+"store bokstaver er betraktet ulik."
#: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25
msgid "Log in"
-msgstr "Log inn"
+msgstr "Logg inn"
#: contrib/admin/views/decorators.py:61
msgid ""
@@ -473,12 +472,11 @@ msgstr "Brukernavnet kan ikke inneholde '@'"
#: contrib/admin/views/decorators.py:84
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
-msgstr "Epost adressen din er ikke brukernavnet ditt, prøv '%s' i stede."
+msgstr "E-post adressen din er ikke brukernavnet ditt, prøv '%s' i stede."
#: contrib/admin/views/main.py:226
-#, fuzzy
msgid "Site administration"
-msgstr "Django administrasjon"
+msgstr "Nettsted administrasjon"
#: contrib/admin/views/main.py:260
#, python-format
@@ -502,7 +500,7 @@ msgstr "Ny %s"
#: contrib/admin/views/main.py:336
#, python-format
msgid "Added %s."
-msgstr "La til %s"
+msgstr "Lagt til %s"
#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
#: contrib/admin/views/main.py:340
@@ -559,7 +557,7 @@ msgid "Are you sure?"
msgstr "Er du sikker?"
#: contrib/admin/views/main.py:533
-#, fuzzy, python-format
+#, python-format
msgid "Change history: %s"
msgstr "Endre historien: %s"
@@ -580,7 +578,6 @@ msgid "Integer"
msgstr "Heltall"
#: contrib/admin/views/doc.py:278
-#, fuzzy
msgid "Boolean (Either True or False)"
msgstr "Boolean (Enten \"True\" eller \"False\")"
@@ -603,7 +600,7 @@ msgstr "Dato/tid"
#: contrib/admin/views/doc.py:283
msgid "E-mail address"
-msgstr "Epost adresse"
+msgstr "E-post adresse"
#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
msgid "File path"
@@ -614,13 +611,12 @@ msgid "Decimal number"
msgstr "Desimal tall"
#: contrib/admin/views/doc.py:291
-#, fuzzy
msgid "Boolean (Either True, False or None)"
msgstr "Boolean (enten \"True\", \"False\" eller \"None\")"
#: contrib/admin/views/doc.py:292
msgid "Relation to parent model"
-msgstr ""
+msgstr "Relasjon til forelder modell"
#: contrib/admin/views/doc.py:293
msgid "Phone number"
@@ -636,7 +632,7 @@ msgstr "Tid"
#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
msgid "URL"
-msgstr "Internettadresse"
+msgstr "URL"
#: contrib/admin/views/doc.py:301
msgid "U.S. state (two uppercase letters)"
@@ -756,12 +752,12 @@ msgstr "Fant ikke siden"
#: contrib/admin/templates/admin/404.html:10
msgid "We're sorry, but the requested page could not be found."
-msgstr "Beklager, men siden du spør etter finnest ikke."
+msgstr "Beklager, men siden du spør etter finnes ikke."
#: contrib/admin/templates/admin/index.html:17
#, python-format
msgid "Models available in the %(name)s application."
-msgstr ""
+msgstr "Modeller fra applikasjonen %(name)s."
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
@@ -813,7 +809,7 @@ msgid ""
"objects, but your account doesn't have permission to delete the following "
"types of objects:"
msgstr ""
-"Vist du sletter %(object_name)s '%(object)s' vill du også slette relaterte "
+"Hivs du sletter %(object_name)s '%(object)s' vil du også slette relaterte "
"objekter, men du har ikke tillatelse til å slette de følgende objektene:"
#: contrib/admin/templates/admin/delete_confirmation.html:21
@@ -836,11 +832,11 @@ msgstr "Av %(title)s "
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
-msgstr ""
+msgstr "GÃ¥"
#: contrib/admin/templates/admin/change_form.html:21
msgid "View on site"
-msgstr "Vis på siden"
+msgstr "Vis på nettsted"
#: contrib/admin/templates/admin/change_form.html:30
msgid "Please correct the error below."
@@ -900,12 +896,12 @@ msgid ""
"Forgotten your password? Enter your e-mail address below, and we'll reset "
"your password and e-mail the new one to you."
msgstr ""
-"Har du glemt passordet ditt? Skriv inn epost adressen din under, så sender "
-"vi deg et nytt passord via epost."
+"Har du glemt passordet ditt? Skriv inn e-post adressen din under, så sender "
+"vi deg et nytt passord via e-post."
#: contrib/admin/templates/registration/password_reset_form.html:16
msgid "E-mail address:"
-msgstr "Epost adresse:"
+msgstr "E-post adresse:"
#: contrib/admin/templates/registration/password_reset_form.html:16
msgid "Reset my password"
@@ -917,7 +913,7 @@ msgstr "Takk for å bruke tid på internett siden i dag."
#: contrib/admin/templates/registration/logged_out.html:10
msgid "Log in again"
-msgstr "Log inn igjen"
+msgstr "Logg inn igjen"
#: contrib/admin/templates/registration/password_reset_done.html:6
#: contrib/admin/templates/registration/password_reset_done.html:10
@@ -929,7 +925,7 @@ msgid ""
"We've e-mailed a new password to the e-mail address you submitted. You "
"should be receiving it shortly."
msgstr ""
-"Vi sender deg et nytt passord til epost adressen du oppgav. Du villmotta det "
+"Vi sender deg et nytt passord til e-post adressen du oppgav. Du villmotta det "
"snart."
#: contrib/admin/templates/registration/password_change_form.html:12
@@ -959,7 +955,7 @@ msgstr "Endre passord"
#: contrib/admin/templates/registration/password_reset_email.html:2
msgid "You're receiving this e-mail because you requested a password reset"
msgstr ""
-"Du har mottatt denne epost-en fordi du ba om å tilbakestille passordet ditt"
+"Du har mottatt denne e-posten fordi du ba om å tilbakestille passordet ditt"
#: contrib/admin/templates/registration/password_reset_email.html:3
#, python-format
@@ -1036,10 +1032,9 @@ msgid "Edit this object (current window)"
msgstr "Endre dette objektet (Ã¥pnes i dette vinduet)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
-#, fuzzy
msgid "Jumps to the admin page for pages that represent a single object."
msgstr ""
-"Hopp til administrasjonsiden for siden som representerer et enkelt objekt."
+"Hopp til administrasjonsiden for sidene som representerer et enkelt objekt."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)"
@@ -1051,21 +1046,19 @@ msgstr "Samme som over, men åpner administrasjonsiden i et nytt vindu."
#: contrib/admin/templates/widget/date_time.html:3
msgid "Date:"
-msgstr ""
+msgstr "Dato:"
#: contrib/admin/templates/widget/date_time.html:4
-#, fuzzy
msgid "Time:"
-msgstr "Tid"
+msgstr "Tid:"
#: contrib/admin/templates/widget/file.html:2
msgid "Currently:"
-msgstr ""
+msgstr "NÃ¥:"
#: contrib/admin/templates/widget/file.html:3
-#, fuzzy
msgid "Change:"
-msgstr "Endre"
+msgstr "Endre:"
#: contrib/redirects/models.py:7
msgid "redirect from"
@@ -1126,7 +1119,7 @@ msgid ""
"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
"use 'flatpages/default'."
msgstr ""
-"Eksempel: 'flatfiler/kontakt_side'. Vist denne ikke denne er gitt, vill "
+"Eksempel: 'flatfiler/kontakt_side'. Hvis denne ikke denne er gitt, vill "
"'flatfiles/default' bli brukt."
#: contrib/flatpages/models.py:14
@@ -1136,7 +1129,7 @@ msgstr "registrering kreves"
#: contrib/flatpages/models.py:14
msgid "If this is checked, only logged-in users will be able to view the page."
msgstr ""
-"Vist denne er krysset av er det bare brukere som er logget inn som kan se "
+"Hvis denne er krysset av er det bare brukere som er logget inn som kan se "
"siden."
#: contrib/flatpages/models.py:18
@@ -1156,24 +1149,20 @@ msgid "codename"
msgstr "kodenavn"
#: contrib/auth/models.py:17
-#, fuzzy
msgid "permission"
-msgstr "Rettighet"
+msgstr "rettighet"
#: contrib/auth/models.py:18 contrib/auth/models.py:27
-#, fuzzy
msgid "permissions"
-msgstr "Rettigheter"
+msgstr "rettigheter"
#: contrib/auth/models.py:29
-#, fuzzy
msgid "group"
-msgstr "Gruppe"
+msgstr "gruppe"
#: contrib/auth/models.py:30 contrib/auth/models.py:65
-#, fuzzy
msgid "groups"
-msgstr "Grupper"
+msgstr "grupper"
#: contrib/auth/models.py:55
msgid "username"
@@ -1205,7 +1194,7 @@ msgstr "administrasjons status"
#: contrib/auth/models.py:60
msgid "Designates whether the user can log into this admin site."
-msgstr "Bestemmer om brukeren kan logge inn på denne administrasjons siden."
+msgstr "Bestemmer om brukeren kan logge inn på dette administrasjons sted."
#: contrib/auth/models.py:61
msgid "active"
@@ -1217,7 +1206,7 @@ msgstr "super bruker"
#: contrib/auth/models.py:63
msgid "last login"
-msgstr "liste logg inn"
+msgstr "siste logg inn"
#: contrib/auth/models.py:64
msgid "date joined"
@@ -1232,19 +1221,16 @@ msgstr ""
"tilgang til gruppene han/hun er i."
#: contrib/auth/models.py:67
-#, fuzzy
msgid "user permissions"
msgstr "Rettigheter"
#: contrib/auth/models.py:70
-#, fuzzy
msgid "user"
-msgstr "Bruker"
+msgstr "bruker"
#: contrib/auth/models.py:71
-#, fuzzy
msgid "users"
-msgstr "Brukere"
+msgstr "brukere"
#: contrib/auth/models.py:76
msgid "Personal info"
@@ -1263,9 +1249,8 @@ msgid "Groups"
msgstr "Grupper"
#: contrib/auth/models.py:219
-#, fuzzy
msgid "message"
-msgstr "Meldinger"
+msgstr "Melding"
#: contrib/auth/forms.py:30
msgid ""
@@ -1274,9 +1259,8 @@ msgid ""
msgstr ""
#: contrib/contenttypes/models.py:25
-#, fuzzy
msgid "python model class name"
-msgstr "python modul navn"
+msgstr "python modell klasse navn"
#: contrib/contenttypes/models.py:28
msgid "content type"
@@ -1312,23 +1296,23 @@ msgstr "domene navn"
#: contrib/sites/models.py:11
msgid "display name"
-msgstr "vist navn"
+msgstr "vise navn"
#: contrib/sites/models.py:15
msgid "site"
-msgstr "side"
+msgstr "nettsted"
#: contrib/sites/models.py:16
msgid "sites"
-msgstr "sider"
+msgstr "nettsteder"
#: utils/translation.py:360
msgid "DATE_FORMAT"
-msgstr "j. M U"
+msgstr "j. M Y"
#: utils/translation.py:361
msgid "DATETIME_FORMAT"
-msgstr "j. M U - h:i"
+msgstr "j. M Y - h:i"
#: utils/translation.py:362
msgid "TIME_FORMAT"
@@ -1336,7 +1320,7 @@ msgstr "h:i"
#: utils/dates.py:6
msgid "Monday"
-msgstr "Mondag"
+msgstr "Mandag"
#: utils/dates.py:6
msgid "Tuesday"
@@ -1411,54 +1395,52 @@ msgid "December"
msgstr "Desember"
#: utils/dates.py:19
-#, fuzzy
msgid "jan"
-msgstr "og"
+msgstr "jan"
#: utils/dates.py:19
msgid "feb"
-msgstr ""
+msgstr "feb"
#: utils/dates.py:19
msgid "mar"
-msgstr ""
+msgstr "mar"
#: utils/dates.py:19
msgid "apr"
-msgstr ""
+msgstr "apr"
#: utils/dates.py:19
-#, fuzzy
msgid "may"
-msgstr "Mai"
+msgstr "mai"
#: utils/dates.py:19
msgid "jun"
-msgstr ""
+msgstr "jun"
#: utils/dates.py:20
msgid "jul"
-msgstr ""
+msgstr "jul"
#: utils/dates.py:20
msgid "aug"
-msgstr ""
+msgstr "aug"
#: utils/dates.py:20
msgid "sep"
-msgstr ""
+msgstr "sep"
#: utils/dates.py:20
msgid "oct"
-msgstr ""
+msgstr "okt"
#: utils/dates.py:20
msgid "nov"
-msgstr ""
+msgstr "nov"
#: utils/dates.py:20
msgid "dec"
-msgstr ""
+msgstr "des"
#: utils/dates.py:27
msgid "Jan."
@@ -1466,7 +1448,7 @@ msgstr "Jan."
#: utils/dates.py:27
msgid "Feb."
-msgstr "Fef."
+msgstr "Feb."
#: utils/dates.py:28
msgid "Aug."
@@ -1491,40 +1473,38 @@ msgstr "Des."
#: utils/timesince.py:12
msgid "year"
msgid_plural "years"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ã¥r"
+msgstr[1] "Ã¥r"
#: utils/timesince.py:13
msgid "month"
msgid_plural "months"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "måned"
+msgstr[1] "måndeder"
#: utils/timesince.py:14
msgid "week"
msgid_plural "weeks"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "uke"
+msgstr[1] "uker"
#: utils/timesince.py:15
-#, fuzzy
msgid "day"
msgid_plural "days"
-msgstr[0] "Mai"
-msgstr[1] "Mai"
+msgstr[0] "dag"
+msgstr[1] "dager"
#: utils/timesince.py:16
msgid "hour"
msgid_plural "hours"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "time"
+msgstr[1] "timer"
#: utils/timesince.py:17
-#, fuzzy
msgid "minute"
msgid_plural "minutes"
-msgstr[0] "side"
-msgstr[1] "side"
+msgstr[0] "minutt"
+msgstr[1] "minutter"
#: conf/global_settings.py:37
msgid "Bengali"
@@ -1548,7 +1528,7 @@ msgstr "Tysk"
#: conf/global_settings.py:42
msgid "Greek"
-msgstr ""
+msgstr "Gresk"
#: conf/global_settings.py:43
msgid "English"
@@ -1568,11 +1548,11 @@ msgstr "Galisisk"
#: conf/global_settings.py:47
msgid "Hungarian"
-msgstr ""
+msgstr "Ungarsk"
#: conf/global_settings.py:48
msgid "Hebrew"
-msgstr ""
+msgstr "Hebraiske"
#: conf/global_settings.py:49
msgid "Icelandic"
@@ -1584,11 +1564,11 @@ msgstr "Italiensk"
#: conf/global_settings.py:51
msgid "Japanese"
-msgstr ""
+msgstr "Japansk"
#: conf/global_settings.py:52
msgid "Dutch"
-msgstr ""
+msgstr "Nederlandsk"
#: conf/global_settings.py:53
msgid "Norwegian"
@@ -1600,7 +1580,7 @@ msgstr "Brasiliansk"
#: conf/global_settings.py:55
msgid "Romanian"
-msgstr "Romansk"
+msgstr "Rumensk"
#: conf/global_settings.py:56
msgid "Russian"
@@ -1611,9 +1591,8 @@ msgid "Slovak"
msgstr "Slovakisk"
#: conf/global_settings.py:58
-#, fuzzy
msgid "Slovenian"
-msgstr "Slovakisk"
+msgstr "Slovensk"
#: conf/global_settings.py:59
msgid "Serbian"
@@ -1624,9 +1603,8 @@ msgid "Swedish"
msgstr "Svensk"
#: conf/global_settings.py:61
-#, fuzzy
msgid "Ukrainian"
-msgstr "Brasiliansk"
+msgstr "Ukrainsk"
#: conf/global_settings.py:62
msgid "Simplified Chinese"
@@ -1634,14 +1612,13 @@ msgstr "Simplifisert Kinesisk"
#: conf/global_settings.py:63
msgid "Traditional Chinese"
-msgstr ""
+msgstr "Tradisjonell Kinesisk"
#: core/validators.py:60
msgid "This value must contain only letters, numbers and underscores."
msgstr "Dette feltet må bare inneholde bokstaver, nummer og understreker."
#: core/validators.py:64
-#, fuzzy
msgid ""
"This value must contain only letters, numbers, underscores, dashes or "
"slashes."
@@ -1651,7 +1628,7 @@ msgstr ""
#: core/validators.py:72
msgid "Uppercase letters are not allowed here."
-msgstr "Tor skrift er ikke tillatt her."
+msgstr "Stor bokstaver er ikke tillatt her."
#: core/validators.py:76
msgid "Lowercase letters are not allowed here."
@@ -1687,19 +1664,19 @@ msgstr "Skriv inn et helt nummer."
#: core/validators.py:120
msgid "Only alphabetical characters are allowed here."
-msgstr "Bare alfabetiske bokstaber er tillatt her."
+msgstr "Bare alfabetiske bokstaver er tillatt her."
#: core/validators.py:124
msgid "Enter a valid date in YYYY-MM-DD format."
-msgstr "Skriv inn en dato i Ã…Ã…Ã…Ã…-MM-DD formatet."
+msgstr "Skriv inn en dato i Ã…Ã…Ã…Ã…-MM-DD format."
#: core/validators.py:128
msgid "Enter a valid time in HH:MM format."
-msgstr "Skriv inn tiden i TT:MM formatet."
+msgstr "Skriv inn tiden i TT:MM format."
#: core/validators.py:132 db/models/fields/__init__.py:468
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
-msgstr "Skriv inn dato og tid i Ã…Ã…Ã…Ã…-MM-DD TT:MM formatet."
+msgstr "Skriv inn dato og tid i Ã…Ã…Ã…Ã…-MM-DD TT:MM format."
#: core/validators.py:136
msgid "Enter a valid e-mail address."
@@ -1722,7 +1699,7 @@ msgstr "Internettadressen %s peker ikke til et godkjent bilde."
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr ""
-"Telefon nummeret må være i XXX-XXX-XXXX formatet. \"%s\" er ikke godkjent."
+"Telefon nummeret må være i XXX-XXX-XXXX format. \"%s\" er ikke godkjent."
#: core/validators.py:167
#, python-format
@@ -1731,7 +1708,7 @@ msgstr "Internettadressen %s peker ikke til en godkjent QuickTime film."
#: core/validators.py:171
msgid "A valid URL is required."
-msgstr "En godkjent internettadresse er påbudt."
+msgstr "En godkjent internettadresse er påkrevd."
#: core/validators.py:185
#, python-format
@@ -1739,7 +1716,7 @@ msgid ""
"Valid HTML is required. Specific errors are:\n"
"%s"
msgstr ""
-"Godkjent HTML er påbudt. Feilene var:\n"
+"Godkjent HTML er påkrevd. Feilene var:\n"
"%s"
#: core/validators.py:192
@@ -1750,7 +1727,7 @@ msgstr "Ikke godkjent XML: %s"
#: core/validators.py:202
#, python-format
msgid "Invalid URL: %s"
-msgstr "Ikke godkjent internettadresse: %s"
+msgstr "Ikke godkjent URL: %s"
#: core/validators.py:206 core/validators.py:208
#, python-format
@@ -1759,7 +1736,7 @@ msgstr "Internettadresse fører til en side som ikke virker."
#: core/validators.py:214
msgid "Enter a valid U.S. state abbreviation."
-msgstr "Skriv inn en godkjent amerikansk stats forkortelse."
+msgstr "Skriv inn en godkjent amerikansk delstat forkortelse."
#: core/validators.py:229
#, python-format
@@ -1771,7 +1748,7 @@ msgstr[1] "Pass munnen din! Ordene %s er ikke tillatt her."
#: core/validators.py:236
#, python-format
msgid "This field must match the '%s' field."
-msgstr "Dette felte må være det samme som i '%s' feltet."
+msgstr "Dette feltet må være det samme som i '%s' feltet."
#: core/validators.py:255
msgid "Please enter something for at least one field."
@@ -1784,12 +1761,12 @@ msgstr "Vennligst skriv inn noe i begge felta, eller la dem stå blanke."
#: core/validators.py:282
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
-msgstr "Dette feltet må bare brukes vist %(field)s er lik %(value)s"
+msgstr "Dette feltet må bare brukes hvis %(field)s er lik %(value)s"
#: core/validators.py:294
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
-msgstr "Dette feltet må bare brukes vist %(field)s ikke er lik %(value)s"
+msgstr "Dette feltet må bare brukes hvis %(field)s ikke er lik %(value)s"
#: core/validators.py:313
msgid "Duplicate values are not allowed."
@@ -1824,13 +1801,13 @@ msgstr[1] "Skriv inn et desimal tall med maksimum %s tall bak komma. "
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr ""
-"Er du sikker på at fila du prøver å laste opp er minimum %s bytes stor?"
+"Vær sikker på at fila du prøver å laste opp er minimum %s bytes stor."
#: core/validators.py:363
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr ""
-"Er du sikker på at fila du prøver å laste opp er maksimum %s bytes stor?"
+"Vær sikker på at fila du prøver å laste opp er maksimum %s bytes stor."
#: core/validators.py:376
msgid "The format for this field is wrong."
@@ -1850,7 +1827,7 @@ msgstr "Klarte ikke å motta noe fra %s."
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr ""
-"Tnternettadressen %(url)s returnerte en ikke godkjent Content-Type '%"
+"Internettadressen %(url)s returnerte en ikke godkjent Content-Type '%"
"(contenttype)s'."
#: core/validators.py:462
@@ -1859,7 +1836,7 @@ msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
"\"%(start)s\".)"
msgstr ""
-"Vennligst lukk taggen %(tag)s på linje %(line)s. (Linja starer med \"%(start)"
+"Vennligst lukk taggen %(tag)s på linje %(line)s. (Linjen starer med \"%(start)"
"s\".)"
#: core/validators.py:466
@@ -1868,7 +1845,7 @@ msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line "
"starts with \"%(start)s\".)"
msgstr ""
-"Noe av teksten som starter på linje %(line)s er ikke tillatt. (Linja starter "
+"Noe av teksten som starter på linje %(line)s er ikke tillatt. (Linjen starter "
"med \"%(start)s\".)"
#: core/validators.py:471
@@ -1877,7 +1854,7 @@ msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
"(start)s\".)"
msgstr ""
-"\"%(attr)s\" på linje %(line)s er ikke en godkjent tillegg. (Linja starter "
+"\"%(attr)s\" på linje %(line)s er ikke en godkjent tillegg. (Linjen starter "
"med \"%(start)s\".)"
#: core/validators.py:476
@@ -1886,7 +1863,7 @@ msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
"(start)s\".)"
msgstr ""
-"\"<%(tag)s>\" på linje %(line)s er ikke en godkjent tag. (linja starter med "
+"\"<%(tag)s>\" på linje %(line)s er ikke en godkjent tag. (linjen starter med "
"\"%(start)s\".)"
#: core/validators.py:480
@@ -1895,7 +1872,7 @@ msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line "
"starts with \"%(start)s\".)"
msgstr ""
-"En tag på linje %(line)s mangler en av de påbydte tillegga. (linja starter "
+"En tag på linje %(line)s mangler en av de påkrevde attributtene. (linjen starter "
"med \"%(start)s\".)"
#: core/validators.py:485
@@ -1904,13 +1881,13 @@ msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
"starts with \"%(start)s\".)"
msgstr ""
-"\"%(attr)s\" tillegg på linje $(line)s har en ikke godkjent verdi. (Linja "
+"\"%(attr)s\" tillegg på linje $(line)s har en ikke godkjent verdi. (Linjen "
"starter med \"%(start)s\".)"
#: db/models/manipulators.py:302
-#, fuzzy, python-format
+#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
-msgstr "$(optname)s med %(fieldname)s finnes allerede."
+msgstr "%(object)s med %(type)s finnes allerede for angitt %(field)s."
#: db/models/fields/__init__.py:40
#, python-format
@@ -1924,37 +1901,31 @@ msgid "This field is required."
msgstr "Dette feltet er påkrevd."
#: db/models/fields/__init__.py:337
-#, fuzzy
msgid "This value must be an integer."
-msgstr "Denne verdien må være 'power' av %s."
+msgstr "Denne verdien må være et heltall."
#: db/models/fields/__init__.py:369
-#, fuzzy
msgid "This value must be either True or False."
-msgstr "Denne verdien må være 'power' av %s."
+msgstr "Denne verdien må være enten \"True\" eller \"False\"."
#: db/models/fields/__init__.py:385
-#, fuzzy
msgid "This field cannot be null."
-msgstr "Dette feltet er feil."
+msgstr "Dette feltet kan ikke være null/tom."
#: db/models/fields/__init__.py:562
-#, fuzzy
msgid "Enter a valid filename."
-msgstr "Skriv inn en godkjent e-post adresse."
+msgstr "Skriv inn et godkjent fil navn."
#: db/models/fields/related.py:43
-#, fuzzy, python-format
+#, python-format
msgid "Please enter a valid %s."
-msgstr "Vennligst skriv inn en godkjent IP adresse."
+msgstr "Vennligst skriv inn en/et gyldig %s."
#: db/models/fields/related.py:579
-#, fuzzy
msgid "Separate multiple IDs with commas."
msgstr "Separer Id-ene med kommaer."
#: db/models/fields/related.py:581
-#, fuzzy
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
@@ -1965,14 +1936,14 @@ msgstr ""
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
msgid_plural ""
"Please enter valid %(self)s IDs. The values %(value)r are invalid."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Skriv inn gyldige %(self)s ID-er. Verdien %(value)r er ikke gyldig."
+msgstr[1] "Skriv inn gyldige %(self)s ID-er. Verdiene %(value)r er ikke gyldige."
#: forms/__init__.py:380
-#, fuzzy, python-format
+#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
-msgstr[0] "Sjekk at teksten er kortere enn %s bokstaver"
+msgstr[0] "Sjekk at teksten er kortere enn %s bokstav"
msgstr[1] "Sjekk at teksten er kortere enn %s bokstaver"
#: forms/__init__.py:385
@@ -1982,7 +1953,7 @@ msgstr "Det er ikke tillatt med flere linjer her."
#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
-msgstr "Velg et av valga; '%(data)s' er ikke i %(choices)s."
+msgstr "Velg et gyldig valg; '%(data)s' er ikke i %(choices)s."
#: forms/__init__.py:645
msgid "The submitted file is empty."
@@ -2002,7 +1973,7 @@ msgstr "Skriv inn et heltall mellom 0 og 32767."
#: template/defaultfilters.py:379
msgid "yes,no,maybe"
-msgstr ""
+msgstr "ja,nei,kanskje"
#, fuzzy
#~ msgid "Comments"
diff --git a/django/conf/locale/no/LC_MESSAGES/djangojs.mo b/django/conf/locale/no/LC_MESSAGES/djangojs.mo
index acdc98a7ef..4b23aba4e0 100644
--- a/django/conf/locale/no/LC_MESSAGES/djangojs.mo
+++ b/django/conf/locale/no/LC_MESSAGES/djangojs.mo
Binary files differ
diff --git a/django/conf/locale/no/LC_MESSAGES/djangojs.po b/django/conf/locale/no/LC_MESSAGES/djangojs.po
index befc101881..c6087646e0 100644
--- a/django/conf/locale/no/LC_MESSAGES/djangojs.po
+++ b/django/conf/locale/no/LC_MESSAGES/djangojs.po
@@ -61,6 +61,15 @@ msgstr "Søndag Mandag Tirsdag Onsdag Torsdag Fredag Lørdag"
msgid "S M T W T F S"
msgstr "S M T O T F L"
+#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
+#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
+msgid "Show"
+msgstr "Vis"
+
+#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
+msgid "Hide"
+msgstr "Skjul"
+
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
@@ -80,7 +89,7 @@ msgstr "24.00"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
-msgstr "18.00"
+msgstr "06.00"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
diff --git a/django/conf/locale/pl/LC_MESSAGES/django.mo b/django/conf/locale/pl/LC_MESSAGES/django.mo
index f7fad56339..d132fc114e 100644
--- a/django/conf/locale/pl/LC_MESSAGES/django.mo
+++ b/django/conf/locale/pl/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/pl/LC_MESSAGES/django.po b/django/conf/locale/pl/LC_MESSAGES/django.po
index b6449e22b0..61fc4d0a90 100644
--- a/django/conf/locale/pl/LC_MESSAGES/django.po
+++ b/django/conf/locale/pl/LC_MESSAGES/django.po
@@ -126,12 +126,10 @@ msgid "approved by staff"
msgstr "zaakceptowano"
#: contrib/comments/models.py:176
-#, fuzzy
msgid "free comment"
msgstr "wolny komentarz"
#: contrib/comments/models.py:177
-#, fuzzy
msgid "free comments"
msgstr "wolne komentarze"
@@ -144,7 +142,6 @@ msgid "score date"
msgstr "data przyznania punktów"
#: contrib/comments/models.py:237
-#, fuzzy
msgid "karma score"
msgstr "ilość punktów"
@@ -243,6 +240,9 @@ msgid ""
"\n"
"%(text)s"
msgstr ""
+"Ten komentarze został dodany przez użytkownika::\n"
+"\n"
+"%(text)s"
#: contrib/comments/views/comments.py:189
#: contrib/comments/views/comments.py:280
@@ -257,19 +257,20 @@ msgstr "Jedno lub więcej wymaganych pól nie zostało wypełnionych"
#: contrib/comments/views/comments.py:197
#: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)"
-msgstr ""
+msgstr "Ktoś próbował obejść zabezpieczenia formularza komentarzy"
#: contrib/comments/views/comments.py:207
#: contrib/comments/views/comments.py:292
msgid ""
"The comment form had an invalid 'target' parameter -- the object ID was "
"invalid"
-msgstr ""
+msgstr "Formularz komentarza miał niepoprawny parametr 'target' -- ID obiektu było "
+"niepoprawne"
#: contrib/comments/views/comments.py:257
#: contrib/comments/views/comments.py:321
msgid "The comment form didn't provide either 'preview' or 'post'"
-msgstr ""
+msgstr "Formularz komentarza nie zapewnił obiektów 'preview' ani 'post'"
#: contrib/comments/templates/comments/form.html:6
#: contrib/comments/templates/comments/form.html:8
@@ -600,7 +601,7 @@ msgstr "Wartość logiczna (True, False, None - prawda, fałsz lub nic)"
#: contrib/admin/views/doc.py:292
msgid "Relation to parent model"
-msgstr ""
+msgstr "Relacja do modelu rodzica"
#: contrib/admin/views/doc.py:293
msgid "Phone number"
@@ -794,6 +795,9 @@ msgid ""
"objects, but your account doesn't have permission to delete the following "
"types of objects:"
msgstr ""
+"Skasowanie %(object_name)s '%(object)s' spowoduje kasację zależnych "
+"obiektów, lecz twoje uprawnienia nie pozwalają na usunięcie następujących "
+"typów obiektów:"
#: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format
@@ -801,6 +805,8 @@ msgid ""
"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
"the following related items will be deleted:"
msgstr ""
+"Czy chcesz skasować %(object_name)s \"%(object)s\"? Wszystkie "
+"zależne obiekty zostaną skasowane:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure"
@@ -820,11 +826,10 @@ msgid "View on site"
msgstr "Pokaż na stronie"
#: contrib/admin/templates/admin/change_form.html:30
-#, fuzzy
msgid "Please correct the error below."
msgid_plural "Please correct the errors below."
msgstr[0] "Proszę popraw poniższy błąd"
-msgstr[1] "Proszę popraw poniższy błąd"
+msgstr[1] "Proszę popraw poniższe błędy"
#: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering"
@@ -965,11 +970,11 @@ msgstr "Zespół %(site_name)s"
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
msgid "Bookmarklets"
-msgstr ""
+msgstr "Zakładki"
#: contrib/admin/templates/admin_doc/bookmarklets.html:5
msgid "Documentation bookmarklets"
-msgstr ""
+msgstr "Zakładki Dokumentacji"
#: contrib/admin/templates/admin_doc/bookmarklets.html:9
msgid ""
@@ -1094,6 +1099,8 @@ msgid ""
"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
"use 'flatpages/default'."
msgstr ""
+"Przykład: 'flatpages/contact_page'. Jeżeli nie podane system użyje "
+"'flatpages/default'."
#: contrib/flatpages/models.py:14
msgid "registration required"
@@ -1105,11 +1112,11 @@ msgstr "Jeżeli zaznaczone - tylko zalogowani użytkownicy bÄ™dÄ… mogli zobaczyÄ
#: contrib/flatpages/models.py:18
msgid "flat page"
-msgstr ""
+msgstr "strona statyczna"
#: contrib/flatpages/models.py:19
msgid "flat pages"
-msgstr ""
+msgstr "strony statyczne"
#: contrib/auth/models.py:13 contrib/auth/models.py:26
msgid "name"
@@ -1117,7 +1124,7 @@ msgstr "nazwa"
#: contrib/auth/models.py:15
msgid "codename"
-msgstr ""
+msgstr "nazwa kodowa"
#: contrib/auth/models.py:17
msgid "permission"
@@ -1161,11 +1168,11 @@ msgstr "Użyj '[algo]$[salt]$[hexdigest]'"
#: contrib/auth/models.py:60
msgid "staff status"
-msgstr "stan w zespole"
+msgstr "w zespole"
#: contrib/auth/models.py:60
msgid "Designates whether the user can log into this admin site."
-msgstr "Oznaczy czy użytkownik może zalogować się do panelu admina."
+msgstr "Oznacza czy użytkownik może zalogować się do panelu admina."
#: contrib/auth/models.py:61
msgid "active"
@@ -1195,15 +1202,14 @@ msgstr ""
msgid "user permissions"
msgstr "uprawnienia użytkownika"
+#kurwa
#: contrib/auth/models.py:70
-#, fuzzy
msgid "user"
-msgstr "Użytkownik"
+msgstr "użytkownik"
#: contrib/auth/models.py:71
-#, fuzzy
msgid "users"
-msgstr "Uzytkownicy"
+msgstr "użytkownicy"
#: contrib/auth/models.py:76
msgid "Personal info"
@@ -1222,7 +1228,6 @@ msgid "Groups"
msgstr "Grupy"
#: contrib/auth/models.py:219
-#, fuzzy
msgid "message"
msgstr "wiadomość"
@@ -1371,7 +1376,6 @@ msgid "December"
msgstr "Grudzień"
#: utils/dates.py:19
-#, fuzzy
msgid "jan"
msgstr "sty"
@@ -1472,11 +1476,10 @@ msgstr[0] "dzień"
msgstr[1] "dni"
#: utils/timesince.py:16
-#, fuzzy
msgid "hour"
msgid_plural "hours"
msgstr[0] "godzina"
-msgstr[1] "godzina"
+msgstr[1] "godzin"
#: utils/timesince.py:17
msgid "minute"
@@ -1569,7 +1572,6 @@ msgid "Slovak"
msgstr "Słowacki"
#: conf/global_settings.py:58
-#, fuzzy
msgid "Slovenian"
msgstr "Słowacki"
@@ -1582,9 +1584,8 @@ msgid "Swedish"
msgstr "Szwedzki"
#: conf/global_settings.py:61
-#, fuzzy
msgid "Ukrainian"
-msgstr "Brazylijski"
+msgstr "Ukraiński"
#: conf/global_settings.py:62
msgid "Simplified Chinese"
@@ -1715,14 +1716,14 @@ msgstr "Odnośnik %s jest nieprawidłowy."
#: core/validators.py:214
msgid "Enter a valid U.S. state abbreviation."
-msgstr "Wpisz poprawny kod stanu U.S."
+msgstr "Wpisz poprawny kod stanu U.S.A."
#: core/validators.py:229
-#, fuzzy, python-format
+#, python-format
msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Nie wolno przeklinać! Słowo %s jest niedozwolone."
-msgstr[1] "Nie wolno przeklinać! Słowo %s jest niedozwolone."
+msgstr[1] "Nie wolno przeklinać! Słowa %s są niedozwolone."
#: core/validators.py:236
#, python-format
@@ -1745,11 +1746,11 @@ msgstr "To pole musi być uzupełnione jeśli %(field)s jest %(value)s"
#: core/validators.py:294
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
-msgstr ""
+msgstr "To pole musi być wypełnione jeżeli %(field)s nie jest %(value)s"
#: core/validators.py:313
msgid "Duplicate values are not allowed."
-msgstr ""
+msgstr "Duplikaty sÄ… niedozwolone."
#: core/validators.py:336
#, python-format
@@ -1761,20 +1762,20 @@ msgid "Please enter a valid decimal number."
msgstr "Proszę wpisać poprawną liczbę dziesiętną."
#: core/validators.py:349
-#, fuzzy, python-format
+#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
"Please enter a valid decimal number with at most %s total digits."
-msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną."
-msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną."
+msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną zawierającą nie więcej niż %s cyfry."
+msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną zawierającą nie więcej niż %s cyfr."
#: core/validators.py:352
-#, fuzzy, python-format
+#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
"Please enter a valid decimal number with at most %s decimal places."
-msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną."
-msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną."
+msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną z dokładnością do %s miejsca po przecinku."
+msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną z dokładnością do %s miejsc po przecinku."
#: core/validators.py:362
#, python-format
@@ -1797,13 +1798,14 @@ msgstr "To pole jest nieprawidłowe."
#: core/validators.py:426
#, python-format
msgid "Could not retrieve anything from %s."
-msgstr "Nie można otrzymać nic z %s."
+msgstr "Nie można nic pobrać z %s."
#: core/validators.py:429
#, python-format
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr ""
+"URL %(url)s zwrócił niepoprawny Content-Type header '%(contenttype)s'."
#: core/validators.py:462
@@ -1866,17 +1868,15 @@ msgstr "To pole jest wymagane"
#: db/models/fields/__init__.py:337
msgid "This value must be an integer."
-msgstr ""
+msgstr "Ta wartość musi być liczbą całkowitą"
#: db/models/fields/__init__.py:369
-#, fuzzy
msgid "This value must be either True or False."
-msgstr "Wartość logiczna (True, False - prawda lub fałsz)"
+msgstr "Ta wartość musi być logiczna (True, False - prawda lub fałsz)."
#: db/models/fields/__init__.py:385
-#, fuzzy
msgid "This field cannot be null."
-msgstr "To pole jest nieprawidłowe."
+msgstr "To pole nie może być puste."
#: db/models/fields/__init__.py:562
msgid "Enter a valid filename."
@@ -1888,12 +1888,10 @@ msgid "Please enter a valid %s."
msgstr "Proszę wpisać poprawne %s."
#: db/models/fields/related.py:579
-#, fuzzy
msgid "Separate multiple IDs with commas."
msgstr "Oddziel kilka pól ID przecinkami."
#: db/models/fields/related.py:581
-#, fuzzy
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
@@ -1909,11 +1907,11 @@ msgstr[0] ""
msgstr[1] ""
#: forms/__init__.py:380
-#, fuzzy, python-format
+#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
-msgstr[0] "Upewnij się, że jest mniej niż %s znaków."
-msgstr[1] "Upewnij się, że jest mniej niż %s znaków."
+msgstr[0] "Upewnij się, że tekst ma mniej niż %s znak."
+msgstr[1] "Upewnij się, że tekst ma mniej niż %s znaków."
#: forms/__init__.py:385
msgid "Line breaks are not allowed here."
diff --git a/django/conf/locale/ru/LC_MESSAGES/django.mo b/django/conf/locale/ru/LC_MESSAGES/django.mo
index 562996eee5..12e240529f 100644
--- a/django/conf/locale/ru/LC_MESSAGES/django.mo
+++ b/django/conf/locale/ru/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/ru/LC_MESSAGES/django.po b/django/conf/locale/ru/LC_MESSAGES/django.po
index 024b2bfc12..f329efe24f 100644
--- a/django/conf/locale/ru/LC_MESSAGES/django.po
+++ b/django/conf/locale/ru/LC_MESSAGES/django.po
@@ -5,97 +5,102 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: django\n"
+"Project-Id-Version: django 0.95\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:11+0200\n"
-"PO-Revision-Date: 2005-11-26 00:00\n"
-"Last-Translator: Dmitry Sorokin <ds@dial.com.ru>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"PO-Revision-Date: 2006-09-07 15:28+0300\n"
+"Last-Translator: Alexander Yakovlev <AYakovlev@rambler.ru>\n"
+"Language-Team: Dialcom Services <greg@dial.com.ru>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Poedit-Language: Russian\n"
+"X-Poedit-Country: RUSSIAN FEDERATION\n"
+"X-Poedit-SourceCharset: utf-8\n"
-#: contrib/comments/models.py:67 contrib/comments/models.py:166
+#: contrib/comments/models.py:67
+#: contrib/comments/models.py:166
msgid "object ID"
msgstr "ID объекта"
#: contrib/comments/models.py:68
msgid "headline"
-msgstr "заголовок"
+msgstr "Заголовок"
-#: contrib/comments/models.py:69 contrib/comments/models.py:90
+#: contrib/comments/models.py:69
+#: contrib/comments/models.py:90
#: contrib/comments/models.py:167
msgid "comment"
-msgstr "комментарий"
+msgstr "Комментарий"
#: contrib/comments/models.py:70
msgid "rating #1"
-msgstr "рейтинг #1"
+msgstr "рейтинг №1"
#: contrib/comments/models.py:71
msgid "rating #2"
-msgstr "рейтинг #2"
+msgstr "рейтинг №2"
#: contrib/comments/models.py:72
msgid "rating #3"
-msgstr "рейтинг #3"
+msgstr "рейтинг №3"
#: contrib/comments/models.py:73
msgid "rating #4"
-msgstr "рейтинг #4"
+msgstr "рейтинг №4"
#: contrib/comments/models.py:74
msgid "rating #5"
-msgstr "рейтинг #5"
+msgstr "рейтинг №5"
#: contrib/comments/models.py:75
msgid "rating #6"
-msgstr "рейтинг #6"
+msgstr "рейтинг №6"
#: contrib/comments/models.py:76
msgid "rating #7"
-msgstr "рейтинг #7"
+msgstr "рейтинг №7"
#: contrib/comments/models.py:77
msgid "rating #8"
-msgstr "рейтинг #8"
+msgstr "рейтинг №8"
#: contrib/comments/models.py:82
msgid "is valid rating"
-msgstr "доÑтупный рейтинг"
+msgstr "ДопуÑтимый рейтинг"
-#: contrib/comments/models.py:83 contrib/comments/models.py:169
+#: contrib/comments/models.py:83
+#: contrib/comments/models.py:169
msgid "date/time submitted"
-msgstr "дата/Ð²Ñ€ÐµÐ¼Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ"
+msgstr "Дата/Ð²Ñ€ÐµÐ¼Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ"
-#: contrib/comments/models.py:84 contrib/comments/models.py:170
+#: contrib/comments/models.py:84
+#: contrib/comments/models.py:170
msgid "is public"
-msgstr "публичный"
+msgstr "Публичный"
-#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
+#: contrib/comments/models.py:85
+#: contrib/admin/views/doc.py:289
msgid "IP address"
-msgstr "IP адреÑ"
+msgstr "IP-адреÑ"
#: contrib/comments/models.py:86
msgid "is removed"
-msgstr "удален"
+msgstr "Удален"
#: contrib/comments/models.py:86
-msgid ""
-"Check this box if the comment is inappropriate. A \"This comment has been "
-"removed\" message will be displayed instead."
-msgstr ""
-"Отметте, еÑли комментарий нежелателен. Сообщение \"Этот комментарий был "
-"удалён\" будет показано взамен."
+msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead."
+msgstr "Отметьте, еÑли комментарий нежелателен. Сообщение \"Этот комментарий был удалён\" будет показано взамен."
#: contrib/comments/models.py:91
-#, fuzzy
msgid "comments"
-msgstr "комментарий"
+msgstr "Комментарии"
-#: contrib/comments/models.py:131 contrib/comments/models.py:207
+#: contrib/comments/models.py:131
+#: contrib/comments/models.py:207
msgid "Content object"
-msgstr "Объект наполнениÑ"
+msgstr "Объект Ñодержимого"
#: contrib/comments/models.py:159
#, python-format
@@ -106,7 +111,7 @@ msgid ""
"\n"
"http://%(domain)s%(url)s"
msgstr ""
-"Добавил %(user)s %(date)s\n"
+"Добавил %(user)s %(date)s\n"
"\n"
"%(comment)s\n"
"\n"
@@ -114,15 +119,15 @@ msgstr ""
#: contrib/comments/models.py:168
msgid "person's name"
-msgstr "Ð¸Ð¼Ñ Ñ‡ÐµÐ»Ð¾Ð²ÐµÐºÐ°"
+msgstr "Ð˜Ð¼Ñ Ñ‡ÐµÐ»Ð¾Ð²ÐµÐºÐ°"
#: contrib/comments/models.py:171
msgid "ip address"
-msgstr "ip адреÑ:"
+msgstr "IP-адреÑ:"
#: contrib/comments/models.py:173
msgid "approved by staff"
-msgstr "одобрено админиÑтрацией"
+msgstr "Одобрено админиÑтрацией"
#: contrib/comments/models.py:176
msgid "free comment"
@@ -134,24 +139,24 @@ msgstr "Свободные комментарии"
#: contrib/comments/models.py:233
msgid "score"
-msgstr "Ñчёт"
+msgstr "Счёт"
#: contrib/comments/models.py:234
msgid "score date"
-msgstr "Ñчёт времени"
+msgstr "Ð’Ñ€ÐµÐ¼Ñ Ñчёта"
#: contrib/comments/models.py:237
msgid "karma score"
-msgstr "Карма Ñчёт"
+msgstr "КармичеÑкий Ñчёт"
#: contrib/comments/models.py:238
msgid "karma scores"
-msgstr "Карма Ñчета"
+msgstr "КармичеÑкие Ñчета"
#: contrib/comments/models.py:242
#, python-format
msgid "%(score)d rating by %(user)s"
-msgstr ""
+msgstr "%(score)d рейтинг Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %(user)s"
#: contrib/comments/models.py:258
#, python-format
@@ -160,21 +165,21 @@ msgid ""
"\n"
"%(text)s"
msgstr ""
-"Этот комментарий был отмечен %(user)s:\n"
+"Этот комментарий был отмечен пользователем %(user)s:\n"
"\n"
"%(text)s"
#: contrib/comments/models.py:265
msgid "flag date"
-msgstr "отметка даты"
+msgstr "Дата отметки"
#: contrib/comments/models.py:268
msgid "user flag"
-msgstr "Признак пользователÑ"
+msgstr "Отметка пользователÑ"
#: contrib/comments/models.py:269
msgid "user flags"
-msgstr "Признаки пользователÑ"
+msgstr "Отметки пользователÑ"
#: contrib/comments/models.py:273
#, python-format
@@ -183,11 +188,11 @@ msgstr "Отмечен %r"
#: contrib/comments/models.py:278
msgid "deletion date"
-msgstr "дата удалениÑ"
+msgstr "Дата удалениÑ"
#: contrib/comments/models.py:280
msgid "moderator deletion"
-msgstr "Удаленно модератором"
+msgstr "Удаление модератором"
#: contrib/comments/models.py:281
msgid "moderator deletions"
@@ -196,7 +201,7 @@ msgstr "Ð£Ð´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð´ÐµÑ€Ð°Ñ‚Ð¾Ñ€Ð¾Ð¼"
#: contrib/comments/models.py:285
#, python-format
msgid "Moderator deletion by %r"
-msgstr ""
+msgstr "Ð£Ð´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð´ÐµÑ€Ð°Ñ‚Ð¾Ñ€Ð° %r"
#: contrib/comments/views/karma.py:19
msgid "Anonymous users cannot vote"
@@ -211,24 +216,31 @@ msgid "No voting for yourself"
msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð³Ð¾Ð»Ð¾Ñовать за ÑебÑ"
#: contrib/comments/views/comments.py:28
-msgid ""
-"This rating is required because you've entered at least one other rating."
-msgstr ""
+msgid "This rating is required because you've entered at least one other rating."
+msgstr "Этот рейтинг обÑзателен, так как вы уже ввели как минимум еще один рейтинг."
#: contrib/comments/views/comments.py:112
#, python-format
msgid ""
-"This comment was posted by a user who has posted fewer than %(count)s "
-"comment:\n"
+"This comment was posted by a user who has posted fewer than %(count)s comment:\n"
"\n"
"%(text)s"
msgid_plural ""
-"This comment was posted by a user who has posted fewer than %(count)s "
-"comments:\n"
+"This comment was posted by a user who has posted fewer than %(count)s comments:\n"
"\n"
"%(text)s"
msgstr[0] ""
+"Этот комментарий Ñделан пользователем, который отправил меньше %(count)s комментариÑ:\n"
+"\n"
+"%(text)s"
msgstr[1] ""
+"Этот комментарий Ñделан пользователем, который отправил меньше %(count)s комментариев:\n"
+"\n"
+"%(text)s"
+msgstr[2] ""
+"Этот комментарий Ñделан пользователем, который отправил меньше %(count)s комментариев:\n"
+"\n"
+"%(text)s"
#: contrib/comments/views/comments.py:117
#, python-format
@@ -237,14 +249,14 @@ msgid ""
"\n"
"%(text)s"
msgstr ""
-"Коментарий был добавлен ндоверенным пользователем:\n"
+"Коментарий был добавлен недоверенным пользователем:\n"
"\n"
"%(text)s"
#: contrib/comments/views/comments.py:189
#: contrib/comments/views/comments.py:280
msgid "Only POSTs are allowed"
-msgstr "Только POSTы разрешены"
+msgstr "Разрешены только POSTы"
#: contrib/comments/views/comments.py:193
#: contrib/comments/views/comments.py:284
@@ -254,20 +266,17 @@ msgstr "Одно или больше обÑзательных полей не б
#: contrib/comments/views/comments.py:197
#: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)"
-msgstr "Кто-то вмешиваетÑÑ Ð² форму ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ (нарушение безопаÑноÑти)"
+msgstr "Кто-то вмешалÑÑ Ð² форму ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ (нарушение безопаÑноÑти)"
#: contrib/comments/views/comments.py:207
#: contrib/comments/views/comments.py:292
-msgid ""
-"The comment form had an invalid 'target' parameter -- the object ID was "
-"invalid"
-msgstr ""
-"Форма ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð¸Ð¼ÐµÐµÑ‚ неверный 'target' параметр -- ID объекта неверно"
+msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid"
+msgstr "Форма ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð¸Ð¼ÐµÐ»Ð° неверный параметр 'target' -- ID объекта неверен"
#: contrib/comments/views/comments.py:257
#: contrib/comments/views/comments.py:321
msgid "The comment form didn't provide either 'preview' or 'post'"
-msgstr "Форма ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð½Ðµ обеÑпечивает и 'preview' или 'post'"
+msgstr "Форма ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð½Ðµ предоÑтавила ни 'предпроÑмотр', ни 'отправить'"
#: contrib/comments/templates/comments/form.html:6
#: contrib/comments/templates/comments/form.html:8
@@ -312,7 +321,7 @@ msgstr "Рейтинги"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Required"
-msgstr "Ðеобходимое"
+msgstr "ОбÑзательное"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
@@ -331,11 +340,11 @@ msgstr "Комментарий:"
#: contrib/comments/templates/comments/form.html:32
#: contrib/comments/templates/comments/freeform.html:9
msgid "Preview comment"
-msgstr "ПроÑмотр комментариÑ"
+msgstr "ПредпроÑмотр комментариÑ"
#: contrib/comments/templates/comments/freeform.html:4
msgid "Your name:"
-msgstr "Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ:"
+msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ:"
#: contrib/admin/filterspecs.py:40
#, python-format
@@ -343,8 +352,11 @@ msgid ""
"<h3>By %s:</h3>\n"
"<ul>\n"
msgstr ""
+"<h3>По %s:</h3>\n"
+"<ul>\n"
-#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
+#: contrib/admin/filterspecs.py:70
+#: contrib/admin/filterspecs.py:88
#: contrib/admin/filterspecs.py:143
msgid "All"
msgstr "Ð’Ñе"
@@ -383,7 +395,7 @@ msgstr "ÐеизвеÑтно"
#: contrib/admin/models.py:16
msgid "action time"
-msgstr "Ð²Ñ€ÐµÐ¼Ñ Ð´ÐµÐ¹ÑтвиÑ"
+msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð´ÐµÐ¹ÑтвиÑ"
#: contrib/admin/models.py:19
msgid "object id"
@@ -391,36 +403,33 @@ msgstr "id обьекта"
#: contrib/admin/models.py:20
msgid "object repr"
-msgstr "предÑтавление обьекта"
+msgstr "ПредÑтавление обьекта"
#: contrib/admin/models.py:21
msgid "action flag"
-msgstr "отметка дейÑтвиÑ"
+msgstr "Отметка дейÑтвиÑ"
#: contrib/admin/models.py:22
msgid "change message"
-msgstr "изменить Ñообщение"
+msgstr "Изменить Ñообщение"
#: contrib/admin/models.py:25
msgid "log entry"
-msgstr "Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ"
+msgstr "Ð–ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ"
#: contrib/admin/models.py:26
msgid "log entries"
-msgstr "журнальные запиÑи"
+msgstr "Журнальные запиÑи"
#: contrib/admin/templatetags/admin_list.py:228
msgid "All dates"
msgstr "Ð’Ñе даты"
-#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
+#: contrib/admin/views/decorators.py:9
+#: contrib/auth/forms.py:36
#: contrib/auth/forms.py:41
-msgid ""
-"Please enter a correct username and password. Note that both fields are case-"
-"sensitive."
-msgstr ""
-"ПожалуйÑта, вводите верные данные Ð¸Ð¼ÐµÐ½Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. Помните, оба "
-"Ð¿Ð¾Ð»Ñ Ñ‡ÑƒÐ²Ñтвительны к региÑтру."
+msgid "Please enter a correct username and password. Note that both fields are case-sensitive."
+msgstr "ПожалуйÑта, введите верные Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. Помните, оба Ð¿Ð¾Ð»Ñ Ñ‡ÑƒÐ²Ñтвительны к региÑтру."
#: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25
@@ -428,20 +437,12 @@ msgid "Log in"
msgstr "Вход"
#: contrib/admin/views/decorators.py:61
-msgid ""
-"Please log in again, because your session has expired. Don't worry: Your "
-"submission has been saved."
-msgstr ""
-"ПожалуйÑта войдите Ñнова, поÑколькук ваша ÑеÑÑÐ¸Ñ ÑƒÑтарела. Ðе беÑпокойтеÑÑŒ:"
-"введенные вами данные Ñохранены."
+msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved."
+msgstr "ПожалуйÑта, войдите Ñнова, поÑкольку ваша ÑеÑÑÐ¸Ñ ÑƒÑтарела. Ðе беÑпокойтеÑÑŒ: введенные вами данные Ñохранены."
#: contrib/admin/views/decorators.py:68
-msgid ""
-"Looks like your browser isn't configured to accept cookies. Please enable "
-"cookies, reload this page, and try again."
-msgstr ""
-"Похоже, что ваш броузер не наÑтроен на прием cookies. ПожалуйÑтва включите "
-"cookie, перезагрузите Ñтраницу и попытайтеÑÑŒ Ñнова. "
+msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again."
+msgstr "Похоже, ваш броузер не наÑтроен на прием cookies. ПожалуйÑтва, включите cookie, перезагрузите Ñтраницу и попытайтеÑÑŒ Ñнова."
#: contrib/admin/views/decorators.py:82
msgid "Usernames cannot contain the '@' character."
@@ -450,7 +451,7 @@ msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ может включать ÑимÐ
#: contrib/admin/views/decorators.py:84
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
-msgstr ""
+msgstr "Ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты не ÑвлÑетÑÑ Ð²Ð°ÑˆÐ¸Ð¼ именем пользователÑ. Попробуйте '%s' взамен."
#: contrib/admin/views/main.py:226
msgid "Site administration"
@@ -459,13 +460,15 @@ msgstr "ÐдминиÑтрирование Ñайта"
#: contrib/admin/views/main.py:260
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
-msgstr "%(name)s \"%(obj)s\" были уÑпешно добавлены."
+msgstr "%(name)s \"%(obj)s\" был уÑпешно добавлен."
-#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
+#: contrib/admin/views/main.py:264
+#: contrib/admin/views/main.py:348
msgid "You may edit it again below."
-msgstr "Ð’Ñ‹ Ñнова можете редактировать их внизу"
+msgstr "Ðиже можно Ñнова редактировать его"
-#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
+#: contrib/admin/views/main.py:272
+#: contrib/admin/views/main.py:357
#, python-format
msgid "You may add another %s below."
msgstr "Вы можете добавить %s внизу."
@@ -478,9 +481,10 @@ msgstr "Добавить %s"
#: contrib/admin/views/main.py:336
#, python-format
msgid "Added %s."
-msgstr "Добавлено %s"
+msgstr "Добавлен %s."
-#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
+#: contrib/admin/views/main.py:336
+#: contrib/admin/views/main.py:338
#: contrib/admin/views/main.py:340
msgid "and"
msgstr "и"
@@ -488,27 +492,26 @@ msgstr "и"
#: contrib/admin/views/main.py:338
#, python-format
msgid "Changed %s."
-msgstr "Изменено %s."
+msgstr "Изменен %s."
#: contrib/admin/views/main.py:340
#, python-format
msgid "Deleted %s."
-msgstr "Удалено %s."
+msgstr "Удален %s."
#: contrib/admin/views/main.py:343
msgid "No fields changed."
-msgstr ""
+msgstr "Ðи одно поле не изменено."
#: contrib/admin/views/main.py:346
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
-msgstr ""
+msgstr "%(name)s \"%(obj)s\" был уÑпешно изменен."
#: contrib/admin/views/main.py:354
#, python-format
-msgid ""
-"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
-msgstr ""
+msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
+msgstr "%(name)s \"%(obj)s\" был уÑпешно добавлен. Ðиже можно Ñнова редактировать его."
#: contrib/admin/views/main.py:392
#, python-format
@@ -518,17 +521,17 @@ msgstr "Изменить %s"
#: contrib/admin/views/main.py:470
#, python-format
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
-msgstr "Одно или более %(fieldname)s в %(name)s: %(obj)s"
+msgstr "Один или более %(fieldname)s в %(name)s: %(obj)s"
#: contrib/admin/views/main.py:475
#, python-format
msgid "One or more %(fieldname)s in %(name)s:"
-msgstr "Одно или более %(fieldname)s в %(name)s:"
+msgstr "Один или более %(fieldname)s в %(name)s:"
#: contrib/admin/views/main.py:508
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
-msgstr "%(name)s \"%(obj)s\" было уÑпешно удалено."
+msgstr "%(name)s \"%(obj)s\" был уÑпешно удален."
#: contrib/admin/views/main.py:511
msgid "Are you sure?"
@@ -537,7 +540,7 @@ msgstr "Вы уверены?"
#: contrib/admin/views/main.py:533
#, python-format
msgid "Change history: %s"
-msgstr "Измени иÑторию: %s"
+msgstr "ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹: %s"
#: contrib/admin/views/main.py:565
#, python-format
@@ -549,9 +552,12 @@ msgstr "Выберите %s"
msgid "Select %s to change"
msgstr "Выберите %s Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ"
-#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
-#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
-#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
+#: contrib/admin/views/doc.py:277
+#: contrib/admin/views/doc.py:286
+#: contrib/admin/views/doc.py:288
+#: contrib/admin/views/doc.py:294
+#: contrib/admin/views/doc.py:295
+#: contrib/admin/views/doc.py:297
msgid "Integer"
msgstr "Целое"
@@ -559,7 +565,8 @@ msgstr "Целое"
msgid "Boolean (Either True or False)"
msgstr "ЛогичеÑкое (True или False)"
-#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
+#: contrib/admin/views/doc.py:279
+#: contrib/admin/views/doc.py:296
#, python-format
msgid "String (up to %(maxlength)s)"
msgstr "Строка (до %(maxlength)s Ñимволов)"
@@ -578,9 +585,10 @@ msgstr "Дата (Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸ÐµÐ¼ времени)"
#: contrib/admin/views/doc.py:283
msgid "E-mail address"
-msgstr "E-mail адреÑ"
+msgstr "ÐÐ´Ñ€ÐµÑ Ñлектронной почты"
-#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
+#: contrib/admin/views/doc.py:284
+#: contrib/admin/views/doc.py:287
msgid "File path"
msgstr "Путь к файлу"
@@ -594,7 +602,7 @@ msgstr "ЛогичеÑкое (True, False или None)"
#: contrib/admin/views/doc.py:292
msgid "Relation to parent model"
-msgstr ""
+msgstr "СвÑзь Ñ Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÑкой моделью"
#: contrib/admin/views/doc.py:293
msgid "Phone number"
@@ -608,17 +616,18 @@ msgstr "ТекÑÑ‚"
msgid "Time"
msgstr "ВремÑ"
-#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
+#: contrib/admin/views/doc.py:300
+#: contrib/flatpages/models.py:7
msgid "URL"
msgstr "URL"
#: contrib/admin/views/doc.py:301
msgid "U.S. state (two uppercase letters)"
-msgstr "Штат СШР(два заглавных Ñимвола)"
+msgstr "Штат СШР(две заглавные буквы)"
#: contrib/admin/views/doc.py:302
msgid "XML text"
-msgstr "XML текÑÑ‚"
+msgstr "ТекÑÑ‚ XML"
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5
@@ -685,15 +694,11 @@ msgstr "ДейÑтвие"
#: contrib/admin/templates/admin/object_history.html:26
msgid "DATE_WITH_TIME_FULL"
-msgstr "j. N Y, H:i"
+msgstr "j N Y H:i"
#: contrib/admin/templates/admin/object_history.html:36
-msgid ""
-"This object doesn't have a change history. It probably wasn't added via this "
-"admin site."
-msgstr ""
-"Данный обьект не имеет иÑтории изменениÑ. Возможно он не был добавлен через "
-"данный админиÑтративный Ñайт."
+msgid "This object doesn't have a change history. It probably wasn't added via this admin site."
+msgstr "Данный обьект не имеет иÑтории изменений. Возможно, он был добавлен не через данный админиÑтративный Ñайт."
#: contrib/admin/templates/admin/base_site.html:4
msgid "Django site admin"
@@ -716,12 +721,8 @@ msgid "Server Error <em>(500)</em>"
msgstr "Ошибка Ñервера <em>(500)</em>"
#: contrib/admin/templates/admin/500.html:10
-msgid ""
-"There's been an error. It's been reported to the site administrators via e-"
-"mail and should be fixed shortly. Thanks for your patience."
-msgstr ""
-"Произошла ошибка. Отчет об ошибке отправлен админиÑтраторам Ñайта по e-mailи "
-"она должна быть вÑкоре иÑправлена. Благодарим Ð²Ð°Ñ Ð½Ð° терпение и помощь."
+msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience."
+msgstr "Произошла ошибка. Отчет об ошибке отправлен админиÑтраторам Ñайта по Ñлектронной почте, ошибка должна быть вÑкоре иÑправлена. Благодарим Ð²Ð°Ñ Ð½Ð° терпение и помощь."
#: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8
@@ -735,7 +736,7 @@ msgstr "К Ñожалению, Ð·Ð°Ð¿Ñ€Ð°ÑˆÐ¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²Ð°Ð¼Ð¸ ÑтраниÑ
#: contrib/admin/templates/admin/index.html:17
#, python-format
msgid "Models available in the %(name)s application."
-msgstr "Модели доÑтупны в %(name)s приложении."
+msgstr "Модели доÑтупны в приложении %(name)s."
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
@@ -752,11 +753,11 @@ msgstr "ÐедоÑтаточно прав Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ."
#: contrib/admin/templates/admin/index.html:52
msgid "Recent Actions"
-msgstr "ПоÑледние ДейÑтвиÑ"
+msgstr "ПоÑледние дейÑтвиÑ"
#: contrib/admin/templates/admin/index.html:53
msgid "My Actions"
-msgstr "Мои ДейÑтвиÑ"
+msgstr "Мои дейÑтвиÑ"
#: contrib/admin/templates/admin/index.html:57
msgid "None available"
@@ -782,23 +783,13 @@ msgstr "Удалить"
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
-msgid ""
-"Deleting the %(object_name)s '%(object)s' would result in deleting related "
-"objects, but your account doesn't have permission to delete the following "
-"types of objects:"
-msgstr ""
-"Удаление объекта %(object_name)s '%(object)s' приведет к удалению завиÑимых "
-"Ñлементов, но предоÑтавленных вам прав недоÑтаточно Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñледующих "
-"типов объектов:"
+msgid "Deleting the %(object_name)s '%(object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:"
+msgstr "Удаление объекта %(object_name)s '%(object)s' привело бы к удалению ÑвÑзанных Ñлементов, но предоÑтавленных вам прав недоÑтаточно Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñледующих типов объектов:"
#: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format
-msgid ""
-"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
-"the following related items will be deleted:"
-msgstr ""
-"Ð’Ñ‹ уверены, что хотите удалить %(object_name)s \"%(object)s\"? Ð’Ñе "
-"Ñледующие объекты также будут удалены:"
+msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of the following related items will be deleted:"
+msgstr "Ð’Ñ‹ уверены, что хотите удалить %(object_name)s \"%(object)s\"? Ð’Ñе Ñледующие ÑвÑзанные объекты также будут удалены:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure"
@@ -807,12 +798,24 @@ msgstr "Да, Ñ ÑƒÐ²ÐµÑ€ÐµÐ½"
#: contrib/admin/templates/admin/filter.html:2
#, python-format
msgid " By %(title)s "
-msgstr ""
+msgstr " По %(title)s "
#: contrib/admin/templates/admin/search_form.html:8
msgid "Go"
msgstr "Вперёд"
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "1 result"
+msgid_plural "%(counter)s results"
+msgstr[0] "1 результат"
+msgstr[1] "%(counter)s результата"
+msgstr[2] "%(counter)s результатов"
+
+#: contrib/admin/templates/admin/search_form.html:10
+msgid "%(full_result_count)s total"
+msgstr "%(full_result_count)s вÑего"
+
#: contrib/admin/templates/admin/change_form.html:21
msgid "View on site"
msgstr "Смотреть Ñайт"
@@ -820,8 +823,9 @@ msgstr "Смотреть Ñайт"
#: contrib/admin/templates/admin/change_form.html:30
msgid "Please correct the error below."
msgid_plural "Please correct the errors below."
-msgstr[0] "ПожалуйÑта иÑправьте ошибку ниже."
-msgstr[1] "ПожалуйÑта иÑправьте ошибки ниже."
+msgstr[0] "ПожалуйÑта, иÑправьте ошибку ниже."
+msgstr[1] "ПожалуйÑта, иÑправьте ошибки ниже."
+msgstr[2] "ПожалуйÑта, иÑправьте ошибки ниже."
#: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering"
@@ -871,16 +875,12 @@ msgid "Password reset"
msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ"
#: contrib/admin/templates/registration/password_reset_form.html:12
-msgid ""
-"Forgotten your password? Enter your e-mail address below, and we'll reset "
-"your password and e-mail the new one to you."
-msgstr ""
-"Забыли пароль? Введите ваш e-mail Ð°Ð´Ñ€ÐµÑ Ð½Ð¸Ð¶Ðµ и мы очиÑтим ваш Ñтарый пароль, "
-"и вышлем вам по e-mail новый."
+msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you."
+msgstr "Забыли пароль? Введите Ñвой Ð°Ð´Ñ€ÐµÑ Ñлектронной почты ниже, мы очиÑтим ваш Ñтарый пароль и вышлем вам по e-mail новый."
#: contrib/admin/templates/registration/password_reset_form.html:16
msgid "E-mail address:"
-msgstr "E-mail адреÑ:"
+msgstr "ÐÐ´Ñ€ÐµÑ Ñлектронной почты:"
#: contrib/admin/templates/registration/password_reset_form.html:16
msgid "Reset my password"
@@ -900,20 +900,12 @@ msgid "Password reset successful"
msgstr "УÑÐ¿ÐµÑˆÐ½Ð°Ñ Ð¾Ñ‡Ð¸Ñтка паролÑ"
#: contrib/admin/templates/registration/password_reset_done.html:12
-msgid ""
-"We've e-mailed a new password to the e-mail address you submitted. You "
-"should be receiving it shortly."
-msgstr ""
-"Мы отправили новый пароль по указанному вами адреÑу Ñлектронной почты. Ð’Ñ‹ "
-"должны его вÑкоре получить."
+msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly."
+msgstr "Мы отправили новый пароль по указанному вами адреÑу Ñлектронной почты. Ð’Ñкоре вы его получите."
#: contrib/admin/templates/registration/password_change_form.html:12
-msgid ""
-"Please enter your old password, for security's sake, and then enter your new "
-"password twice so we can verify you typed it in correctly."
-msgstr ""
-"Ð’ целÑÑ… безопаÑноÑти, пожалуйÑта, введите ваш Ñтарый пароль, затем - новый "
-"пароль дважды, Ñ Ñ‚ÐµÐ¼, чтобы мы могли убедитьÑÑ Ð² правильноÑти напиÑаниÑ."
+msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly."
+msgstr "Ð’ целÑÑ… безопаÑноÑти, пожалуйÑта, введите Ñвой Ñтарый пароль, затем - новый пароль дважды, Ñ Ñ‚ÐµÐ¼, чтобы мы могли убедитьÑÑ Ð² правильноÑти напиÑаниÑ."
#: contrib/admin/templates/registration/password_change_form.html:17
msgid "Old password:"
@@ -933,12 +925,12 @@ msgstr "Изменение паролÑ"
#: contrib/admin/templates/registration/password_reset_email.html:2
msgid "You're receiving this e-mail because you requested a password reset"
-msgstr "Ð’Ñ‹ получили Ñто Ñообщение потому что была запрошена очиÑтка паролÑ"
+msgstr "Ð’Ñ‹ получили Ñто Ñообщение, потому что была запрошена очиÑтка паролÑ"
#: contrib/admin/templates/registration/password_reset_email.html:3
#, python-format
msgid "for your user account at %(site_name)s"
-msgstr "Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ пользовательÑкого аккаунта на %(site_name)s"
+msgstr "Ð”Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑи на %(site_name)s"
#: contrib/admin/templates/registration/password_reset_email.html:5
#, python-format
@@ -947,7 +939,7 @@ msgstr "Ваш новый пароль: %(new_password)s"
#: contrib/admin/templates/registration/password_reset_email.html:7
msgid "Feel free to change this password by going to this page:"
-msgstr "Ð’Ñ‹ вÑегда можете изменить Ñтот пароль Ð¿ÐµÑ€ÐµÐ¹Ð´Ñ Ð½Ð° Ñтраницу:"
+msgstr "Ð’Ñ‹ вÑегда можете изменить Ñтот пароль, Ð¿ÐµÑ€ÐµÐ¹Ð´Ñ Ð½Ð° Ñтраницу:"
#: contrib/admin/templates/registration/password_reset_email.html:11
msgid "Your username, in case you've forgotten:"
@@ -968,7 +960,7 @@ msgstr "Закладки"
#: contrib/admin/templates/admin_doc/bookmarklets.html:5
msgid "Documentation bookmarklets"
-msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð¿Ð¾ bookmarklets"
+msgstr "Закладки документации"
#: contrib/admin/templates/admin_doc/bookmarklets.html:9
msgid ""
@@ -980,30 +972,29 @@ msgid ""
"as \"internal\" (talk to your system administrator if you aren't sure if\n"
"your computer is \"internal\").</p>\n"
msgstr ""
+"\n"
+"<p class=\"help\">Ð”Ð»Ñ ÑƒÑтановки закладок перетащите ÑÑылку к Ñебе на панель\n"
+"закладок или щелкните правой кнопкой мыши по ÑÑылке и добавьте ее в закладки. Теперь у Ð²Ð°Ñ ÐµÑть возможноÑть\n"
+"выбрать закладку Ñ Ð»ÑŽÐ±Ð¾Ð¹ Ñтраницы Ñайта. Обратите внимание: некоторые из Ñтих\n"
+"закладок требуют, чтобы вы проÑматривали Ñайт Ñ ÐºÐ¾Ð¼Ð¿ÑŒÑŽÑ‚ÐµÑ€Ð°, определенного\n"
+"как \"внутренний\" (уточните у Ñвоего ÑиÑтемного админиÑтратора, еÑли не уверены, ÑвлÑетÑÑ Ð»Ð¸\n"
+"ваш компьютер \"внутренним\").</p>\n"
#: contrib/admin/templates/admin_doc/bookmarklets.html:19
msgid "Documentation for this page"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð¿Ð¾ данной Ñтранице"
#: contrib/admin/templates/admin_doc/bookmarklets.html:20
-msgid ""
-"Jumps you from any page to the documentation for the view that generates "
-"that page."
-msgstr ""
-"Перенаправит Ð²Ð°Ñ Ñ Ð»ÑŽÐ±Ð¾Ð¹ Ñтраницы к проÑмотру документа, который генерирует "
-"Ñту Ñтраницу."
+msgid "Jumps you from any page to the documentation for the view that generates that page."
+msgstr "ПеренаправлÑет Ð²Ð°Ñ Ñ Ð»ÑŽÐ±Ð¾Ð¹ Ñтраницы к документации view, который генерирует Ñту Ñтраницу."
#: contrib/admin/templates/admin_doc/bookmarklets.html:22
msgid "Show object ID"
msgstr "Показать ID обьекта"
#: contrib/admin/templates/admin_doc/bookmarklets.html:23
-msgid ""
-"Shows the content-type and unique ID for pages that represent a single "
-"object."
-msgstr ""
-"Показывает тип Ð½Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ уникальный ID Ð´Ð»Ñ Ñтраниц, которые означают "
-"одинокий объект."
+msgid "Shows the content-type and unique ID for pages that represent a single object."
+msgstr "Показывает тип Ð½Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ уникальный ID Ð´Ð»Ñ Ñтраниц, предÑтавлÑющих один объект."
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
msgid "Edit this object (current window)"
@@ -1011,7 +1002,7 @@ msgstr "Редактировать данный обьект (в текущем
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
msgid "Jumps to the admin page for pages that represent a single object."
-msgstr "Перейти на Ñтраницу админиÑтратор Ð´Ð»Ñ Ñтраниц предÑтавлÑющих один объект."
+msgstr "Перейдет на админиÑтративную Ñтраницу Ð´Ð»Ñ Ñтраниц, предÑтавлÑющих один объект."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)"
@@ -1019,7 +1010,7 @@ msgstr "Редактировать данный обьект (в новом ок
#: contrib/admin/templates/admin_doc/bookmarklets.html:29
msgid "As above, but opens the admin page in a new window."
-msgstr "То же что и выше, но откроет админиÑтративную Ñтраницу в новом окне"
+msgstr "То же что и выше, но откроет админиÑтративную Ñтраницу в новом окне."
#: contrib/admin/templates/widget/date_time.html:3
msgid "Date:"
@@ -1039,67 +1030,55 @@ msgstr "Изменить:"
#: contrib/redirects/models.py:7
msgid "redirect from"
-msgstr "перенаправить из"
+msgstr "Перенаправить из"
#: contrib/redirects/models.py:8
-msgid ""
-"This should be an absolute path, excluding the domain name. Example: '/"
-"events/search/'."
-msgstr ""
-"Это должен быть абÑолютный путь, иÑÐºÐ»ÑŽÑ‡Ð°Ñ Ð´Ð¾Ð¼ÐµÐ½Ð½Ð¾Ðµ имÑ. Пример: '/events/"
-"search/'."
+msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'."
+msgstr "Это должен быть абÑолютный путь без доменного имени. Пример: '/events/search/'."
#: contrib/redirects/models.py:9
msgid "redirect to"
-msgstr "перенаправить на"
+msgstr "Перенаправить на"
#: contrib/redirects/models.py:10
-msgid ""
-"This can be either an absolute path (as above) or a full URL starting with "
-"'http://'."
-msgstr ""
-"Это должен быть, либо абÑолютный путь (как выше) или полный URL начинающийÑÑ "
-"Ñ 'http://'."
+msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'."
+msgstr "Это должен быть абÑолютный путь (как выше) или полный URL, начинающийÑÑ Ñ 'http://'."
#: contrib/redirects/models.py:12
msgid "redirect"
-msgstr "перенаправить"
+msgstr "Перенаправление"
#: contrib/redirects/models.py:13
msgid "redirects"
-msgstr "перенаправлениÑ"
+msgstr "ПеренаправлениÑ"
#: contrib/flatpages/models.py:8
-msgid ""
-"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
-msgstr ""
-"Пример: '/about/contact/'. Будьте уверенны, что вÑтавили завепршающий ÑлÑш."
+msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes."
+msgstr "Пример: '/about/contact/'. Будьте уверенны, что вÑтавили завепршающий ÑлÑш."
#: contrib/flatpages/models.py:9
msgid "title"
-msgstr "заголовок"
+msgstr "Заголовок"
#: contrib/flatpages/models.py:10
msgid "content"
-msgstr "наполнение"
+msgstr "Содержимое"
#: contrib/flatpages/models.py:11
msgid "enable comments"
-msgstr "активировать комментарии"
+msgstr "Ðктивировать комментарии"
#: contrib/flatpages/models.py:12
msgid "template name"
-msgstr "Ð¸Ð¼Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð°"
+msgstr "Ð˜Ð¼Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð°"
#: contrib/flatpages/models.py:13
-msgid ""
-"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
-"use 'flatpages/default'."
-msgstr ""
+msgid "Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'."
+msgstr "Пример: 'flatpages/contact_page'. ЕÑли Ñтот файл не приÑутÑтвует, ÑиÑтема будет иÑпользовать 'flatpages/default'."
#: contrib/flatpages/models.py:14
msgid "registration required"
-msgstr "региÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¾Ð±Ñзательна"
+msgstr "РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¾Ð±Ñзательна"
#: contrib/flatpages/models.py:14
msgid "If this is checked, only logged-in users will be able to view the page."
@@ -1107,25 +1086,27 @@ msgstr "ЕÑли отмечено, только вошедшие пользовÐ
#: contrib/flatpages/models.py:18
msgid "flat page"
-msgstr "проÑÑ‚Ð°Ñ Ñтраница"
+msgstr "ПроÑÑ‚Ð°Ñ Ñтраница"
#: contrib/flatpages/models.py:19
msgid "flat pages"
-msgstr "проÑтые Ñтраницы"
+msgstr "ПроÑтые Ñтраницы"
-#: contrib/auth/models.py:13 contrib/auth/models.py:26
+#: contrib/auth/models.py:13
+#: contrib/auth/models.py:26
msgid "name"
-msgstr "имÑ"
+msgstr "ИмÑ"
#: contrib/auth/models.py:15
msgid "codename"
-msgstr "код"
+msgstr "Кодовое название"
#: contrib/auth/models.py:17
msgid "permission"
-msgstr "Права"
+msgstr "Право"
-#: contrib/auth/models.py:18 contrib/auth/models.py:27
+#: contrib/auth/models.py:18
+#: contrib/auth/models.py:27
msgid "permissions"
msgstr "Права"
@@ -1133,37 +1114,38 @@ msgstr "Права"
msgid "group"
msgstr "Группа"
-#: contrib/auth/models.py:30 contrib/auth/models.py:65
+#: contrib/auth/models.py:30
+#: contrib/auth/models.py:65
msgid "groups"
msgstr "Группы"
#: contrib/auth/models.py:55
msgid "username"
-msgstr "Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
+msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
#: contrib/auth/models.py:56
msgid "first name"
-msgstr "имÑ"
+msgstr "ИмÑ"
#: contrib/auth/models.py:57
msgid "last name"
-msgstr "фамилиÑ"
+msgstr "ФамилиÑ"
#: contrib/auth/models.py:58
msgid "e-mail address"
-msgstr "e-mail адреÑ"
+msgstr "ÐÐ´Ñ€ÐµÑ Ñлектронной почты"
#: contrib/auth/models.py:59
msgid "password"
-msgstr "пароль"
+msgstr "Пароль"
#: contrib/auth/models.py:59
msgid "Use '[algo]$[salt]$[hexdigest]'"
-msgstr ""
+msgstr "ИÑпользуйте '[algo]$[salt]$[hexdigest]'"
#: contrib/auth/models.py:60
msgid "staff status"
-msgstr "ÑÑ‚Ð°Ñ‚ÑƒÑ Ð¿ÐµÑ€Ñонала"
+msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿ÐµÑ€Ñонала"
#: contrib/auth/models.py:60
msgid "Designates whether the user can log into this admin site."
@@ -1171,31 +1153,27 @@ msgstr "Отметьте, еÑли пользователь может входÐ
#: contrib/auth/models.py:61
msgid "active"
-msgstr "активен"
+msgstr "Ðктивный"
#: contrib/auth/models.py:62
msgid "superuser status"
-msgstr "ÑÑ‚Ð°Ñ‚ÑƒÑ Ð°Ð´Ð¼Ð¸Ð½Ð°"
+msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ ÑуперпользователÑ"
#: contrib/auth/models.py:63
msgid "last login"
-msgstr "поÑледний вход"
+msgstr "ПоÑледний вход"
#: contrib/auth/models.py:64
msgid "date joined"
-msgstr "дата региÑтрации"
+msgstr "Дата региÑтрации"
#: contrib/auth/models.py:66
-msgid ""
-"In addition to the permissions manually assigned, this user will also get "
-"all permissions granted to each group he/she is in."
-msgstr ""
-"К добавлению к перавам выбрнанным вуручную, Ñтот пользователь может получить "
-"вÑе права группы, к которой он принадлежит."
+msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."
+msgstr "Ð’ добавление к правам, приÑвоенным вручную, Ñтот пользователь получит вÑе права групп, к которым он принадлежит."
#: contrib/auth/models.py:67
msgid "user permissions"
-msgstr "Права пользователÑ"
+msgstr "права пользователÑ"
#: contrib/auth/models.py:70
msgid "user"
@@ -1226,10 +1204,8 @@ msgid "message"
msgstr "Сообщение"
#: contrib/auth/forms.py:30
-msgid ""
-"Your Web browser doesn't appear to have cookies enabled. Cookies are "
-"required for logging in."
-msgstr ""
+msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."
+msgstr "У вашего браузера не включены cookies. Cookies необходимы Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð°."
#: contrib/contenttypes/models.py:25
msgid "python model class name"
@@ -1237,59 +1213,59 @@ msgstr "Ð¸Ð¼Ñ ÐºÐ»Ð°ÑÑа python модулÑ"
#: contrib/contenttypes/models.py:28
msgid "content type"
-msgstr "тип наполнениÑ"
+msgstr "Тип Ñодержимого"
#: contrib/contenttypes/models.py:29
msgid "content types"
-msgstr "типы наполнениÑ"
+msgstr "Типы Ñодержимого"
#: contrib/sessions/models.py:35
msgid "session key"
-msgstr "ключ ÑеÑÑии"
+msgstr "Ключ ÑеÑÑии"
#: contrib/sessions/models.py:36
msgid "session data"
-msgstr "данные ÑеÑÑии"
+msgstr "Данные ÑеÑÑии"
#: contrib/sessions/models.py:37
msgid "expire date"
-msgstr "дата окончаниÑ"
+msgstr "Дата окончаниÑ"
#: contrib/sessions/models.py:41
msgid "session"
-msgstr "ÑеÑÑиÑ"
+msgstr "СеÑÑиÑ"
#: contrib/sessions/models.py:42
msgid "sessions"
-msgstr "ÑеÑÑии"
+msgstr "СеÑÑии"
#: contrib/sites/models.py:10
msgid "domain name"
-msgstr "домен"
+msgstr "Доменное имÑ"
#: contrib/sites/models.py:11
msgid "display name"
-msgstr "выводимое имÑ"
+msgstr "Выводимое имÑ"
#: contrib/sites/models.py:15
msgid "site"
-msgstr "Ñайт"
+msgstr "Сайт"
#: contrib/sites/models.py:16
msgid "sites"
-msgstr "Ñайты"
+msgstr "Сайты"
#: utils/translation.py:360
msgid "DATE_FORMAT"
-msgstr ""
+msgstr "d.m.Y"
#: utils/translation.py:361
msgid "DATETIME_FORMAT"
-msgstr ""
+msgstr "d.m.Y H:i"
#: utils/translation.py:362
msgid "TIME_FORMAT"
-msgstr ""
+msgstr "H:i"
#: utils/dates.py:6
msgid "Monday"
@@ -1327,23 +1303,28 @@ msgstr "Январь"
msgid "February"
msgstr "Февраль"
-#: utils/dates.py:14 utils/dates.py:27
+#: utils/dates.py:14
+#: utils/dates.py:27
msgid "March"
msgstr "Март"
-#: utils/dates.py:14 utils/dates.py:27
+#: utils/dates.py:14
+#: utils/dates.py:27
msgid "April"
msgstr "Ðпрель"
-#: utils/dates.py:14 utils/dates.py:27
+#: utils/dates.py:14
+#: utils/dates.py:27
msgid "May"
msgstr "Май"
-#: utils/dates.py:14 utils/dates.py:27
+#: utils/dates.py:14
+#: utils/dates.py:27
msgid "June"
msgstr "Июнь"
-#: utils/dates.py:15 utils/dates.py:27
+#: utils/dates.py:15
+#: utils/dates.py:27
msgid "July"
msgstr "Июль"
@@ -1357,7 +1338,7 @@ msgstr "СентÑбрь"
#: utils/dates.py:15
msgid "October"
-msgstr "ОÑÑ‚Ñбрь"
+msgstr "ОктÑбрь"
#: utils/dates.py:15
msgid "November"
@@ -1417,143 +1398,149 @@ msgstr "дек"
#: utils/dates.py:27
msgid "Jan."
-msgstr "Янв."
+msgstr "Ñнв."
#: utils/dates.py:27
msgid "Feb."
-msgstr "Фев."
+msgstr "фев."
#: utils/dates.py:28
msgid "Aug."
-msgstr "Ðвг."
+msgstr "авг."
#: utils/dates.py:28
msgid "Sept."
-msgstr "Сен."
+msgstr "Ñен."
#: utils/dates.py:28
msgid "Oct."
-msgstr "Окт."
+msgstr "окт."
#: utils/dates.py:28
msgid "Nov."
-msgstr "ÐоÑб."
+msgstr "ноÑб."
#: utils/dates.py:28
msgid "Dec."
-msgstr "Дек."
+msgstr "дек."
#: utils/timesince.py:12
msgid "year"
msgid_plural "years"
msgstr[0] "год"
-msgstr[1] "лет"
+msgstr[1] "года"
+msgstr[2] "лет"
#: utils/timesince.py:13
msgid "month"
msgid_plural "months"
msgstr[0] "меÑÑц"
-msgstr[1] "меÑÑцев"
+msgstr[1] "меÑÑца"
+msgstr[2] "меÑÑцев"
#: utils/timesince.py:14
msgid "week"
msgid_plural "weeks"
msgstr[0] "неделÑ"
-msgstr[1] "недель"
+msgstr[1] "недели"
+msgstr[2] "недель"
#: utils/timesince.py:15
msgid "day"
msgid_plural "days"
msgstr[0] "день"
-msgstr[1] "дней"
+msgstr[1] "днÑ"
+msgstr[2] "дней"
#: utils/timesince.py:16
msgid "hour"
msgid_plural "hours"
msgstr[0] "чаÑ"
-msgstr[1] "чаÑов"
+msgstr[1] "чаÑа"
+msgstr[2] "чаÑов"
#: utils/timesince.py:17
msgid "minute"
msgid_plural "minutes"
msgstr[0] "минута"
-msgstr[1] "минут"
+msgstr[1] "минуты"
+msgstr[2] "минут"
#: conf/global_settings.py:37
msgid "Bengali"
-msgstr ""
+msgstr "БенгальÑкий"
#: conf/global_settings.py:38
msgid "Czech"
-msgstr ""
+msgstr "ЧешÑкий"
#: conf/global_settings.py:39
msgid "Welsh"
-msgstr ""
+msgstr "УÑльÑкий"
#: conf/global_settings.py:40
msgid "Danish"
-msgstr ""
+msgstr "ДатÑкий"
#: conf/global_settings.py:41
msgid "German"
-msgstr ""
+msgstr "Ðемецкий"
#: conf/global_settings.py:42
msgid "Greek"
-msgstr ""
+msgstr "ГречеÑкий"
#: conf/global_settings.py:43
msgid "English"
-msgstr ""
+msgstr "ÐнглийÑкий"
#: conf/global_settings.py:44
msgid "Spanish"
-msgstr ""
+msgstr "ИÑпанÑкий"
#: conf/global_settings.py:45
msgid "French"
-msgstr ""
+msgstr "ФранцузÑкий"
#: conf/global_settings.py:46
msgid "Galician"
-msgstr ""
+msgstr "ГалльÑкий"
#: conf/global_settings.py:47
msgid "Hungarian"
-msgstr ""
+msgstr "ВенгерÑкий"
#: conf/global_settings.py:48
msgid "Hebrew"
-msgstr ""
+msgstr "Иврит"
#: conf/global_settings.py:49
msgid "Icelandic"
-msgstr ""
+msgstr "ИÑландÑкий"
#: conf/global_settings.py:50
msgid "Italian"
-msgstr ""
+msgstr "ИтальÑнÑкий"
#: conf/global_settings.py:51
msgid "Japanese"
-msgstr ""
+msgstr "ЯпонÑкий"
#: conf/global_settings.py:52
msgid "Dutch"
-msgstr ""
+msgstr "ГолландÑкий"
#: conf/global_settings.py:53
msgid "Norwegian"
-msgstr ""
+msgstr "ÐорвежÑкий"
#: conf/global_settings.py:54
msgid "Brazilian"
-msgstr ""
+msgstr "БразильÑкий"
#: conf/global_settings.py:55
msgid "Romanian"
-msgstr ""
+msgstr "РумынÑкий"
#: conf/global_settings.py:56
msgid "Russian"
@@ -1561,106 +1548,100 @@ msgstr "РуÑÑкий"
#: conf/global_settings.py:57
msgid "Slovak"
-msgstr ""
+msgstr "Словацкий"
#: conf/global_settings.py:58
msgid "Slovenian"
-msgstr ""
+msgstr "СловенÑкий"
#: conf/global_settings.py:59
msgid "Serbian"
-msgstr ""
+msgstr "СербÑкий"
#: conf/global_settings.py:60
msgid "Swedish"
-msgstr ""
+msgstr "ШведÑкий"
#: conf/global_settings.py:61
msgid "Ukrainian"
-msgstr ""
+msgstr "УкраинÑкий"
#: conf/global_settings.py:62
msgid "Simplified Chinese"
-msgstr ""
+msgstr "Упрощенный китайÑкий"
#: conf/global_settings.py:63
msgid "Traditional Chinese"
-msgstr ""
+msgstr "Традиционный китайÑкий"
#: core/validators.py:60
msgid "This value must contain only letters, numbers and underscores."
-msgstr "Значение может Ñодержать только буквы, цифры и подчеркиваниÑ."
+msgstr "Значение должно ÑоÑтоÑть только из букв, цифр и знаков подчеркиваниÑ."
#: core/validators.py:64
-msgid ""
-"This value must contain only letters, numbers, underscores, dashes or "
-"slashes."
-msgstr "Значение может Ñодержать только буквы, цифры, подчеркиваниÑ, дифиÑÑ‹ или "
-"тере."
+msgid "This value must contain only letters, numbers, underscores, dashes or slashes."
+msgstr "Значение должно ÑоÑтоÑть только из букв, цифр, знаков подчеркиваниÑ, тире или наклонной черты вправо."
#: core/validators.py:72
msgid "Uppercase letters are not allowed here."
-msgstr "Заглавные буквы не разрешены"
+msgstr "Заглавные буквы недопуÑтимы."
#: core/validators.py:76
msgid "Lowercase letters are not allowed here."
-msgstr "Строчные буквы не разрешены"
+msgstr "Строчные буквы здеÑÑŒ недопуÑтимы."
#: core/validators.py:83
msgid "Enter only digits separated by commas."
-msgstr "Вводите только цифры разделённые запÑтыми"
+msgstr "Введите цифры, разделённые запÑтыми."
#: core/validators.py:95
msgid "Enter valid e-mail addresses separated by commas."
-msgstr "Вводите реальные e-mail адреÑа разделённые запÑтыми"
+msgstr "Введите правильные адреÑа Ñлектронной почты, разделённые запÑтыми."
#: core/validators.py:99
msgid "Please enter a valid IP address."
-msgstr "ПожалуйÑта, вводите реальный IP адреÑ"
+msgstr "ПожалуйÑта, введите правильный IP-адреÑ."
#: core/validators.py:103
msgid "Empty values are not allowed here."
-msgstr "ПуÑтое значение не разрешено"
+msgstr "ПуÑтое значение здеÑÑŒ недопуÑтимо."
#: core/validators.py:107
msgid "Non-numeric characters aren't allowed here."
-msgstr "Ðе цифровые Ñимволы не рназрешены"
+msgstr "Ðецифровые Ñимволы здеÑÑŒ недопуÑтимы."
#: core/validators.py:111
msgid "This value can't be comprised solely of digits."
-msgstr ""
+msgstr "Это значение не может быть ÑоÑтавлено только из цифр."
#: core/validators.py:116
msgid "Enter a whole number."
-msgstr "Введите номер"
+msgstr "Введите целое чиÑло."
#: core/validators.py:120
msgid "Only alphabetical characters are allowed here."
-msgstr "Только буквы можно иÑпользовать"
+msgstr "ЗдеÑÑŒ разрешены только алфавитные Ñимволы."
#: core/validators.py:124
msgid "Enter a valid date in YYYY-MM-DD format."
-msgstr "Вводите реальную дату в формате YYYY-MM-DD."
+msgstr "Вводите правильную дату в формате YYYY-MM-DD."
#: core/validators.py:128
msgid "Enter a valid time in HH:MM format."
-msgstr "Вводите реальное Ð²Ñ€ÐµÐ¼Ñ Ð² формате HH:MM."
+msgstr "Введите правильное Ð²Ñ€ÐµÐ¼Ñ Ð² формате HH:MM."
-#: core/validators.py:132 db/models/fields/__init__.py:468
+#: core/validators.py:132
+#: db/models/fields/__init__.py:468
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
-msgstr "Вводите реальные дата/Ð²Ñ€ÐµÐ¼Ñ Ð² формате YYYY-MM-DD HH:MM."
+msgstr "Введите правильные дату/Ð²Ñ€ÐµÐ¼Ñ Ð² формате YYYY-MM-DD HH:MM."
#: core/validators.py:136
msgid "Enter a valid e-mail address."
-msgstr "Укажите реальный e-mail адреÑ."
+msgstr "Укажите правильный Ð°Ð´Ñ€ÐµÑ Ñлектронной почты."
#: core/validators.py:148
-msgid ""
-"Upload a valid image. The file you uploaded was either not an image or a "
-"corrupted image."
-msgstr ""
-"Загрузите реальное изображение. Файл, который вы загружали, не был "
-"изображением или был поврежден."
+msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image."
+msgstr "Загрузите реальное изображение. Файл, который вы загрузили, не ÑвлÑетÑÑ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸ÐµÐ¼ или был поврежден."
#: core/validators.py:155
#, python-format
@@ -1670,7 +1651,7 @@ msgstr "URL %s не указывает на реальное изображенÐ
#: core/validators.py:159
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
-msgstr "Телефонный номер должен быть в формате XXX-XXX-XXXX. \"%s\" не верен."
+msgstr "Телефонные номера должен быть в формате XXX-XXX-XXXX. \"%s\" неверен."
#: core/validators.py:167
#, python-format
@@ -1679,7 +1660,7 @@ msgstr "URL %s не указывает на реальное видео QuickTim
#: core/validators.py:171
msgid "A valid URL is required."
-msgstr "Реальный URL обÑзателен."
+msgstr "Правильный URL обÑзателен."
#: core/validators.py:185
#, python-format
@@ -1687,7 +1668,7 @@ msgid ""
"Valid HTML is required. Specific errors are:\n"
"%s"
msgstr ""
-"Реальный HTML обÑзателен. Специфичные ошибки:\n"
+"Правильный HTML обÑзателен. Специфичные ошибки:\n"
"%s"
#: core/validators.py:192
@@ -1700,14 +1681,15 @@ msgstr "Ðеверный формат XML: %s"
msgid "Invalid URL: %s"
msgstr "Ðеверный URL: %s"
-#: core/validators.py:206 core/validators.py:208
+#: core/validators.py:206
+#: core/validators.py:208
#, python-format
msgid "The URL %s is a broken link."
-msgstr "URL %s ÑÐ»Ð¾Ð¼Ð°Ð½Ð½Ð°Ñ ÑÑылка."
+msgstr "URL %s - ÑÐ»Ð¾Ð¼Ð°Ð½Ð½Ð°Ñ ÑÑылка."
#: core/validators.py:214
msgid "Enter a valid U.S. state abbreviation."
-msgstr "Вводите реальную абревиатуру штатов СШÐ."
+msgstr "Введите правильную аббревиатуру штата СШÐ."
#: core/validators.py:229
#, python-format
@@ -1715,6 +1697,7 @@ msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Следите за Ñвоими Ñловами! Слово %s здеÑÑŒ запрещено."
msgstr[1] "Следите за Ñвоими Ñловами! Слова %s здеÑÑŒ запрещены."
+msgstr[2] "Следите за Ñвоими Ñловами! Слова %s здеÑÑŒ запрещены."
#: core/validators.py:236
#, python-format
@@ -1725,70 +1708,63 @@ msgstr "Это поле должно Ñовпадать Ñ Ð¿Ð¾Ð»ÐµÐ¼ '%s'."
msgid "Please enter something for at least one field."
msgstr "ПожалуйÑта, заполните Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одно поле."
-#: core/validators.py:264 core/validators.py:275
+#: core/validators.py:264
+#: core/validators.py:275
msgid "Please enter both fields or leave them both empty."
-msgstr "ПожалуйÑта, заполните оба Ð¿Ð¾Ð»Ñ Ð»Ð¸Ð±Ð¾ оÑтавьте их пуÑтыми."
+msgstr "ПожалуйÑта, заполните оба Ð¿Ð¾Ð»Ñ Ð¸Ð»Ð¸ оÑтавьте их оба пуÑтыми."
#: core/validators.py:282
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
-msgstr "Это поле должно быть заполнено еÑли %(field)s равно %(value)s"
+msgstr "Это поле должно быть заполнено, еÑли %(field)s равно %(value)s"
#: core/validators.py:294
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
-msgstr "Это поле должно быть заполнено еÑли %(field)s не равно %(value)s"
+msgstr "Это поле должно быть заполнено, еÑли %(field)s не равно %(value)s"
#: core/validators.py:313
msgid "Duplicate values are not allowed."
-msgstr "Двойные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ñ€ÐµÑ‰ÐµÐ½Ð½Ñ‹."
+msgstr "Двойные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ñ€ÐµÑ‰ÐµÐ½Ñ‹."
#: core/validators.py:336
#, python-format
msgid "This value must be a power of %s."
-msgstr ""
+msgstr "Это значение должно быть Ñтепенью %s."
#: core/validators.py:347
msgid "Please enter a valid decimal number."
-msgstr "ПожалуйÑта, вводите корректное деÑÑтичное чиÑло."
+msgstr "ПожалуйÑта, введите корректное деÑÑтичное чиÑло."
#: core/validators.py:349
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
-msgid_plural ""
-"Please enter a valid decimal number with at most %s total digits."
-msgstr[0] ""
-"ПожалуйÑта, вводите корректное деÑÑтичное чиÑло Ñ Ð¼Ð°ÐºÑимальным количеÑтвом "
-"знаков %s."
-msgstr[1] ""
-"ПожалуйÑта, вводите корректное деÑÑтичное чиÑло Ñ Ð¼Ð°ÐºÑимальным количеÑтвом "
-"знаков %s."
+msgid_plural "Please enter a valid decimal number with at most %s total digits."
+msgstr[0] "ПожалуйÑта, введите корректное деÑÑтичное чиÑло макÑимально Ñ %s знаком."
+msgstr[1] "ПожалуйÑта, введите корректное деÑÑтичное чиÑло макÑимально Ñ %s знаками."
+msgstr[2] "ПожалуйÑта, введите корректное деÑÑтичное чиÑло макÑимально Ñ %s знаками."
#: core/validators.py:352
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
-msgid_plural ""
-"Please enter a valid decimal number with at most %s decimal places."
-msgstr[0] ""
-"ПожалуйÑта, вводите корректное деÑÑтичное чиÑло Ñ Ð¼Ð°ÐºÑимальным количеÑтвом "
-"знаков поÑле запÑтой %s."
-msgstr[1] ""
-"ПожалуйÑта, вводите корректное деÑÑтичное чиÑло Ñ Ð¼Ð°ÐºÑимальным количеÑтвом "
-"знаков поÑле запÑтой %s."
+msgid_plural "Please enter a valid decimal number with at most %s decimal places."
+msgstr[0] "ПожалуйÑта, введите корректное деÑÑтичное чиÑло макÑимально Ñ %s знаком поÑле запÑтой."
+msgstr[1] "ПожалуйÑта, введите корректное деÑÑтичное чиÑло макÑимально Ñ %s знаками поÑле запÑтой."
+msgstr[2] "ПожалуйÑта, введите корректное деÑÑтичное чиÑло макÑимально Ñ %s знаками поÑле запÑтой."
#: core/validators.py:362
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
-msgstr "УбедитеÑÑŒ, что загруженный файл по крайней мере не меньше %s байт."
+msgstr "УбедитеÑÑŒ, что загруженный файл не меньше %s байт."
#: core/validators.py:363
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
-msgstr "УбедитеÑÑŒ, что загруженный файл больше чем %s байт."
+msgstr "УбедитеÑÑŒ, что загруженный файл не больше %s байт."
#: core/validators.py:376
msgid "The format for this field is wrong."
-msgstr "Формат Ñтого Ð¿Ð¾Ð»Ñ Ð½ÐµÐ²ÐµÑ€ÐµÐ½"
+msgstr "Формат Ñтого Ð¿Ð¾Ð»Ñ Ð½ÐµÐ²ÐµÑ€ÐµÐ½."
#: core/validators.py:391
msgid "This field is invalid."
@@ -1797,85 +1773,72 @@ msgstr "Это поле неверно."
#: core/validators.py:426
#, python-format
msgid "Could not retrieve anything from %s."
-msgstr "Ðевозможно получить что-либо Ñ %s."
+msgstr "Ðевозможно получить ничего Ñ %s."
#: core/validators.py:429
#, python-format
-msgid ""
-"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
-msgstr "URL %(url) вернул неверный заголовок Content-Type '%(contenttype)'."
+msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
+msgstr "URL %(url)s вернул неверный заголовок Content-Type '%(contenttype)s'."
#: core/validators.py:462
#, python-format
-msgid ""
-"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
-"\"%(start)s\".)"
-msgstr ""
+msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)"
+msgstr "ПожалуйÑта, закройте незакрытый Ñ‚Ñг %(tag)s на Ñтроке %(line)s. (Строка начинаетÑÑ Ñ \"%(start)s\".)"
#: core/validators.py:466
#, python-format
-msgid ""
-"Some text starting on line %(line)s is not allowed in that context. (Line "
-"starts with \"%(start)s\".)"
-msgstr ""
+msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)"
+msgstr "Что-то из текÑта, начинающегоÑÑ Ð½Ð° Ñтроке %(line)s, недопуÑтимо в том контекÑте. (Строка начинаетÑÑ Ñ \"%(start)s\".)"
#: core/validators.py:471
#, python-format
-msgid ""
-"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
-"(start)s\".)"
-msgstr ""
+msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)"
+msgstr "\"%(attr)s\" на Ñтроке %(line)s - неправильный атрибут. (Строка начинаетÑÑ Ñ \"%(start)s\".)"
#: core/validators.py:476
#, python-format
-msgid ""
-"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
-"(start)s\".)"
-msgstr ""
+msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)"
+msgstr "\"<%(tag)s>\" на Ñтроке %(line)s - неправильный тег. (Строка начинаетÑÑ Ñ \"%(start)s\".)"
#: core/validators.py:480
#, python-format
-msgid ""
-"A tag on line %(line)s is missing one or more required attributes. (Line "
-"starts with \"%(start)s\".)"
-msgstr ""
+msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)"
+msgstr "Ð’ теге на Ñтроке %(line)s не хватает одного или более обÑзательных атрибутов. (Строка начинаетÑÑ Ñ \"%(start)s\".)"
#: core/validators.py:485
#, python-format
-msgid ""
-"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
-"starts with \"%(start)s\".)"
-msgstr ""
+msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)"
+msgstr "Ðтрибут \"%(attr)s\" на Ñтроке %(line)s имеет недопуÑтимое значение. (Строка начинаетÑÑ Ñ \"%(start)s\".)"
#: db/models/manipulators.py:302
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
-msgstr ""
+msgstr "%(object)s Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ %(type)s уже ÑущеÑтвует Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ %(field)s."
#: db/models/fields/__init__.py:40
#, python-format
msgid "%(optname)s with this %(fieldname)s already exists."
-msgstr ""
+msgstr "%(optname)s Ñ %(fieldname)s уже ÑущеÑтвует."
-#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
-#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
+#: db/models/fields/__init__.py:114
+#: db/models/fields/__init__.py:265
+#: db/models/fields/__init__.py:542
+#: db/models/fields/__init__.py:553
#: forms/__init__.py:346
msgid "This field is required."
msgstr "ОбÑзательное поле."
#: db/models/fields/__init__.py:337
msgid "This value must be an integer."
-msgstr ""
+msgstr "Это значение должно быть целым чиÑлом."
#: db/models/fields/__init__.py:369
-#, fuzzy
msgid "This value must be either True or False."
-msgstr "ЛогичеÑкое (True или False)"
+msgstr "Значение должно либо True, либо False."
#: db/models/fields/__init__.py:385
-#, fuzzy
msgid "This field cannot be null."
-msgstr "Это поле неверно."
+msgstr "Это поле не может быть нулевым."
#: db/models/fields/__init__.py:562
msgid "Enter a valid filename."
@@ -1884,52 +1847,50 @@ msgstr "Укажите правильное Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°."
#: db/models/fields/related.py:43
#, python-format
msgid "Please enter a valid %s."
-msgstr ""
+msgstr "ПожалуйÑта, введите правильный %s."
#: db/models/fields/related.py:579
-#, fuzzy
msgid "Separate multiple IDs with commas."
-msgstr "ÐеÑколько значений ID разделÑйте запÑтыми."
+msgstr "ÐеÑколько значений ID разделите запÑтыми."
#: db/models/fields/related.py:581
-#, fuzzy
-msgid ""
-"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
-msgstr ""
-" Удерживайте \"Control\", или \"Command\" на Макинтош, Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° больше чем "
-"одного."
+msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
+msgstr "Удерживайте \"Control\" (или \"Command\" на Mac) Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° неÑкольких."
#: db/models/fields/related.py:625
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
-msgid_plural ""
-"Please enter valid %(self)s IDs. The values %(value)r are invalid."
-msgstr[0] ""
-msgstr[1] ""
+msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid."
+msgstr[0] "ПожалуйÑта, введите корректный ID Ð´Ð»Ñ %(self)s. Значение %(value)r недопуÑтимо."
+msgstr[1] "ПожалуйÑта, введите корректные ID Ð´Ð»Ñ %(self)s. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ %(value)r недопуÑтимы."
+msgstr[2] "ПожалуйÑта, введите корректные ID Ð´Ð»Ñ %(self)s. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ %(value)r недопуÑтимы."
#: forms/__init__.py:380
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "УбедитеÑÑŒ, что длина вашего текÑта меньше %s Ñимвола."
+msgstr[1] "УбедитеÑÑŒ, что длина вашего текÑта меньше %s Ñимволов."
+msgstr[2] "УбедитеÑÑŒ, что длина вашего текÑта меньше %s Ñимволов."
#: forms/__init__.py:385
msgid "Line breaks are not allowed here."
-msgstr "ПереноÑÑ‹ Ñтрок не допуÑкаютÑÑ Ð·Ð´ÐµÑÑŒ."
+msgstr "ПереноÑÑ‹ Ñтрок здеÑÑŒ не допуÑкаютÑÑ."
-#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
+#: forms/__init__.py:480
+#: forms/__init__.py:551
+#: forms/__init__.py:589
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
-msgstr ""
+msgstr "Выберите корректный вариант; '%(data)s' нет в %(choices)s."
#: forms/__init__.py:645
msgid "The submitted file is empty."
-msgstr "Указанный файл - пуÑÑ‚."
+msgstr "Указанный файл пуÑÑ‚."
#: forms/__init__.py:699
msgid "Enter a whole number between -32,768 and 32,767."
-msgstr ""
+msgstr "Введите целое чиÑло в диапазоне от -32768 до 32767."
#: forms/__init__.py:708
msgid "Enter a positive number."
@@ -1943,30 +1904,3 @@ msgstr "Введите целое чиÑло в диапазоне от 0 до 3
msgid "yes,no,maybe"
msgstr "да,нет,может быть"
-#~ msgid "Comment"
-#~ msgstr "Комментарий"
-
-#~ msgid "Comments"
-#~ msgstr "Комментарии"
-
-#~ msgid "label"
-#~ msgstr "метка"
-
-#~ msgid "package"
-#~ msgstr "пакет"
-
-#~ msgid "packages"
-#~ msgstr "пакеты"
-
-#~ msgid "String (up to 50)"
-#~ msgstr "Строка (до 50 Ñимволов)"
-
-#~ msgid ""
-#~ "Example: 'flatfiles/contact_page'. If this isn't provided, the system "
-#~ "will use 'flatfiles/default'."
-#~ msgstr ""
-#~ "Пример: 'flatfiles/contact_page'. ЕÑли не предуÑмотрена, ÑиÑтема будет "
-#~ "иÑпользовать 'flatfiles/default'."
-
-#~ msgid "Server error <em>(500)</em>"
-#~ msgstr "Ошибка Ñервера <em>(500)</em>"
diff --git a/django/conf/locale/sl/LC_MESSAGES/django.mo b/django/conf/locale/sl/LC_MESSAGES/django.mo
index a7d6152411..12253610c4 100644
--- a/django/conf/locale/sl/LC_MESSAGES/django.mo
+++ b/django/conf/locale/sl/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/sl/LC_MESSAGES/django.po b/django/conf/locale/sl/LC_MESSAGES/django.po
index 1d9e2f4028..5a9b6d6b46 100644
--- a/django/conf/locale/sl/LC_MESSAGES/django.po
+++ b/django/conf/locale/sl/LC_MESSAGES/django.po
@@ -1,21 +1,25 @@
-# SOME DESCRIPTIVE TITLE.
+# translation of django.po to Slovenian
+# Igor Kolar <ike@email.si), 2006.
+# Nena Kojadin <nena@kiberpipa.org), 2006.
+# Jure Cuhalev <gandalf@owca.info>, 2006.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-# Igor Kolar <ike@email.si), 2006.
-# Nena Kojadin <nena@kiberpipa.org), 2006
msgid ""
msgstr ""
-"Project-Id-Version: Django Slovenian 0.92+svn translation\n"
+"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:13+0200\n"
-"PO-Revision-Date: 2006-03-19 17:30+0100\n"
+"PO-Revision-Date: 2006-07-29 11:52+0100\n"
"Last-Translator: Jure ÄŒuhalev <gandalf@owca.info>\n"
-"Language-Team: Slovenian <sl@li.org>\n"
+"Language-Team: Slovenian <lugos-slo@lugos.si>\n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.2\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
-#: contrib/comments/models.py:67 contrib/comments/models.py:166
+#: contrib/comments/models.py:67
+#: contrib/comments/models.py:166
msgid "object ID"
msgstr "ID objekta"
@@ -23,7 +27,8 @@ msgstr "ID objekta"
msgid "headline"
msgstr "naslov"
-#: contrib/comments/models.py:69 contrib/comments/models.py:90
+#: contrib/comments/models.py:69
+#: contrib/comments/models.py:90
#: contrib/comments/models.py:167
msgid "comment"
msgstr "komentar"
@@ -64,15 +69,18 @@ msgstr "rating #8"
msgid "is valid rating"
msgstr "je veljavni rating"
-#: contrib/comments/models.py:83 contrib/comments/models.py:169
+#: contrib/comments/models.py:83
+#: contrib/comments/models.py:169
msgid "date/time submitted"
-msgstr "podatek datum/Äas poslan"
+msgstr "datum/Äas vnosa"
-#: contrib/comments/models.py:84 contrib/comments/models.py:170
+#: contrib/comments/models.py:84
+#: contrib/comments/models.py:170
msgid "is public"
msgstr "je javno"
-#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
+#: contrib/comments/models.py:85
+#: contrib/admin/views/doc.py:289
msgid "IP address"
msgstr "IP naslov"
@@ -81,21 +89,17 @@ msgid "is removed"
msgstr "je odstranjen/-a"
#: contrib/comments/models.py:86
-msgid ""
-"Check this box if the comment is inappropriate. A \"This comment has been "
-"removed\" message will be displayed instead."
-msgstr ""
-"Odkljukaj, Äe je komntar neprimeren. Namesto komentarja bo vidno obvestilo "
-"\"Ta komentar je bil odstranjen\"."
+msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead."
+msgstr "Odkljukaj, Äe je komntar neprimeren. Namesto komentarja bo vidno obvestilo \"Ta komentar je bil odstranjen\"."
#: contrib/comments/models.py:91
-#, fuzzy
msgid "comments"
-msgstr "komentar"
+msgstr "komentarji"
-#: contrib/comments/models.py:131 contrib/comments/models.py:207
+#: contrib/comments/models.py:131
+#: contrib/comments/models.py:207
msgid "Content object"
-msgstr "Objekt s vsebino"
+msgstr "Objekt z vsebino"
#: contrib/comments/models.py:159
#, python-format
@@ -125,14 +129,12 @@ msgid "approved by staff"
msgstr "potrjeno s strani osebja"
#: contrib/comments/models.py:176
-#, fuzzy
msgid "free comment"
-msgstr "Zastonj komentar"
+msgstr "anonimen komentar"
#: contrib/comments/models.py:177
-#, fuzzy
msgid "free comments"
-msgstr "Zastonj komentarji"
+msgstr "anonimni komentarji"
#: contrib/comments/models.py:233
msgid "score"
@@ -143,14 +145,12 @@ msgid "score date"
msgstr "datum ocene"
#: contrib/comments/models.py:237
-#, fuzzy
msgid "karma score"
-msgstr "Karma"
+msgstr "karma toÄke"
#: contrib/comments/models.py:238
-#, fuzzy
msgid "karma scores"
-msgstr "Skrivnosti karme"
+msgstr "karma toÄke"
#: contrib/comments/models.py:242
#, python-format
@@ -173,14 +173,12 @@ msgid "flag date"
msgstr "datum oznaÄitve (zastavice)"
#: contrib/comments/models.py:268
-#, fuzzy
msgid "user flag"
-msgstr "Uporabniška zastavica"
+msgstr "uporabnikova zastavica"
#: contrib/comments/models.py:269
-#, fuzzy
msgid "user flags"
-msgstr "Uporabniške zastavice"
+msgstr "uporabniške zastavice"
#: contrib/comments/models.py:273
#, python-format
@@ -192,14 +190,12 @@ msgid "deletion date"
msgstr "datum izbrisa"
#: contrib/comments/models.py:280
-#, fuzzy
msgid "moderator deletion"
-msgstr "Izbris s strani moderatorja"
+msgstr "izbris s strani moderatorja"
#: contrib/comments/models.py:281
-#, fuzzy
msgid "moderator deletions"
-msgstr "Izbrisi s strani moderatorja"
+msgstr "izbrisi s strani moderatorja"
#: contrib/comments/models.py:285
#, python-format
@@ -219,30 +215,33 @@ msgid "No voting for yourself"
msgstr "Ni mogoÄe glasovati zase"
#: contrib/comments/views/comments.py:28
-msgid ""
-"This rating is required because you've entered at least one other rating."
+msgid "This rating is required because you've entered at least one other rating."
msgstr "Moraš podati tole oceno, ker si podal vsaj še eno drugo oceno."
#: contrib/comments/views/comments.py:112
#, python-format
msgid ""
-"This comment was posted by a user who has posted fewer than %(count)s "
-"comment:\n"
+"This comment was posted by a user who has posted fewer than %(count)s comment:\n"
"\n"
"%(text)s"
msgid_plural ""
-"This comment was posted by a user who has posted fewer than %(count)s "
-"comments:\n"
+"This comment was posted by a user who has posted fewer than %(count)s comments:\n"
"\n"
"%(text)s"
msgstr[0] ""
-"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s "
-"komentarjev Komentar:\n"
+"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s komentarjev:\n"
"\n"
"%(text)s"
msgstr[1] ""
-"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s "
-"komentarjev Komentar:\n"
+"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s komentar:\n"
+"\n"
+"%(text)s"
+msgstr[2] ""
+"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s komentarja:\n"
+"\n"
+"%(text)s"
+msgstr[3] ""
+"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s komentarje:\n"
"\n"
"%(text)s"
@@ -260,12 +259,12 @@ msgstr ""
#: contrib/comments/views/comments.py:189
#: contrib/comments/views/comments.py:280
msgid "Only POSTs are allowed"
-msgstr "Dovoljena je le metoda HTTP POST"
+msgstr "Dovoljena je le metoda POST"
#: contrib/comments/views/comments.py:193
#: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted"
-msgstr "Eden ali veÄ obveznih polj ni vpisanih"
+msgstr "Eno ali veÄ obveznih polj ni vpisanih"
#: contrib/comments/views/comments.py:197
#: contrib/comments/views/comments.py:286
@@ -274,17 +273,13 @@ msgstr "Nekdo se je poigraval z obrazcem za komentarje (varnostna kršitev)"
#: contrib/comments/views/comments.py:207
#: contrib/comments/views/comments.py:292
-msgid ""
-"The comment form had an invalid 'target' parameter -- the object ID was "
-"invalid"
-msgstr ""
-"Obrazec s komentarji ima neveljavni parameter 'target' -- ID objekta je "
-"neveljaven."
+msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid"
+msgstr "Obrazec s komentarji ima neveljavni parameter 'target' -- ID objekta je neveljaven."
#: contrib/comments/views/comments.py:257
#: contrib/comments/views/comments.py:321
msgid "The comment form didn't provide either 'preview' or 'post'"
-msgstr "Obrazec s komentarji ne zahteva niti 'preview' niti 'post' akcije."
+msgstr "Obrazec s komentarji ni podal niti 'preview' niti 'post' akcije."
#: contrib/comments/templates/comments/form.html:6
#: contrib/comments/templates/comments/form.html:8
@@ -363,7 +358,8 @@ msgstr ""
"<h3>Avtor: %s</h3>\n"
"<ul>\n"
-#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
+#: contrib/admin/filterspecs.py:70
+#: contrib/admin/filterspecs.py:88
#: contrib/admin/filterspecs.py:143
msgid "All"
msgstr "Vse"
@@ -390,7 +386,7 @@ msgstr "Letos"
#: contrib/admin/filterspecs.py:143
msgid "Yes"
-msgstr "Ja"
+msgstr "Da"
#: contrib/admin/filterspecs.py:143
msgid "No"
@@ -432,46 +428,33 @@ msgstr "vnosi v dnevniku"
msgid "All dates"
msgstr "Vsi datumi"
-#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
+#: contrib/admin/views/decorators.py:9
+#: contrib/auth/forms.py:36
#: contrib/auth/forms.py:41
-msgid ""
-"Please enter a correct username and password. Note that both fields are case-"
-"sensitive."
-msgstr ""
-"Prosimo, vnesite veljavno uporabniško ime in geslo. Opomba: obe polji sta "
-"obÄutljivi na velikost Ärk"
+msgid "Please enter a correct username and password. Note that both fields are case-sensitive."
+msgstr "Prosimo, vnesite veljavno uporabniÅ¡ko ime in geslo. Opomba: obe polji sta obÄutljivi na velikost Ärk"
#: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25
msgid "Log in"
-msgstr "Prijate se"
+msgstr "Prijavite se"
#: contrib/admin/views/decorators.py:61
-msgid ""
-"Please log in again, because your session has expired. Don't worry: Your "
-"submission has been saved."
-msgstr ""
-"Vaša seja je pretekla; prosimo, prijavite se znova. Opomba: Vse vaše objave "
-"so varno shranjene."
+msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved."
+msgstr "Vaša seja je pretekla; prosimo, prijavite se znova. Ne skrbite, vaše objave so varno shranjene."
#: contrib/admin/views/decorators.py:68
-msgid ""
-"Looks like your browser isn't configured to accept cookies. Please enable "
-"cookies, reload this page, and try again."
-msgstr ""
-"Izgleda, da vaÅ¡ brskalnik nima podpore za piÅ¡kotke. Prosimo, vkljuÄite "
-"piškotke, znova naložite to stran in poskusite še enkrat."
+msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again."
+msgstr "Izgleda, da vaÅ¡ brskalnik nima podpore za piÅ¡kotke. Prosimo, vkljuÄite piÅ¡kotke, znova naložite to stran in poskusite Å¡e enkrat."
#: contrib/admin/views/decorators.py:82
msgid "Usernames cannot contain the '@' character."
-msgstr "Uporabniška imena ne smejo vsebovati znaka '@'"
+msgstr "Uporabniška imena ne smejo vsebovati znaka '@'."
#: contrib/admin/views/decorators.py:84
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
-msgstr ""
-"Vaš e-mail naslov ne morete uporabljati kot uporabniško ime. Namesto tega "
-"uporabite '%s'"
+msgstr "Vaš e-mail naslov ne morete uporabljati kot uporabniško ime. Namesto tega uporabite '%s'."
#: contrib/admin/views/main.py:226
msgid "Site administration"
@@ -482,11 +465,13 @@ msgstr "Administracija strani"
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "%(name)s \"%(obj)s\" je bil uspešno dodan."
-#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
+#: contrib/admin/views/main.py:264
+#: contrib/admin/views/main.py:348
msgid "You may edit it again below."
msgstr "Vsebino lahko znova uredite spodaj."
-#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
+#: contrib/admin/views/main.py:272
+#: contrib/admin/views/main.py:357
#, python-format
msgid "You may add another %s below."
msgstr "Spodaj lahko dodate še en %s."
@@ -501,7 +486,8 @@ msgstr "Dodaj %s"
msgid "Added %s."
msgstr "Dodal %s."
-#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
+#: contrib/admin/views/main.py:336
+#: contrib/admin/views/main.py:338
#: contrib/admin/views/main.py:340
msgid "and"
msgstr "in"
@@ -509,7 +495,7 @@ msgstr "in"
#: contrib/admin/views/main.py:338
#, python-format
msgid "Changed %s."
-msgstr "Spremenil %s"
+msgstr "Spremenil %s."
#: contrib/admin/views/main.py:340
#, python-format
@@ -527,10 +513,8 @@ msgstr "%(name)s \"%(obj)s\" je bilo uspešno spremenjeno."
#: contrib/admin/views/main.py:354
#, python-format
-msgid ""
-"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
-msgstr ""
-"%(name)s \"%(obj)s\" je bilo uspešno dodano. Znova ga lahko urejate spodaj."
+msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
+msgstr "%(name)s \"%(obj)s\" je bilo uspešno dodano. Znova ga lahko urejate spodaj."
#: contrib/admin/views/main.py:392
#, python-format
@@ -564,24 +548,28 @@ msgstr "Zgodovina sprememb: %s"
#: contrib/admin/views/main.py:565
#, python-format
msgid "Select %s"
-msgstr "Izberi %s"
+msgstr "Izberite %s"
#: contrib/admin/views/main.py:565
#, python-format
msgid "Select %s to change"
-msgstr "Izberi %s, ki ga želite spremeniti"
+msgstr "Izberite %s, ki ga želite spremeniti"
-#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
-#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
-#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
+#: contrib/admin/views/doc.py:277
+#: contrib/admin/views/doc.py:286
+#: contrib/admin/views/doc.py:288
+#: contrib/admin/views/doc.py:294
+#: contrib/admin/views/doc.py:295
+#: contrib/admin/views/doc.py:297
msgid "Integer"
-msgstr "Integer (število)"
+msgstr "Å tevilo (integer)"
#: contrib/admin/views/doc.py:278
msgid "Boolean (Either True or False)"
msgstr "Boolean (ali True ali False)"
-#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
+#: contrib/admin/views/doc.py:279
+#: contrib/admin/views/doc.py:296
#, python-format
msgid "String (up to %(maxlength)s)"
msgstr "Niz (vse do %(maxlength)s)"
@@ -602,7 +590,8 @@ msgstr "Datum (s Äasom)"
msgid "E-mail address"
msgstr "E-naslov"
-#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
+#: contrib/admin/views/doc.py:284
+#: contrib/admin/views/doc.py:287
msgid "File path"
msgstr "Pot do datoteke"
@@ -616,7 +605,7 @@ msgstr "Boolean (ali True ali False ali None)"
#: contrib/admin/views/doc.py:292
msgid "Relation to parent model"
-msgstr "Razmerje z starševskim modelom"
+msgstr "Razmerje s starševskim modelom"
#: contrib/admin/views/doc.py:293
msgid "Phone number"
@@ -630,7 +619,8 @@ msgstr "Besedilo"
msgid "Time"
msgstr "ÄŒas"
-#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
+#: contrib/admin/views/doc.py:300
+#: contrib/flatpages/models.py:7
msgid "URL"
msgstr "URL (spletni naslov)"
@@ -707,15 +697,11 @@ msgstr "Dejanje"
#: contrib/admin/templates/admin/object_history.html:26
msgid "DATE_WITH_TIME_FULL"
-msgstr "N j, Y, P"
+msgstr "N j, Y, H:i"
#: contrib/admin/templates/admin/object_history.html:36
-msgid ""
-"This object doesn't have a change history. It probably wasn't added via this "
-"admin site."
-msgstr ""
-"Ta objekt nima zgodovine. Verjetno ni bil dodan preko te administratorske "
-"strani."
+msgid "This object doesn't have a change history. It probably wasn't added via this admin site."
+msgstr "Ta objekt nima zgodovine. Verjetno ni bil dodan preko te administratorske strani."
#: contrib/admin/templates/admin/base_site.html:4
msgid "Django site admin"
@@ -738,12 +724,8 @@ msgid "Server Error <em>(500)</em>"
msgstr "Napaka strežnika <em>(500)</em>"
#: contrib/admin/templates/admin/500.html:10
-msgid ""
-"There's been an error. It's been reported to the site administrators via e-"
-"mail and should be fixed shortly. Thanks for your patience."
-msgstr ""
-"PriÅ¡lo je do nepriÄakovane napake. Administratorji strani so že obveÅ¡Äeni "
-"prekoe-pošte in naj bi jo v kratkem odpravili. Hvala za vaše potrpljenje."
+msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience."
+msgstr "PriÅ¡lo je do nepriÄakovane napake. Administratorji strani so že obveÅ¡Äeni prekoe-poÅ¡te in naj bi jo v kratkem odpravili. Hvala za vaÅ¡e potrpljenje."
#: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8
@@ -752,12 +734,12 @@ msgstr "Strani ni mogoÄe najti"
#: contrib/admin/templates/admin/404.html:10
msgid "We're sorry, but the requested page could not be found."
-msgstr "Se opraivÄujemo, a zahtevane strani ni mogoÄe najti."
+msgstr "Se opraviÄujemo, a zahtevane strani ni mogoÄe najti."
#: contrib/admin/templates/admin/index.html:17
#, python-format
msgid "Models available in the %(name)s application."
-msgstr ""
+msgstr "Modeli na voljo v %(name)s aplikaciji"
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
@@ -776,7 +758,7 @@ msgstr "Nimate dovoljenja za urejanje Äesar koli."
msgid "Recent Actions"
msgstr "Zadnja dejanja"
-#: contrib/admin/templates/admin/index.html:53
+#: contrib/admin/tempalates/admin/index.html:53
msgid "My Actions"
msgstr "Moja dejanja"
@@ -804,22 +786,13 @@ msgstr "Izbriši"
#: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format
-msgid ""
-"Deleting the %(object_name)s '%(object)s' would result in deleting related "
-"objects, but your account doesn't have permission to delete the following "
-"types of objects:"
-msgstr ""
-"Izbris %(object_name)s '%(object)s' bi pomenil izbris povezanih objektov, "
-"vendarvi nimate dovoljenja za izbris naslednjih tipov objektov:"
+msgid "Deleting the %(object_name)s '%(object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:"
+msgstr "Izbris %(object_name)s '%(object)s' bi pomenil izbris povezanih objektov, vendarvi nimate dovoljenja za izbris naslednjih tipov objektov:"
#: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format
-msgid ""
-"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
-"the following related items will be deleted:"
-msgstr ""
-"Ste prepriÄani, da želite izbrisati %(object_name)s \"%(object)s\"?Vsi "
-"naslednji povezani elementi bodo izbrisani:"
+msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of the following related items will be deleted:"
+msgstr "Ste prepriÄani, da želite izbrisati %(object_name)s \"%(object)s\"?Vsi naslednji povezani elementi bodo izbrisani:"
#: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure"
@@ -843,6 +816,8 @@ msgid "Please correct the error below."
msgid_plural "Please correct the errors below."
msgstr[0] "Prosimo, odpravite sledeÄo napako."
msgstr[1] "Prosimo, odpravite sledeÄe napake."
+msgstr[2] "Prosimo, odpravite sledeÄi napaki."
+msgstr[3] "Prosimo, odpravite sledeÄe napake."
#: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering"
@@ -892,12 +867,8 @@ msgid "Password reset"
msgstr "Obnova gesla"
#: contrib/admin/templates/registration/password_reset_form.html:12
-msgid ""
-"Forgotten your password? Enter your e-mail address below, and we'll reset "
-"your password and e-mail the new one to you."
-msgstr ""
-"Ste pozabili geslo? Vnesite vaš e-naslov spodaj in mi vam bomo poslali novo "
-"geslo."
+msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you."
+msgstr "Ste pozabili geslo? Vnesite vaš e-naslov spodaj in mi vam bomo poslali novo geslo."
#: contrib/admin/templates/registration/password_reset_form.html:16
msgid "E-mail address:"
@@ -921,18 +892,12 @@ msgid "Password reset successful"
msgstr "Geslo je bilo uspešno obnovljeno"
#: contrib/admin/templates/registration/password_reset_done.html:12
-msgid ""
-"We've e-mailed a new password to the e-mail address you submitted. You "
-"should be receiving it shortly."
+msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly."
msgstr "Po e-pošti smo vam poslali novo geslo.Morali bi ga prejeti v kratkem"
#: contrib/admin/templates/registration/password_change_form.html:12
-msgid ""
-"Please enter your old password, for security's sake, and then enter your new "
-"password twice so we can verify you typed it in correctly."
-msgstr ""
-"Prosim, vnesite vaše staro geslo (zaradi varnosti) in nato še dvakrat novo"
-"(da preverimo, da se niste zatipkali)"
+msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly."
+msgstr "Prosim, vnesite vaše staro geslo (zaradi varnosti) in nato še dvakrat novo(da preverimo, da se niste zatipkali)"
#: contrib/admin/templates/registration/password_change_form.html:17
msgid "Old password:"
@@ -1000,34 +965,24 @@ msgid ""
"your computer is \"internal\").</p>\n"
msgstr ""
"\n"
-"<p class=\"help\">Za inÅ¡talacijo zaznamkic povleÄite povezavo v orodno "
-"vrstico\n"
-"z zaznamki, ali kliknite z desno miškino tipko na povezavo in jo dodajte med "
-"zaznamkeZdaj lahko uporabite zaznamek s katere koli strani. Opomba: nekatere "
-"teh stranilahko gledate le z internega raÄunalnika (preverite s sistemskim "
-"administratorjem)</p>\n"
+"<p class=\"help\">Za inÅ¡talacijo zaznamkic povleÄite povezavo v orodno vrstico\n"
+"z zaznamki, ali kliknite z desno miÅ¡kino tipko na povezavo in jo dodajte med zaznamkeZdaj lahko uporabite zaznamek s katere koli strani. Opomba: nekatere teh stranilahko gledate le z internega raÄunalnika (preverite s sistemskim administratorjem)</p>\n"
#: contrib/admin/templates/admin_doc/bookmarklets.html:19
msgid "Documentation for this page"
msgstr "Dokumentacija za to stran"
#: contrib/admin/templates/admin_doc/bookmarklets.html:20
-msgid ""
-"Jumps you from any page to the documentation for the view that generates "
-"that page."
-msgstr ""
-"Skok na stran z dokumentacijo za pogled (view), ki generira trenutno stran."
+msgid "Jumps you from any page to the documentation for the view that generates that page."
+msgstr "Skok na stran z dokumentacijo za pogled (view), ki generira trenutno stran."
#: contrib/admin/templates/admin_doc/bookmarklets.html:22
msgid "Show object ID"
msgstr "Pokaži ID objekta"
#: contrib/admin/templates/admin_doc/bookmarklets.html:23
-msgid ""
-"Shows the content-type and unique ID for pages that represent a single "
-"object."
-msgstr ""
-"Pokaže content-type in unikatni ID za strani, ki predstavljajo en objekt."
+msgid "Shows the content-type and unique ID for pages that represent a single object."
+msgstr "Pokaže content-type in unikatni ID za strani, ki predstavljajo en objekt."
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
msgid "Edit this object (current window)"
@@ -1035,8 +990,7 @@ msgstr "Uredi trenutni objekt (v trenutnem oknu)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
msgid "Jumps to the admin page for pages that represent a single object."
-msgstr ""
-"Skok na administracijsko stran za vse strani, ki predstavljajo en objekt."
+msgstr "Skok na administracijsko stran za vse strani, ki predstavljajo en objekt."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)"
@@ -1067,23 +1021,16 @@ msgid "redirect from"
msgstr "preusmeritev iz"
#: contrib/redirects/models.py:8
-msgid ""
-"This should be an absolute path, excluding the domain name. Example: '/"
-"events/search/'."
-msgstr ""
-"To mora biti absolutna pot, izkljuÄujoÄ domeno. Primer: '/events/search'-"
+msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'."
+msgstr "To mora biti absolutna pot, izkljuÄujoÄ domeno. Primer: '/events/search'-"
#: contrib/redirects/models.py:9
msgid "redirect to"
msgstr "preusmeri na"
#: contrib/redirects/models.py:10
-msgid ""
-"This can be either an absolute path (as above) or a full URL starting with "
-"'http://'."
-msgstr ""
-"To je ali absolutna pot (kot zgoraj) ali popoln URL naslov (zaÄne se z "
-"'http://')"
+msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'."
+msgstr "To je ali absolutna pot (kot zgoraj) ali popoln URL naslov (zaÄne se z 'http://')"
#: contrib/redirects/models.py:12
msgid "redirect"
@@ -1094,10 +1041,8 @@ msgid "redirects"
msgstr "preusmeritve"
#: contrib/flatpages/models.py:8
-msgid ""
-"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
-msgstr ""
-"Primer: '/about/contact/'. Mora vsebovati / (poÅ¡evnico) na zaÄetku in koncu."
+msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes."
+msgstr "Primer: '/about/contact/'. Mora vsebovati / (poÅ¡evnico) na zaÄetku in koncu."
#: contrib/flatpages/models.py:9
msgid "title"
@@ -1116,12 +1061,8 @@ msgid "template name"
msgstr "ime predloge"
#: contrib/flatpages/models.py:13
-msgid ""
-"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
-"use 'flatpages/default'."
-msgstr ""
-"Primer: 'flatpages/contact_page'. ÄŒe to polje ni izpolnjeno, bo sistem "
-"uporabil 'flatpages/default'."
+msgid "Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'."
+msgstr "Primer: 'flatpages/contact_page'. ÄŒe to polje ni izpolnjeno, bo sistem uporabil 'flatpages/default'."
#: contrib/flatpages/models.py:14
msgid "registration required"
@@ -1129,19 +1070,18 @@ msgstr "obvezna registracija"
#: contrib/flatpages/models.py:14
msgid "If this is checked, only logged-in users will be able to view the page."
-msgstr ""
-"ÄŒe je to polje odkljukano, si lahko to stran ogledajo le registrirani "
-"uporabniki."
+msgstr "ÄŒe je to polje odkljukano, si lahko to stran ogledajo le registrirani uporabniki."
#: contrib/flatpages/models.py:18
msgid "flat page"
-msgstr "ploh stran :)"
+msgstr "enostavna stran"
#: contrib/flatpages/models.py:19
msgid "flat pages"
-msgstr "ploh strani :)"
+msgstr "enostavne strani"
-#: contrib/auth/models.py:13 contrib/auth/models.py:26
+#: contrib/auth/models.py:13
+#: contrib/auth/models.py:26
msgid "name"
msgstr "ime"
@@ -1150,24 +1090,22 @@ msgid "codename"
msgstr "kodno ime"
#: contrib/auth/models.py:17
-#, fuzzy
msgid "permission"
-msgstr "Dovoljenje"
+msgstr "dovoljenje"
-#: contrib/auth/models.py:18 contrib/auth/models.py:27
-#, fuzzy
+#: contrib/auth/models.py:18
+#: contrib/auth/models.py:27
msgid "permissions"
-msgstr "Dovoljenja"
+msgstr "dovoljenja"
#: contrib/auth/models.py:29
-#, fuzzy
msgid "group"
-msgstr "Skupina"
+msgstr "skupina"
-#: contrib/auth/models.py:30 contrib/auth/models.py:65
-#, fuzzy
+#: contrib/auth/models.py:30
+#: contrib/auth/models.py:65
msgid "groups"
-msgstr "Skupine"
+msgstr "skupine"
#: contrib/auth/models.py:55
msgid "username"
@@ -1218,27 +1156,20 @@ msgid "date joined"
msgstr "Älan od"
#: contrib/auth/models.py:66
-msgid ""
-"In addition to the permissions manually assigned, this user will also get "
-"all permissions granted to each group he/she is in."
-msgstr ""
-"Polek roÄno doloÄenih dovoljenj bo ta uporabnik dobil tudi vsa dovoljenja,ki "
-"pripadajo vsem skupinah, v katerih je."
+msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."
+msgstr "Polek roÄno doloÄenih dovoljenj bo ta uporabnik dobil tudi vsa dovoljenja,ki pripadajo vsem skupinah, v katerih je."
#: contrib/auth/models.py:67
-#, fuzzy
msgid "user permissions"
-msgstr "Dovoljenja"
+msgstr "uporabniška dovoljenja"
#: contrib/auth/models.py:70
-#, fuzzy
msgid "user"
-msgstr "Uporabnik"
+msgstr "uporabnik"
#: contrib/auth/models.py:71
-#, fuzzy
msgid "users"
-msgstr "Uporabniki"
+msgstr "uporabniki"
#: contrib/auth/models.py:76
msgid "Personal info"
@@ -1257,22 +1188,16 @@ msgid "Groups"
msgstr "Skupine"
#: contrib/auth/models.py:219
-#, fuzzy
msgid "message"
-msgstr "SporoÄilo"
+msgstr "sporoÄilo"
#: contrib/auth/forms.py:30
-msgid ""
-"Your Web browser doesn't appear to have cookies enabled. Cookies are "
-"required for logging in."
-msgstr ""
-"Izgleda, da vaÅ¡ brskalnik nima omogoÄenih piÅ¡kotkov. PiÅ¡kotki so potrebni za "
-"prijavo."
+msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."
+msgstr "Izgleda, da vaÅ¡ brskalnik nima omogoÄenih piÅ¡kotkov. PiÅ¡kotki so potrebni za prijavo."
#: contrib/contenttypes/models.py:25
-#, fuzzy
msgid "python model class name"
-msgstr "python ime modula"
+msgstr "python ime razreda modela"
#: contrib/contenttypes/models.py:28
msgid "content type"
@@ -1366,23 +1291,28 @@ msgstr "januar"
msgid "February"
msgstr "februar"
-#: utils/dates.py:14 utils/dates.py:27
+#: utils/dates.py:14
+#: utils/dates.py:27
msgid "March"
msgstr "marec"
-#: utils/dates.py:14 utils/dates.py:27
+#: utils/dates.py:14
+#: utils/dates.py:27
msgid "April"
msgstr "april"
-#: utils/dates.py:14 utils/dates.py:27
+#: utils/dates.py:14
+#: utils/dates.py:27
msgid "May"
msgstr "maj"
-#: utils/dates.py:14 utils/dates.py:27
+#: utils/dates.py:14
+#: utils/dates.py:27
msgid "June"
msgstr "junij"
-#: utils/dates.py:15 utils/dates.py:27
+#: utils/dates.py:15
+#: utils/dates.py:27
msgid "July"
msgstr "julij"
@@ -1407,62 +1337,58 @@ msgid "December"
msgstr "december"
#: utils/dates.py:19
-#, fuzzy
msgid "jan"
-msgstr "in"
+msgstr "jan"
#: utils/dates.py:19
-#, fuzzy
msgid "feb"
-msgstr "feb."
+msgstr "feb"
#: utils/dates.py:19
msgid "mar"
-msgstr ""
+msgstr "mar"
#: utils/dates.py:19
msgid "apr"
-msgstr ""
+msgstr "apr"
#: utils/dates.py:19
-#, fuzzy
msgid "may"
-msgstr "dan"
+msgstr "maj"
#: utils/dates.py:19
msgid "jun"
-msgstr ""
+msgstr "jun"
#: utils/dates.py:20
msgid "jul"
-msgstr ""
+msgstr "jul"
#: utils/dates.py:20
msgid "aug"
-msgstr ""
+msgstr "avg"
#: utils/dates.py:20
msgid "sep"
-msgstr ""
+msgstr "sep"
#: utils/dates.py:20
msgid "oct"
-msgstr ""
+msgstr "okt"
#: utils/dates.py:20
msgid "nov"
-msgstr ""
+msgstr "nov"
#: utils/dates.py:20
msgid "dec"
-msgstr ""
+msgstr "dec"
#: utils/dates.py:27
msgid "Jan."
msgstr "jan."
#: utils/dates.py:27
-#, fuzzy
msgid "Feb."
msgstr "feb."
@@ -1489,38 +1415,50 @@ msgstr "dec."
#: utils/timesince.py:12
msgid "year"
msgid_plural "years"
-msgstr[0] "leto"
-msgstr[1] "let"
+msgstr[0] "let"
+msgstr[1] "leto"
+msgstr[2] "leti"
+msgstr[3] "leta"
#: utils/timesince.py:13
msgid "month"
msgid_plural "months"
-msgstr[0] "mesec"
-msgstr[1] "mesecev"
+msgstr[0] "mesecev"
+msgstr[1] "mesec"
+msgstr[2] "meseca"
+msgstr[3] "meseci"
#: utils/timesince.py:14
msgid "week"
msgid_plural "weeks"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "tednov"
+msgstr[1] "teden"
+msgstr[2] "tedna"
+msgstr[3] "tednov"
#: utils/timesince.py:15
msgid "day"
msgid_plural "days"
-msgstr[0] "dan"
-msgstr[1] "dni"
+msgstr[0] "dni"
+msgstr[1] "dan"
+msgstr[2] "dneva"
+msgstr[3] "dni"
#: utils/timesince.py:16
msgid "hour"
msgid_plural "hours"
-msgstr[0] "ura"
-msgstr[1] "ur"
+msgstr[0] "ur"
+msgstr[1] "ura"
+msgstr[2] "uri"
+msgstr[3] "ure"
#: utils/timesince.py:17
msgid "minute"
msgid_plural "minutes"
-msgstr[0] "minuta"
-msgstr[1] "minut"
+msgstr[0] "minut"
+msgstr[1] "minuta"
+msgstr[2] "minuti"
+msgstr[3] "minute"
#: conf/global_settings.py:37
msgid "Bengali"
@@ -1544,7 +1482,7 @@ msgstr "Nemški"
#: conf/global_settings.py:42
msgid "Greek"
-msgstr ""
+msgstr "Grški"
#: conf/global_settings.py:43
msgid "English"
@@ -1564,11 +1502,11 @@ msgstr "GaliÄanski"
#: conf/global_settings.py:47
msgid "Hungarian"
-msgstr ""
+msgstr "Madžarski"
#: conf/global_settings.py:48
msgid "Hebrew"
-msgstr ""
+msgstr "Hebrejski"
#: conf/global_settings.py:49
msgid "Icelandic"
@@ -1619,9 +1557,8 @@ msgid "Swedish"
msgstr "Å vedski"
#: conf/global_settings.py:61
-#, fuzzy
msgid "Ukrainian"
-msgstr "Brazilski"
+msgstr "Ukrajinski"
#: conf/global_settings.py:62
msgid "Simplified Chinese"
@@ -1636,12 +1573,8 @@ msgid "This value must contain only letters, numbers and underscores."
msgstr "To polje lahko vsebuje le Ärke, Å¡tevila in podÄrtaje (_)."
#: core/validators.py:64
-#, fuzzy
-msgid ""
-"This value must contain only letters, numbers, underscores, dashes or "
-"slashes."
-msgstr ""
-"To polje lahko vsebuje le Ärke, Å¡tevila, podÄrtaje (_) in poÅ¡evnice (/)."
+msgid "This value must contain only letters, numbers, underscores, dashes or slashes."
+msgstr "To polje lahko vsebuje le Ärke, Å¡tevila, podÄrtaje, poÅ¡evnice ali pomiÅ¡ljaje."
#: core/validators.py:72
msgid "Uppercase letters are not allowed here."
@@ -1691,23 +1624,18 @@ msgstr "Vnesite veljavni datum v zapisu YYYY-MM-DD (leto-mesec-dan)."
msgid "Enter a valid time in HH:MM format."
msgstr "Vnesite veljavni Äas v zapisu HH:MM (ura:minuta)."
-#: core/validators.py:132 db/models/fields/__init__.py:468
+#: core/validators.py:132
+#: db/models/fields/__init__.py:468
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
-msgstr ""
-"Vnesite veljavni datum/Äas v zapisu YYYY-MM-DD HH:MM (leto-mesec-dan ura:"
-"minuta)"
+msgstr "Vnesite veljavni datum/Äas v zapisu YYYY-MM-DD HH:MM (leto-mesec-dan ura:minuta)"
#: core/validators.py:136
msgid "Enter a valid e-mail address."
msgstr "Vnesite veljavni e-naslov."
#: core/validators.py:148
-msgid ""
-"Upload a valid image. The file you uploaded was either not an image or a "
-"corrupted image."
-msgstr ""
-"Uploadjate veljavno sliko. Trenutna datoteka ni bila niti slika niti "
-"okvarjena slika."
+msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image."
+msgstr "Uploadjate veljavno sliko. Trenutna datoteka ni bila niti slika niti okvarjena slika."
#: core/validators.py:155
#, python-format
@@ -1747,7 +1675,8 @@ msgstr "Pokvarjen XML: %s"
msgid "Invalid URL: %s"
msgstr "Neveljavni URL naslov: %s"
-#: core/validators.py:206 core/validators.py:208
+#: core/validators.py:206
+#: core/validators.py:208
#, python-format
msgid "The URL %s is a broken link."
msgstr "URL povezava %s je polomljena."
@@ -1762,6 +1691,8 @@ msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Pazite na jezik! Beseda %s tu ni dovoljena."
msgstr[1] "Pazite na jezik! Besede %s tu niso dovoljene."
+msgstr[2] "Pazite na jezik! Besede %s tu niso dovoljene."
+msgstr[3] "Pazite na jezik! Besede %s tu niso dovoljene."
#: core/validators.py:236
#, python-format
@@ -1772,7 +1703,8 @@ msgstr "To polje mora ustrezati polju '%s'."
msgid "Please enter something for at least one field."
msgstr "Prosim, vnesite nekaj v vsaj eno od polj."
-#: core/validators.py:264 core/validators.py:275
+#: core/validators.py:264
+#: core/validators.py:275
msgid "Please enter both fields or leave them both empty."
msgstr "Prosimo, izpolnite obe polji ali ju pustite obe prazni."
@@ -1802,20 +1734,20 @@ msgstr "Prosim vnesite decimalno število."
#: core/validators.py:349
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
-msgid_plural ""
-"Please enter a valid decimal number with at most %s total digits."
-msgstr[0] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s Å¡tevkami."
-msgstr[1] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s Å¡tevkami."
+msgid_plural "Please enter a valid decimal number with at most %s total digits."
+msgstr[0] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s Å¡tevko."
+msgstr[1] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s Å¡tevkama."
+msgstr[2] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s Å¡tevkami."
+msgstr[3] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s Å¡tevkami."
#: core/validators.py:352
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
-msgid_plural ""
-"Please enter a valid decimal number with at most %s decimal places."
-msgstr[0] ""
-"Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s decimalnimi mesti."
-msgstr[1] ""
-"Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s decimalnimi mesti."
+msgid_plural "Please enter a valid decimal number with at most %s decimal places."
+msgstr[0] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s decimalnim mestom."
+msgstr[1] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s decimalnimi mesti."
+msgstr[2] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s decimalnimi mesti."
+msgstr[3] "Prosimo, vnesite veljavno decimalno Å¡tevilo z najveÄ %s decimalnimi mesti."
#: core/validators.py:362
#, python-format
@@ -1842,94 +1774,68 @@ msgstr "Iz %s nisem mogel izloÄiti niÄesar."
#: core/validators.py:429
#, python-format
-msgid ""
-"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
+msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr "URL %(url)s je vrnil neveljavni Content-Type '%(contenttype)s'."
#: core/validators.py:462
#, python-format
-msgid ""
-"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
-"\"%(start)s\".)"
-msgstr ""
-"Prosimo, zaprite nezaprto %(tag)s oznako v vrstici %(line)s. (Vrstica se "
-"zaÄne z \"%(start)s\".)"
+msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)"
+msgstr "Prosimo, zaprite nezaprto %(tag)s oznako v vrstici %(line)s. (Vrstica se zaÄne z \"%(start)s\".)"
#: core/validators.py:466
#, python-format
-msgid ""
-"Some text starting on line %(line)s is not allowed in that context. (Line "
-"starts with \"%(start)s\".)"
-msgstr ""
-"Tekst z zaÄetka vrstice %(line)s ni dovoljen v tem kontekstu. (Vrstica se "
-"zaÄne z \"%(start)s\".)"
+msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)"
+msgstr "Tekst z zaÄetka vrstice %(line)s ni dovoljen v tem kontekstu. (Vrstica se zaÄne z \"%(start)s\".)"
#: core/validators.py:471
-#, fuzzy, python-format
-msgid ""
-"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
-"(start)s\".)"
-msgstr ""
-"\"<%(tag)s>\" v vrstici %(line)s je neveljavna oznaka. (Vrstica se zaÄne z "
-"\"%(start)s\".)"
+#, python-format
+msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)"
+msgstr "\"%(attr)s\" v vrstici %(line)s je neveljavna oznaka. (Vrstica se zaÄne z \"%(start)s\".)"
#: core/validators.py:476
#, python-format
-msgid ""
-"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
-"(start)s\".)"
-msgstr ""
-"\"<%(tag)s>\" v vrstici %(line)s je neveljavna oznaka. (Vrstica se zaÄne z "
-"\"%(start)s\".)"
+msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)"
+msgstr "\"<%(tag)s>\" v vrstici %(line)s je neveljavna oznaka. (Vrstica se zaÄne z \"%(start)s\".)"
#: core/validators.py:480
#, python-format
-msgid ""
-"A tag on line %(line)s is missing one or more required attributes. (Line "
-"starts with \"%(start)s\".)"
-msgstr ""
-"Oznaki v vrstici %(line)s manjka eden ali veÄ nujnih atributov (Vrstica se "
-"zaÄne z \"%(start)s\".)"
+msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)"
+msgstr "Oznaki na vrstici %(line)s manjka eden ali veÄ zahtevanih parametrov. (Vrstica se zaÄne z \"%(start)s\".)"
#: core/validators.py:485
#, python-format
-msgid ""
-"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
-"starts with \"%(start)s\".)"
-msgstr ""
-"Atribut \"%(attr)s\" v vrstici %(line)s vsebuje neveljavno vrednost. "
-"(Vrstica se zaÄne z \"%(start)s\".)"
+msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)"
+msgstr "Atribut \"%(attr)s\" v vrstici %(line)s vsebuje neveljavno vrednost. (Vrstica se zaÄne z \"%(start)s\".)"
#: db/models/manipulators.py:302
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
-msgstr "%(object)s s tem %(type)s že obstaja za veljavno (%field)s."
+msgstr "%(object)s s tem %(type)s že obstaja za dane %(field)s."
#: db/models/fields/__init__.py:40
#, python-format
msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "%(optname)s s tem %(fieldname)s že obstaja."
-#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
-#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
+#: db/models/fields/__init__.py:114
+#: db/models/fields/__init__.py:265
+#: db/models/fields/__init__.py:542
+#: db/models/fields/__init__.py:553
#: forms/__init__.py:346
msgid "This field is required."
msgstr "To polje je obvezno"
#: db/models/fields/__init__.py:337
-#, fuzzy
msgid "This value must be an integer."
-msgstr "Ta vrednost mora biti potenca od %s."
+msgstr "Ta vrednost mora biti število."
#: db/models/fields/__init__.py:369
-#, fuzzy
msgid "This value must be either True or False."
-msgstr "Ta vrednost mora biti potenca od %s."
+msgstr "Ta vrednost mora biti \"True\" ali \"False\"."
#: db/models/fields/__init__.py:385
-#, fuzzy
msgid "This field cannot be null."
-msgstr "To polje ni veljavno."
+msgstr "To polje ne more biti prazno."
#: db/models/fields/__init__.py:562
msgid "Enter a valid filename."
@@ -1941,39 +1847,38 @@ msgid "Please enter a valid %s."
msgstr "Prosimo, vnesite veljaven %s."
#: db/models/fields/related.py:579
-#, fuzzy
msgid "Separate multiple IDs with commas."
msgstr "VeÄ ID-jev loÄite z vejicami."
#: db/models/fields/related.py:581
-#, fuzzy
-msgid ""
-"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
-msgstr ""
-" Stisni \"Control\" (ali \"Command\" na Mac-u), da izbereÅ¡ veÄ kot enega."
+msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
+msgstr "Držite \"Control\" (ali \"Command\" na Mac-u), za izbiro veÄ kot enega."
#: db/models/fields/related.py:625
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
-msgid_plural ""
-"Please enter valid %(self)s IDs. The values %(value)r are invalid."
-msgstr[0] ""
-"Prosimo, vnesite veljavni %(self)s ID-je. Vrednost %(value)r ni veljavna."
-msgstr[1] ""
-"Prosimo, vnesite veljavni %(self)s ID-je. Vrednosti %(value)r niso veljavne."
+msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid."
+msgstr[0] "Prosimo, vnesite veljavne %(self)s ID-je. Vrednost %(value)r ni veljavna."
+msgstr[1] "Prosimo, vnesite veljavni %(self)s ID. Vrednosti %(value)r niso veljavne."
+msgstr[2] "Prosimo, vnesite veljavne %(self)s ID-je. Vrednosti %(value)r niso veljavne."
+msgstr[3] "Prosimo, vnesite veljavne %(self)s ID-je. Vrednosti %(value)r niso veljavne."
#: forms/__init__.py:380
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
-msgstr[0] "Poskrbite, da bo tekst krajši do %s znakov."
-msgstr[1] "Poskrbite, da bo tekst krajši od %s znakov."
+msgstr[0] "Poskrbite, da bo tekst krajši od %s znakov."
+msgstr[1] "Poskrbite, da bo tekst krajši od %s znaka."
+msgstr[2] "Poskrbite, da bo tekst krajši od %s znakov."
+msgstr[3] "Poskrbite, da bo tekst krajši od %s znakov."
#: forms/__init__.py:385
msgid "Line breaks are not allowed here."
msgstr "Prelomi vrstice tu niso dovoljeni."
-#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
+#: forms/__init__.py:480
+#: forms/__init__.py:551
+#: forms/__init__.py:589
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "Izberite veljavno možnost; '%(data)s' ni v %(choices)s."
@@ -1998,23 +1903,24 @@ msgstr "Vnesite celo število med 0 in 32,767."
msgid "yes,no,maybe"
msgstr "ja,ne,morda"
-#~ msgid "Comment"
-#~ msgstr "Komentar"
+msgid "Comment"
+msgstr "Komentar"
+
+msgid "Comments"
+msgstr "Komentarji"
-#~ msgid "Comments"
-#~ msgstr "Komentarji"
+msgid "String (up to 50)"
+msgstr "Niz (do 50 znakov)"
-#~ msgid "String (up to 50)"
-#~ msgstr "Niz (do 50 znakov)"
+msgid "label"
+msgstr "oznaka"
-#~ msgid "label"
-#~ msgstr "oznaka"
+msgid "package"
+msgstr "paket"
-#~ msgid "package"
-#~ msgstr "paket"
+msgid "packages"
+msgstr "paketi"
-#~ msgid "packages"
-#~ msgstr "paketi"
+msgid "Slovene"
+msgstr "Slovensko"
-#~ msgid "Slovene"
-#~ msgstr "Slovenski"
diff --git a/django/conf/locale/ta/LC_MESSAGES/django.mo b/django/conf/locale/ta/LC_MESSAGES/django.mo
new file mode 100644
index 0000000000..c85327d06b
--- /dev/null
+++ b/django/conf/locale/ta/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/ta/LC_MESSAGES/django.po b/django/conf/locale/ta/LC_MESSAGES/django.po
new file mode 100644
index 0000000000..7637bb9cdb
--- /dev/null
+++ b/django/conf/locale/ta/LC_MESSAGES/django.po
@@ -0,0 +1,2111 @@
+# translation of django.po to
+# translation of django_aa.po to
+# translation of django_aa.po to tamil
+# Parthan <parthan@au-kbc.org>, 2006.
+# R Hariram Aatreya <rha@localhost.localdomain>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: django\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-05-16 10:14+0200\n"
+"PO-Revision-Date: 2006-07-18 16:47+0530\n"
+"Last-Translator: R Hariram Aatreya <rha@localhost.localdomain>\n"
+"Language-Team: <en@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9\n"
+
+#: contrib/comments/models.py:67 contrib/comments/models.py:166
+msgid "object ID"
+msgstr "அடையாளமà¯"
+
+#: contrib/comments/models.py:68
+msgid "headline"
+msgstr "தலையஙà¯à®•à®®à¯"
+
+#: contrib/comments/models.py:69 contrib/comments/models.py:90
+#: contrib/comments/models.py:167
+msgid "comment"
+msgstr "கà¯à®±à®¿à®ªà¯à®ªà¯"
+
+#: contrib/comments/models.py:70
+msgid "rating #1"
+msgstr "#1 தரவரிசை"
+
+#: contrib/comments/models.py:71
+msgid "rating #2"
+msgstr "#2 தரவரிசை"
+
+#: contrib/comments/models.py:72
+msgid "rating #3"
+msgstr "#3 தரவரிசை"
+
+#: contrib/comments/models.py:73
+msgid "rating #4"
+msgstr "#4 தரவரிசை"
+
+#: contrib/comments/models.py:74
+msgid "rating #5"
+msgstr "#5 தரவரிசை"
+
+#: contrib/comments/models.py:75
+msgid "rating #6"
+msgstr "#6 தரவரிசை"
+
+#: contrib/comments/models.py:76
+msgid "rating #7"
+msgstr "#7 தரவரிசை"
+
+#: contrib/comments/models.py:77
+msgid "rating #8"
+msgstr "#8 தரவரிசை"
+
+#: contrib/comments/models.py:82
+msgid "is valid rating"
+msgstr "à®…à®™à¯à®•ீகரிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿ தரவரிசை"
+
+#: contrib/comments/models.py:83 contrib/comments/models.py:169
+msgid "date/time submitted"
+msgstr "தேதிநேரம௠சமரà¯à®ªà¯à®ªà®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯"
+
+#: contrib/comments/models.py:84 contrib/comments/models.py:170
+msgid "is public"
+msgstr "பொதà¯à®µà®¾à®©à®¤à¯"
+
+#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
+msgid "IP address"
+msgstr "ip விலாசமà¯"
+
+#: contrib/comments/models.py:86
+msgid "is removed"
+msgstr "நீகà¯à®•படà¯à®Ÿà®¤à¯"
+
+#: contrib/comments/models.py:86
+msgid ""
+"Check this box if the comment is inappropriate. A \"This comment has been "
+"removed\" message will be displayed instead."
+msgstr "கà¯à®±à®¿à®ªà¯à®ªà¯ செரியாக இலà¯à®²à¯ˆà®¯à¯†à®©à¯à®±à®¾à®²à¯ இநà¯à®¤à¯ பெடà¯à®Ÿà®¿à®¯à®¿à®²à¯ கà¯à®±à®¿à®¯à®¿à®Ÿà®µà¯à®®à¯. இதறà¯à®•௠பதிலாக \"இநà¯à®¤ கà¯à®±à®¿à®ªà¯à®ªà¯ நீகà¯à®•படà¯à®Ÿà®¤à¯\" காணà¯à®ªà®¿à®•à¯à®•படà¯à®®à¯."
+
+#: contrib/comments/models.py:91
+msgid "comments"
+msgstr "கà¯à®±à®¿à®ªà¯à®ªà¯"
+
+#: contrib/comments/models.py:131 contrib/comments/models.py:207
+msgid "Content object"
+msgstr "பொரà¯à®³à¯ அடகà¯à®• object"
+
+#: contrib/comments/models.py:159
+#, python-format
+msgid ""
+"Posted by %(user)s at %(date)s\n"
+"\n"
+"%(comment)s\n"
+"\n"
+"http://%(domain)s%(url)s"
+msgstr ""
+"%(user)s ஆல௠%(date)s இல௠அளிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ \n"
+"\n"
+"%(comment)s\n"
+"\n"
+"http://%(domain)s%(url)s"
+
+#: contrib/comments/models.py:168
+msgid "person's name"
+msgstr "நபரின௠பெயரà¯"
+
+#: contrib/comments/models.py:171
+msgid "ip address"
+msgstr "ip விலாசமà¯"
+
+#: contrib/comments/models.py:173
+msgid "approved by staff"
+msgstr "பணியாளரà¯à®•ளால௠அனà¯à®®à®¤à®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯"
+
+#: contrib/comments/models.py:176
+msgid "free comment"
+msgstr "சà¯à®¤à®¨à¯à®¤à®°à®®à®¾à®© கà¯à®±à®¿à®ªà¯à®ªà¯"
+
+#: contrib/comments/models.py:177
+msgid "free comments"
+msgstr "சà¯à®¤à®¨à¯à®¤à®°à®®à®¾à®© கà¯à®±à®¿à®ªà¯à®ªà¯"
+
+#: contrib/comments/models.py:233
+msgid "score"
+msgstr "மதிபà¯à®ªà¯€à®Ÿà¯"
+
+#: contrib/comments/models.py:234
+msgid "score date"
+msgstr "மதிபà¯à®ªà¯€à®Ÿà¯ தேதி"
+
+#: contrib/comments/models.py:237
+msgid "karma score"
+msgstr "கரà¯à®®à®¾ மதிபà¯à®ªà¯€à®Ÿà¯"
+
+#: contrib/comments/models.py:238
+msgid "karma scores"
+msgstr "கரà¯à®®à®¾ மதிபà¯à®ªà¯€à®Ÿà¯"
+
+#: contrib/comments/models.py:242
+#, python-format
+msgid "%(score)d rating by %(user)s"
+msgstr "%(user)s ஈடà¯à®Ÿà®¯ %(score)d "
+
+#: contrib/comments/models.py:258
+#, python-format
+msgid ""
+"This comment was flagged by %(user)s:\n"
+"\n"
+"%(text)s"
+msgstr ""
+"இநà¯à®¤ கà¯à®±à®¿à®ªà¯à®ªà¯ %(user)s ஆல௠கà¯à®±à®¿à®•à¯à®•படà¯à®Ÿà®¤à¯:\n"
+"\n"
+"%(text)s"
+
+#: contrib/comments/models.py:265
+msgid "flag date"
+msgstr "கà¯à®±à®¿à®¯à®¿à®©à¯ தேதி"
+
+#: contrib/comments/models.py:268
+msgid "user flag"
+msgstr "பயனாளர௠கà¯à®±à®¿"
+
+#: contrib/comments/models.py:269
+msgid "user flags"
+msgstr "பயனாளர௠கà¯à®±à®¿à®•ளà¯"
+
+#: contrib/comments/models.py:273
+#, python-format
+msgid "Flag by %r"
+msgstr "%r ஆல௠கà¯à®±à®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯"
+
+#: contrib/comments/models.py:278
+msgid "deletion date"
+msgstr "நீகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿ தேதி"
+
+#: contrib/comments/models.py:280
+msgid "moderator deletion"
+msgstr "மடà¯à®Ÿà¯Šà®±à¯à®¤à¯à®¤à®¾à®²à¯ நீகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯"
+
+#: contrib/comments/models.py:281
+msgid "moderator deletions"
+msgstr "மடà¯à®Ÿà¯Šà®±à¯à®¤à¯à®¤à®¾à®²à¯ நீகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯"
+
+#: contrib/comments/models.py:285
+#, python-format
+msgid "Moderator deletion by %r"
+msgstr "மடà¯à®Ÿà¯Šà®±à¯à®¤à¯à®¤à®¾à®²à¯ நீகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ %r"
+
+#: contrib/comments/views/karma.py:19
+msgid "Anonymous users cannot vote"
+msgstr "அடயாளà¯à®®à¯ இலà¯à®²à®¾à®¤ பயனாளறால௠வாகà¯à®•ளிகà¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯"
+
+#: contrib/comments/views/karma.py:23
+msgid "Invalid comment ID"
+msgstr "செலà¯à®²à®¾à®¤ கà¯à®±à®¿à®ªà¯à®ªà¯ ID"
+
+#: contrib/comments/views/karma.py:25
+msgid "No voting for yourself"
+msgstr "உஙà¯à®•ளை நீஙà¯à®•ளே தேரà¯à®µà¯ செயà¯à®¤à¯ கொளà¯à®³ à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯"
+
+#: contrib/comments/views/comments.py:28
+msgid "This rating is required because you've entered at least one other rating."
+msgstr "மறà¯à®±à¯Šà®°à¯ தரவரிசை அளிகà¯à®•à¯à®ªà®Ÿà¯à®Ÿà®¤à®¾à®²à¯ இநà¯à®¤ தரவரிசை தேவைபà¯à®ªà®Ÿà¯à®•ிறதà¯."
+
+#: contrib/comments/views/comments.py:112
+#, python-format
+msgid ""
+"This comment was posted by a user who has posted fewer than %(count)s "
+"comment:\n"
+"\n"
+"%(text)s"
+"This comment was posted by a user who has posted fewer than %(count)s "
+"comments:\n"
+"\n"
+"%(text)s"
+msgstr ""
+"%(count)s கà¯à®±à¯ˆà®µà®¾à®• அளிதà¯à®¤ பயனாளரால௠இநà¯à®¤ கà¯à®°à®¿à®ªà¯à®ªà¯ˆ அளà¯à®¤à¯à®¤à®ªà®Ÿà®¤à¯:\n"
+"\n"
+"%(text)s"
+"%(count)s கà¯à®±à¯ˆà®µà®¾à®• அளிதà¯à®¤ பயனாளரால௠இநà¯à®¤ கà¯à®°à®¿à®ªà¯à®ªà¯ˆ அளà¯à®¤à¯à®¤à®ªà®Ÿà®¤à¯:\n"
+"\n"
+"%(text)s"
+
+#: contrib/comments/views/comments.py:117
+#, python-format
+msgid ""
+"This comment was posted by a sketchy user:\n"
+"\n"
+"%(text)s"
+msgstr ""
+"à®®à¯à®´à¯à®®à¯ˆà®¯à®¾à®© விவரஙகளை அளிகà¯à®•ாத பயனாளறால௠கொடà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯:\n"
+"%(text)s"
+
+#: contrib/comments/views/comments.py:189
+#: contrib/comments/views/comments.py:280
+msgid "Only POSTs are allowed"
+msgstr "POSTகளà¯à®•à¯à®•௠மடà¯à®Ÿà¯à®®à¯ அனà¯à®®à®¤à®¿ உணà¯à®Ÿà¯"
+
+#: contrib/comments/views/comments.py:193
+#: contrib/comments/views/comments.py:284
+msgid "One or more of the required fields wasn't submitted"
+msgstr "ஒனà¯à®±à¯ அலà¯à®²à®¤à¯ ஒனà¯à®±à®¿à®±à¯à®•௠மேறà¯à®ªà¯à®ªà®Ÿà¯à®Ÿ பà¯à®²à®™à¯à®•ள௠சமறà¯à®ªà®¿à®•à¯à®•பà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ"
+
+#: contrib/comments/views/comments.py:197
+#: contrib/comments/views/comments.py:286
+msgid "Somebody tampered with the comment form (security violation)"
+msgstr "எவறோ கà¯à®°à®¿à®ªà¯à®ªà¯à®±à¯ˆà®¯à¯ˆ செதபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®µà®¿à®Ÿà¯à®Ÿà®¾à®±à¯à®•ள௠(பாதà¯à®•ாபà¯à®ªà¯ மீறலà¯)"
+
+#: contrib/comments/views/comments.py:207
+#: contrib/comments/views/comments.py:292
+msgid ""
+"The comment form had an invalid 'target' parameter -- the object ID was "
+"invalid"
+msgstr "கà¯à®±à®¿à®ªà¯à®ªà¯à®±à¯ˆ படிவதà¯à®¤à®¿à®²à¯ à®®à¯à®±à¯ˆà®¯à®¾à®© இலகà¯à®•௠அளவà¯à®°à¯à®•à¯à®• இலà¯à®²à¯ˆ -- object ID à®®à¯à®±à¯ˆà®¯à®¾à®©à®¤à®¾à®• இலà¯à®²à¯ˆ"
+
+#: contrib/comments/views/comments.py:257
+#: contrib/comments/views/comments.py:321
+msgid "The comment form didn't provide either 'preview' or 'post'"
+msgstr "கà¯à®±à®¿à®ªà¯à®ªà¯ படிவம௠மà¯à®©à¯à®©à¯‹à®Ÿà¯à®Ÿà®®à¯ அலà¯à®²à®¤à¯ பிறà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ˆ வழஙà¯à®•விலà¯à®²à¯ˆ."
+
+#: contrib/comments/templates/comments/form.html:6
+#: contrib/comments/templates/comments/form.html:8
+#: contrib/admin/templates/admin/login.html:17
+msgid "Username:"
+msgstr "பயணர௠பெயரà¯:"
+
+#: contrib/comments/templates/comments/form.html:6
+#: contrib/admin/templates/admin/login.html:20
+msgid "Password:"
+msgstr "கடவà¯à®šà¯à®šà¯†à®¾à®²à¯:"
+
+#: contrib/comments/templates/comments/form.html:6
+msgid "Forgotten your password?"
+msgstr "கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மறநà¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà¯€à®°à®¾?"
+
+#: contrib/comments/templates/comments/form.html:8
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/registration/password_change_done.html:3
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/admin_doc/bookmarklets.html:4
+#: contrib/admin/templates/admin_doc/view_detail.html:4
+#: contrib/admin/templates/admin_doc/template_tag_index.html:5
+#: contrib/admin/templates/admin_doc/template_detail.html:4
+#: contrib/admin/templates/admin_doc/template_filter_index.html:5
+#: contrib/admin/templates/admin_doc/missing_docutils.html:4
+#: contrib/admin/templates/admin_doc/view_index.html:5
+#: contrib/admin/templates/admin_doc/model_detail.html:3
+#: contrib/admin/templates/admin_doc/index.html:4
+#: contrib/admin/templates/admin_doc/model_index.html:5
+msgid "Log out"
+msgstr "வெளியேறà¯"
+
+#: contrib/comments/templates/comments/form.html:12
+msgid "Ratings"
+msgstr "விகிதமà¯"
+
+#: contrib/comments/templates/comments/form.html:12
+#: contrib/comments/templates/comments/form.html:23
+msgid "Required"
+msgstr "தேவைபà¯à®ªà®Ÿà¯à®•ிறத௠"
+
+#: contrib/comments/templates/comments/form.html:12
+#: contrib/comments/templates/comments/form.html:23
+msgid "Optional"
+msgstr "விரà¯à®ªà¯à®ªà®¤à¯à®¤à¯‡à®°à¯à®µà¯"
+
+#: contrib/comments/templates/comments/form.html:23
+msgid "Post a photo"
+msgstr "பà¯à®•ைபà¯à®ªà®Ÿà®¤à¯à®¤à¯ˆ அணà¯à®ªà¯à®ªà¯"
+
+#: contrib/comments/templates/comments/form.html:27
+#: contrib/comments/templates/comments/freeform.html:5
+msgid "Comment:"
+msgstr "விவரமà¯:"
+
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# translation of django_ab.po to
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# R Hariram Aatreya <rha@localhost.localdomain>, 2006.
+#: contrib/comments/templates/comments/form.html:32
+#: contrib/comments/templates/comments/freeform.html:9
+msgid "Preview comment"
+msgstr "கà¯à®±à®¿à®ªà¯à®ªà¯ˆ à®®à¯à®©à¯à®©à¯‡à®±à¯à®±à®®à®¿à®Ÿà¯"
+
+#: contrib/comments/templates/comments/freeform.html:4
+msgid "Your name:"
+msgstr "உஙà¯à®•ளà¯à®ªà¯†à®¯à®°à¯:"
+
+#: contrib/admin/filterspecs.py:40
+#, python-format
+msgid ""
+"<h3>By %s:</h3>\n"
+"<ul>\n"
+msgstr ""
+"<h3> %s ஆலà¯:</h3>\n"
+"<ul>\n"
+
+#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
+#: contrib/admin/filterspecs.py:143
+msgid "All"
+msgstr "அணைதà¯à®¤à¯à®®à¯"
+
+#: contrib/admin/filterspecs.py:109
+msgid "Any date"
+msgstr "எநà¯à®¤ தேதியà¯à®®à¯"
+
+#: contrib/admin/filterspecs.py:110
+msgid "Today"
+msgstr "இணà¯à®±à¯"
+
+#: contrib/admin/filterspecs.py:113
+msgid "Past 7 days"
+msgstr "கடநà¯à®¤ 7 நாடà¯à®•ளிலà¯"
+
+#: contrib/admin/filterspecs.py:115
+msgid "This month"
+msgstr "இநà¯à®¤ மாதமà¯"
+
+#: contrib/admin/filterspecs.py:117
+msgid "This year"
+msgstr "இநà¯à®¤ வரà¯à®Ÿà®®à¯"
+
+#: contrib/admin/filterspecs.py:143
+msgid "Yes"
+msgstr "ஆமà¯"
+
+#: contrib/admin/filterspecs.py:143
+msgid "No"
+msgstr "இலà¯à®²à¯ˆ"
+
+#: contrib/admin/filterspecs.py:150
+msgid "Unknown"
+msgstr "தெரியாத"
+
+#: contrib/admin/models.py:16
+msgid "action time"
+msgstr "செயல௠நேரமà¯"
+
+#: contrib/admin/models.py:19
+msgid "object id"
+msgstr "பொரà¯à®³à¯ அடையாளமà¯"
+
+#: contrib/admin/models.py:20
+msgid "object repr"
+msgstr "பொரà¯à®³à¯ உரà¯à®µà®•ிதà¯à®¤à®®à¯"
+
+#: contrib/admin/models.py:21
+msgid "action flag"
+msgstr "செயரà¯à®•à¯à®±à®¿"
+
+#: contrib/admin/models.py:22
+msgid "change message"
+msgstr "செயà¯à®¤à®¿à®¯à¯ˆ மாறà¯à®±à¯"
+
+#: contrib/admin/models.py:25
+msgid "log entry"
+msgstr "பà¯à®•à¯à®ªà®¤à®¿à®µà¯ உளà¯à®³à¯€à®Ÿà¯"
+
+#: contrib/admin/models.py:26
+msgid "log entries"
+msgstr "பà¯à®•à¯à®ªà®¤à®¿à®µà¯ உளà¯à®³à¯€à®Ÿà¯"
+
+#: contrib/admin/templatetags/admin_list.py:228
+msgid "All dates"
+msgstr "அனைதà¯à®¤à¯ தேதியà¯à®®à¯"
+
+#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
+#: contrib/auth/forms.py:41
+msgid ""
+"Please enter a correct username and password. Note that both fields are case-"
+"sensitive."
+msgstr "தயவà¯à®šà¯†à®¯à¯à®¤à¯ சரியான பயனரà¯à®ªà®ªà¯†à®¯à®°à¯ மறà¯à®±à¯à®®à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ உளà¯à®³à¯à®³à®¿à®Ÿà®µà¯à®®à¯. இரணà¯à®Ÿà¯à®®à¯ எழà¯à®¤à¯à®¤à¯à®µà®•ையை சாரà¯à®¨à¯à®¤à®¤à¯."
+
+#: contrib/admin/views/decorators.py:23
+#: contrib/admin/templates/admin/login.html:25
+msgid "Log in"
+msgstr "உளà¯à®³à¯‡ போ"
+
+#: contrib/admin/views/decorators.py:61
+msgid ""
+"Please log in again, because your session has expired. Don't worry: Your "
+"submission has been saved."
+msgstr "தயவà¯à®šà¯†à®¯à¯à®¤à¯ மறà¯à®ªà®Ÿà®¿à®¯à¯à®®à¯ பà¯à®•à¯à®ªà®¤à®¿à®µà¯ செயà¯. à®à®©à¯†à®©à¯à®±à®¾à®³à¯ காலம௠மà¯à®Ÿà®¿à®µà®Ÿà¯ˆà®¨à¯à®¤à®µà¯. கவலை படவேணà¯à®Ÿà®¾à®®à¯: உஙà¯à®•ளà¯à®Ÿà¯ˆà®¯ அணà¯à®ªà¯à®ªà¯à®¤à®²à¯ சேமிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. "
+
+#: contrib/admin/views/decorators.py:68
+msgid ""
+"Looks like your browser isn't configured to accept cookies. Please enable "
+"cookies, reload this page, and try again."
+msgstr "உஙà¯à®•ளà¯à®Ÿà¯ˆà®¯ உலாவி தறà¯à®•ால நிரலà¯à®•ளை அணà¯à®®à®¤à®¿à®•à¯à®•ாதவாற௠உளà¯à®³à®®à¯ˆà®•à¯à®•ப௠படà¯à®Ÿà®µà®¾à®±à¯ தெரிகிறதà¯. தயவà¯à®šà¯†à®¯à¯à®¤à¯ தறà¯à®•ாலிக நிரலை செயலà¯à®ªà®Ÿ செயà¯à®¤à¯, பகà¯à®•தà¯à®¤à¯ˆ மறà¯à®ªà®Ÿà®¿ உளà¯à®³à¯à®µà®¾à®™à¯à®•வà¯à®®à¯."
+
+#: contrib/admin/views/decorators.py:82
+msgid "Usernames cannot contain the '@' character."
+msgstr "பயனர௠பெயர௠'@' கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà¯ˆ கொணà¯à®Ÿà®¿à®°à¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯."
+
+#: contrib/admin/views/decorators.py:84
+#, python-format
+msgid "Your e-mail address is not your username. Try '%s' instead."
+msgstr "உனà¯à®•ள௠மிணà¯à®…ஞà¯à®šà®³à¯ à®®à¯à®•வரிஉஙà¯à®•ள௠பயனர௠பெயர௠இலà¯à®²à¯ˆ. '%s' யை à®®à¯à®¯à®±à¯à®šà¯à®šà®¿ செயà¯à®¯à®µà¯à®®à¯. "
+
+#: contrib/admin/views/main.py:226
+msgid "Site administration"
+msgstr "இணைய மேளானà¯à®®à¯ˆ"
+
+#: contrib/admin/views/main.py:260
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was added successfully."
+msgstr "%(name)s \"%(obj)s\" வெறà¯à®±à®¿à®•ரமாக சேரà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯."
+
+#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
+msgid "You may edit it again below."
+msgstr "நீஙà¯à®•ள௠மறà¯à®ªà®Ÿà®¿à®¯à¯à®®à¯ தொகà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à¯à®®à¯. "
+
+#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
+#, python-format
+msgid "You may add another %s below."
+msgstr "நீஙà¯à®•ள௠மறà¯à®± %s யை கீழே சேரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à¯à®®à¯."
+
+#: contrib/admin/views/main.py:290
+#, python-format
+msgid "Add %s"
+msgstr "%s யை சேரà¯"
+
+#: contrib/admin/views/main.py:336
+#, python-format
+msgid "Added %s."
+msgstr "%s சேரà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯."
+
+#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
+#: contrib/admin/views/main.py:340
+msgid "and"
+msgstr "மறà¯à®±à¯à®®à¯"
+
+#: contrib/admin/views/main.py:338
+#, python-format
+msgid "Changed %s."
+msgstr "%s மாறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯."
+
+#: contrib/admin/views/main.py:340
+#, python-format
+msgid "Deleted %s."
+msgstr "%s அழிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯."
+
+#: contrib/admin/views/main.py:343
+msgid "No fields changed."
+msgstr "எநà¯à®¤ பà¯à®²à®®à¯à®®à¯ மாறவிலà¯à®²à¯ˆ."
+
+#: contrib/admin/views/main.py:346
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was changed successfully."
+msgstr " %(name)s \"%(obj)s\" வெறà¯à®±à®¿à®•ரமாக மாறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯."
+
+#: contrib/admin/views/main.py:354
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
+msgstr "%(name)s \"%(obj)s\" வெறà¯à®±à®¿à®•ரமாக சேரà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. நீஙà¯à®•ள௠கீழே தொகà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à¯à®®à¯."
+
+#: contrib/admin/views/main.py:392
+#, python-format
+msgid "Change %s"
+msgstr "%s யை மாறà¯à®±à¯"
+
+#: contrib/admin/views/main.py:470
+#, python-format
+msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
+msgstr "%(name)s ல௠உளà¯à®³ %(fieldname)s: %(obj)s"
+
+#: contrib/admin/views/main.py:475
+#, python-format
+msgid "One or more %(fieldname)s in %(name)s:"
+msgstr "%(name)s ல௠உளà¯à®³ %(fieldname)s:"
+
+#: contrib/admin/views/main.py:508
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was deleted successfully."
+msgstr "%(name)s \"%(obj)s\" வெறà¯à®±à®¿à®•ரமாக அழிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯."
+
+#: contrib/admin/views/main.py:511
+msgid "Are you sure?"
+msgstr "உறà¯à®¤à®¿à®¯à®¾à®• சொகிறீரà¯à®•ளா?"
+
+#: contrib/admin/views/main.py:533
+#, python-format
+msgid "Change history: %s"
+msgstr "வரலாறà¯à®±à¯ˆ மாறà¯à®±à¯: %s"
+
+#: contrib/admin/views/main.py:565
+#, python-format
+msgid "Select %s"
+msgstr "%s யை தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯"
+
+#: contrib/admin/views/main.py:565
+#, python-format
+msgid "Select %s to change"
+msgstr "%s யை மாறà¯à®± தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯"
+
+#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
+#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
+#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
+msgid "Integer"
+msgstr "à®®à¯à®´à¯ எணà¯"
+
+#: contrib/admin/views/doc.py:278
+msgid "Boolean (Either True or False)"
+msgstr "பூலியன௠(சரி அலà¯à®²à®¤à¯ தவறà¯)"
+
+#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
+#, python-format
+msgid "String (up to %(maxlength)s)"
+msgstr "உரை (%(maxlength)s வரைகà¯à®•à¯à®®à¯)"
+
+#: contrib/admin/views/doc.py:280
+msgid "Comma-separated integers"
+msgstr "கமாவாள௠பிரிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿ à®®à¯à®´à¯ எணà¯"
+
+#: contrib/admin/views/doc.py:281
+msgid "Date (without time)"
+msgstr "தேதி (நேரமிலà¯à®²à®¾à®®à®²à¯)"
+
+#: contrib/admin/views/doc.py:282
+msgid "Date (with time)"
+msgstr "தேதி (நேரமà¯à®Ÿà®©à¯)"
+
+#: contrib/admin/views/doc.py:283
+msgid "E-mail address"
+msgstr "மின௠அஞà¯à®šà®²à¯"
+
+#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
+msgid "File path"
+msgstr "கோபà¯à®ªà¯à®ªà¯ பாதை"
+
+#: contrib/admin/views/doc.py:285
+msgid "Decimal number"
+msgstr "பà¯à®³à¯à®³à®¿ எணà¯à®•ளà¯"
+
+#: contrib/admin/views/doc.py:291
+msgid "Boolean (Either True, False or None)"
+msgstr "இலகà¯à®•௠மà¯à®±à¯ˆ (சரி, தவற௠அலà¯à®²à®¤à¯ ஒனà¯à®±à¯à®®à¯ இலà¯à®²à¯ˆ)"
+
+#: contrib/admin/views/doc.py:292
+msgid "Relation to parent model"
+msgstr "ஆதி மாதிரிகà¯à®•௠தொடரà¯à®ªà¯à®Ÿà¯ˆà®¯à®¤à¯"
+
+#: contrib/admin/views/doc.py:293
+msgid "Phone number"
+msgstr "தொலைபேசி எணà¯"
+
+#: contrib/admin/views/doc.py:298
+msgid "Text"
+msgstr "உரை"
+
+#: contrib/admin/views/doc.py:299
+msgid "Time"
+msgstr "நேரமà¯"
+
+#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
+msgid "URL"
+msgstr "URL"
+
+#: contrib/admin/views/doc.py:301
+msgid "U.S. state (two uppercase letters)"
+msgstr "U.S. மாநிலம௠(இரணà¯à®Ÿà¯ மேல௠எழà¯à®¤à¯à®¤à¯à®µà®•ை எழà¯à®¤à¯à®¤à¯)"
+
+#: contrib/admin/views/doc.py:302
+msgid "XML text"
+msgstr "XML உரை"
+
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/registration/password_change_done.html:3
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+msgid "Documentation"
+msgstr "ஆவணமாகà¯à®•à®®à¯"
+
+# translation of django_ac.po to
+# translation of django_ac.po to tamil
+# Ashwin <ashwin@au-kbc.org>, 2006.
+# R Hariram Aatreya <rha@localhost.localdomain>, 2006.
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/base.html:23
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/registration/password_change_done.html:3
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/admin_doc/bookmarklets.html:4
+#: contrib/admin/templates/admin_doc/view_detail.html:4
+#: contrib/admin/templates/admin_doc/template_tag_index.html:5
+#: contrib/admin/templates/admin_doc/template_detail.html:4
+#: contrib/admin/templates/admin_doc/template_filter_index.html:5
+#: contrib/admin/templates/admin_doc/missing_docutils.html:4
+#: contrib/admin/templates/admin_doc/view_index.html:5
+#: contrib/admin/templates/admin_doc/model_detail.html:3
+#: contrib/admin/templates/admin_doc/index.html:4
+#: contrib/admin/templates/admin_doc/model_index.html:5
+msgid "Change password"
+msgstr "கடவà¯à®šà¯à®šà¯†à®¾à®²à¯à®²à¯ˆ மாறà¯à®±à¯ "
+
+#: contrib/admin/templates/admin/object_history.html:5
+#: contrib/admin/templates/admin/500.html:4
+#: contrib/admin/templates/admin/change_list.html:6
+#: contrib/admin/templates/admin/base.html:28
+#: contrib/admin/templates/admin/delete_confirmation.html:6
+#: contrib/admin/templates/admin/change_form.html:13
+#: contrib/admin/templates/registration/password_change_done.html:4
+#: contrib/admin/templates/registration/password_reset_form.html:4
+#: contrib/admin/templates/registration/logged_out.html:4
+#: contrib/admin/templates/registration/password_reset_done.html:4
+#: contrib/admin/templates/registration/password_change_form.html:4
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+msgid "Home"
+msgstr "வீடà¯"
+
+#: contrib/admin/templates/admin/object_history.html:5
+#: contrib/admin/templates/admin/change_form.html:20
+msgid "History"
+msgstr "வரலாறà¯"
+
+#: contrib/admin/templates/admin/object_history.html:18
+msgid "Date/time"
+msgstr "தேதி/நேரம௠"
+
+#: contrib/admin/templates/admin/object_history.html:19
+msgid "User"
+msgstr "பயனரà¯"
+
+#: contrib/admin/templates/admin/object_history.html:20
+msgid "Action"
+msgstr "செயலà¯"
+
+#: contrib/admin/templates/admin/object_history.html:26
+msgid "DATE_WITH_TIME_FULL"
+msgstr "தேதியà¯à®®à¯ à®®à¯à®´à¯ நேரமà¯à®®à¯"
+
+#: contrib/admin/templates/admin/object_history.html:36
+msgid ""
+"This object doesn't have a change history. It probably wasn't added via this "
+"admin site."
+msgstr ""
+"இநà¯à®¤ பொரà¯à®³à¯ மாறà¯à®± வரலாறà¯à®±à®¿à®²à¯ இலà¯à®²à¯ˆ"
+"ஒர௠வேளை நிரà¯à®µà®¾à®•தà¯à®¤à®³à®¤à¯à®¤à®¿à®©à¯ மூலம௠சேரà¯à®•à¯à®•பà¯à®ªà®Ÿà®¾à®®à®²à®¿à®°à¯à®•à¯à®•லாமà¯"
+
+#: contrib/admin/templates/admin/base_site.html:4
+msgid "Django site admin"
+msgstr "டிஜாஙà¯à®™à¯‹ தள நிரà¯à®µà®¾à®•ி"
+
+#: contrib/admin/templates/admin/base_site.html:7
+msgid "Django administration"
+msgstr "டிஜாஙà¯à®™à¯‹ நிரà¯à®µà®¾à®•ம௠"
+
+#: contrib/admin/templates/admin/500.html:4
+msgid "Server error"
+msgstr "சேவகன௠பிழை"
+
+#: contrib/admin/templates/admin/500.html:6
+msgid "Server error (500)"
+msgstr "சேவையகம௠தவறà¯(500)"
+
+#: contrib/admin/templates/admin/500.html:9
+msgid "Server Error <em>(500)</em>"
+msgstr "சேவையகம௠பிழை<em>(500)</em>"
+
+#: contrib/admin/templates/admin/500.html:10
+msgid ""
+"There's been an error. It's been reported to the site administrators via e-"
+"mail and should be fixed shortly. Thanks for your patience."
+msgstr ""
+"தவற௠à®à®±à¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯"
+"வலைதà¯à®¤à®³ நிரà¯à®µà®¾à®•ிகà¯à®•௠மினà¯à®©à®žà¯à®šà®²à¯ அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. விரைவில௠சரி செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®®à¯. உஙà¯à®•à¯à®³à®¤à¯ பொறà¯à®®à¯ˆà®•à¯à®•௠நனà¯à®±à®¿"
+
+#: contrib/admin/templates/admin/404.html:4
+#: contrib/admin/templates/admin/404.html:8
+msgid "Page not found"
+msgstr "பகà¯à®•தà¯à®¤à¯ˆ காணவிலà¯à®²à¯ˆ"
+
+#: contrib/admin/templates/admin/404.html:10
+msgid "We're sorry, but the requested page could not be found."
+msgstr ""
+"நீஙà¯à®•ள௠விரà¯à®®à¯à®ªà®¿à®¯ பகà¯à®•தà¯à®¤à¯ˆ காண இயலவிலà¯à®²à¯ˆ. "
+"அதறà¯à®•ாக வரà¯à®¨à¯à®¤à¯à®•ிறோமà¯."
+
+#: contrib/admin/templates/admin/index.html:17
+#, python-format
+msgid "Models available in the %(name)s application."
+msgstr "செயலியில௠கிடைகà¯à®•க௠கூடிய %(name)s மாதிரிகளà¯"
+
+#: contrib/admin/templates/admin/index.html:28
+#: contrib/admin/templates/admin/change_form.html:15
+msgid "Add"
+msgstr "சேரà¯"
+
+#: contrib/admin/templates/admin/index.html:34
+msgid "Change"
+msgstr "மாறà¯à®±à¯"
+
+#: contrib/admin/templates/admin/index.html:44
+msgid "You don't have permission to edit anything."
+msgstr "உஙà¯à®•ளà¯à®•à¯à®•௠மாறà¯à®±à¯à®µà®¤à®±à¯à®•௠உரிமையிலà¯à®²à¯ˆ"
+
+#: contrib/admin/templates/admin/index.html:52
+msgid "Recent Actions"
+msgstr "தறà¯à®ªà¯‹à®¤à¯ˆà®¯ செயலà¯à®•ளà¯"
+
+#: contrib/admin/templates/admin/index.html:53
+msgid "My Actions"
+msgstr "எனத௠செயலà¯à®•ளà¯"
+
+#: contrib/admin/templates/admin/index.html:57
+msgid "None available"
+msgstr "எதà¯à®µà¯à®®à¯ கிடைகà¯à®•விலà¯à®²à¯ˆ"
+
+#: contrib/admin/templates/admin/change_list.html:11
+#, python-format
+msgid "Add %(name)s"
+msgstr "%(name)s சேரà¯"
+
+#: contrib/admin/templates/admin/login.html:22
+msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
+msgstr "நீஙà¯à®•ள௠தஙà¯à®•ளத௠கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ <a href=\"/password_reset/\"> மறநà¯à®¤à¯ விடà¯à®Ÿà¯€à®°à¯à®•ளா?"
+
+#: contrib/admin/templates/admin/base.html:23
+msgid "Welcome,"
+msgstr "நலà¯à®µà®°à®µà¯,"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:9
+#: contrib/admin/templates/admin/submit_line.html:3
+msgid "Delete"
+msgstr "நீகà¯à®•à¯"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:14
+#, python-format
+msgid ""
+"Deleting the %(object_name)s '%(object)s' would result in deleting related "
+"objects, but your account doesn't have permission to delete the following "
+"types of objects:"
+msgstr "இநà¯à®¤ '%(object)s' இல௠%(object_name)s நீகà¯à®•à¯à®µà®¤à¯ தொடரà¯à®ªà¯à®Ÿà¯ˆà®¯ மறà¯à®±à®µà®±à¯à®±à¯ˆà®¯à¯à®®à¯ நீகà¯à®•à¯à®®à¯. ஆனால௠அதறà¯à®•௠உஙà¯à®•ளà¯à®•à¯à®•௠உரிமையிலà¯à®²à¯ˆ"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:21
+#, python-format
+msgid ""
+"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
+"the following related items will be deleted:"
+msgstr ""
+"நீஙà¯à®•ள௠இநà¯à®¤ \"%(object)s\" %(object_name)s நீகà¯à®•à¯à®µà®¤à®¿à®²à¯ நிசà¯à®šà®¯à®®à®¾?"
+"தொடரà¯à®ªà¯à®Ÿà¯ˆà®¯ மறà¯à®±à®µà¯ˆà®¯à¯à®®à¯ நீகà¯à®•பà¯à®ªà®Ÿà¯à®®à¯. "
+
+#: contrib/admin/templates/admin/delete_confirmation.html:26
+msgid "Yes, I'm sure"
+msgstr "ஆம௠எனகà¯à®•௠உறà¯à®¤à®¿ "
+
+#: contrib/admin/templates/admin/filter.html:2
+#, python-format
+msgid " By %(title)s "
+msgstr "%(title)s ஆல௠"
+
+#: contrib/admin/templates/admin/search_form.html:8
+msgid "Go"
+msgstr "செலà¯"
+
+#: contrib/admin/templates/admin/change_form.html:21
+msgid "View on site"
+msgstr "தளà¯à®¤à¯à®¤à®¿à®²à¯ பார௠"
+
+#: contrib/admin/templates/admin/change_form.html:30
+msgid "Please correct the error below."
+msgstr "கீழே உளà¯à®³ தவறà¯à®•ளைதà¯à®¤à®¿à®°à¯à®¤à¯à®¤à¯"
+
+#: contrib/admin/templates/admin/change_form.html:48
+msgid "Ordering"
+msgstr "வரிசைபà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®¤à®²à¯"
+
+#: contrib/admin/templates/admin/change_form.html:51
+msgid "Order:"
+msgstr "வரிசைபà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯"
+
+#: contrib/admin/templates/admin/submit_line.html:4
+msgid "Save as new"
+msgstr "பà¯à®¤à®¿à®¯à®¤à®¾à®• சேமி"
+
+#: contrib/admin/templates/admin/submit_line.html:5
+msgid "Save and add another"
+msgstr "சேமிதà¯à®¤à¯ இனà¯à®©à¯à®®à¯Šà®©à¯à®±à¯ˆà®šà¯ சேரà¯"
+
+#: contrib/admin/templates/admin/submit_line.html:6
+msgid "Save and continue editing"
+msgstr "சேமிதà¯à®¤à¯ மாறà¯à®±à®¤à¯à®¤à¯ˆ தொடரà¯à®•"
+
+#: contrib/admin/templates/admin/submit_line.html:7
+msgid "Save"
+msgstr "சேமி"
+
+#: contrib/admin/templates/registration/password_change_done.html:4
+#: contrib/admin/templates/registration/password_change_form.html:4
+#: contrib/admin/templates/registration/password_change_form.html:6
+#: contrib/admin/templates/registration/password_change_form.html:10
+msgid "Password change"
+msgstr "கடவà¯à®šà¯à®šà¯Šà®²à¯ மாறà¯à®±à®®à¯"
+
+#: contrib/admin/templates/registration/password_change_done.html:6
+#: contrib/admin/templates/registration/password_change_done.html:10
+msgid "Password change successful"
+msgstr "கடவà¯à®šà¯à®šà¯Šà®²à¯ மாறà¯à®±à®®à¯ வெறà¯à®±à®¿ "
+
+#: contrib/admin/templates/registration/password_change_done.html:12
+msgid "Your password was changed."
+msgstr "உஙà¯à®•ள௠கடவà¯à®šà¯à®šà¯Šà®²à¯ மாறà¯à®±à®ªà¯ படà¯à®Ÿà¯à®³à¯à®³à®¤à¯"
+
+#: contrib/admin/templates/registration/password_reset_form.html:4
+#: contrib/admin/templates/registration/password_reset_form.html:6
+#: contrib/admin/templates/registration/password_reset_form.html:10
+#: contrib/admin/templates/registration/password_reset_done.html:4
+msgid "Password reset"
+msgstr "கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மாறà¯à®±à®¿à®¯à®®à¯ˆ"
+
+#: contrib/admin/templates/registration/password_reset_form.html:12
+msgid ""
+"Forgotten your password? Enter your e-mail address below, and we'll reset "
+"your password and e-mail the new one to you."
+msgstr ""
+"கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மறநà¯à®¤à¯ விடà¯à®Ÿà®¾à®²à¯"
+"உஙà¯à®•ளத௠மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•வரியை உளà¯à®³à®¿à®Ÿà¯à®•"
+"அதன௠பிறக௠உஙà¯à®•ள௠கடவà¯à®šà¯à®šà¯Šà®²à¯ மாறà¯à®±à®¿à®¯à®®à¯ˆà®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà¯ "
+"உஙà¯à®•ளத௠மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•வரிகà¯à®•௠அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®®à¯"
+
+#: contrib/admin/templates/registration/password_reset_form.html:16
+msgid "E-mail address:"
+msgstr "மினà¯à®…ஞà¯à®šà®²à¯ à®®à¯à®•வரி:"
+
+#: contrib/admin/templates/registration/password_reset_form.html:16
+msgid "Reset my password"
+msgstr "எனத௠கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மாறà¯à®±à®¿à®¯à®®à¯ˆ"
+
+#: contrib/admin/templates/registration/logged_out.html:8
+msgid "Thanks for spending some quality time with the Web site today."
+msgstr ""
+"வலைதà¯à®¤à®³à®¤à¯à®¤à®¿à®²à¯ உஙà¯à®•ளத௠பொனà¯à®©à®¾à®© நேரதà¯à®¤à¯ˆ "
+"செலவழிதà¯à®¤à®®à¯ˆà®•à¯à®•௠மிகà¯à®¨à¯à®¤ நனà¯à®±à®¿"
+
+#: contrib/admin/templates/registration/logged_out.html:10
+msgid "Log in again"
+msgstr "மீணà¯à®Ÿà¯à®®à¯ உளà¯à®³à¯‡ பதிவ௠செயà¯à®¯à®µà¯à®®à¯"
+
+#: contrib/admin/templates/registration/password_reset_done.html:6
+#: contrib/admin/templates/registration/password_reset_done.html:10
+msgid "Password reset successful"
+msgstr "கடவà¯à®šà¯à®šà¯Šà®²à¯ மாறà¯à®±à®¿à®¯à®®à¯ˆà®¤à¯à®¤à®²à¯ வெறà¯à®±à®¿"
+
+#: contrib/admin/templates/registration/password_reset_done.html:12
+msgid ""
+"We've e-mailed a new password to the e-mail address you submitted. You "
+"should be receiving it shortly."
+msgstr ""
+"கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மறநà¯à®¤à¯ விடà¯à®Ÿà®¾à®²à¯"
+"உஙà¯à®•ளத௠மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•வரியை உளà¯à®³à®¿à®Ÿà¯à®•"
+"பà¯à®¤à®¿à®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯ "
+"உஙà¯à®•ளத௠மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•வரிகà¯à®•௠அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. விரைவில௠அத௠உஙà¯à®•ளà¯à®•à¯à®•௠கிடைகà¯à®•à¯à®®à¯"
+
+#: contrib/admin/templates/registration/password_change_form.html:12
+msgid ""
+"Please enter your old password, for security's sake, and then enter your new "
+"password twice so we can verify you typed it in correctly."
+msgstr "பாதà¯à®•ாபà¯à®ªà¯ காரணஙà¯à®•ளà¯à®•à¯à®•ாக , à®®à¯à®¤à®²à®¿à®²à¯ உஙà¯à®•ளத௠பழைய கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ உளà¯à®³à®¿à®Ÿà¯à®•. அதன௠பிறக௠பà¯à®¤à®¿à®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ இர௠மà¯à®±à¯ˆ உளà¯à®³à®¿à®Ÿà¯à®•. இத௠உஙà¯à®•ளத௠உளà¯à®³à®¿à®Ÿà¯à®¤à®²à¯ˆ சரிபாரà¯à®•à¯à®• உதவà¯à®®à¯. "
+
+#: contrib/admin/templates/registration/password_change_form.html:17
+msgid "Old password:"
+msgstr "பழைய கடவà¯à®šà¯à®šà¯Šà®²à¯ :"
+
+#: contrib/admin/templates/registration/password_change_form.html:19
+msgid "New password:"
+msgstr "பà¯à®¤à®¿à®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯:"
+
+#: contrib/admin/templates/registration/password_change_form.html:21
+msgid "Confirm password:"
+msgstr "கடவà¯à®šà¯à®šà¯Šà®²à¯ மாறà¯à®±à®¤à¯à®¤à¯ˆ உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯:"
+
+#: contrib/admin/templates/registration/password_change_form.html:23
+msgid "Change my password"
+msgstr "கடவà¯à®šà¯ சொலà¯à®²à¯ˆ மாறà¯à®±à®µà¯à®®à¯"
+
+#: contrib/admin/templates/registration/password_reset_email.html:2
+msgid "You're receiving this e-mail because you requested a password reset"
+msgstr "கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மாறà¯à®±à®¿à®¯à®®à¯ˆà®•à¯à®• நீஙà¯à®•ள௠கேடà¯à®Ÿà®¤à®©à®¾à®²à¯ உஙà¯à®•ளà¯à®•à¯à®•௠இநà¯à®¤ மினà¯à®©à®žà¯à®šà®²à¯ அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯"
+
+#: contrib/admin/templates/registration/password_reset_email.html:3
+#, python-format
+msgid "for your user account at %(site_name)s"
+msgstr "%(site_name)s -இல௠உளà¯à®³ உஙà¯à®•ளத௠பயனாளர௠கணகà¯à®•à¯"
+
+#: contrib/admin/templates/registration/password_reset_email.html:5
+#, python-format
+msgid "Your new password is: %(new_password)s"
+msgstr "உஙà¯à®•ளத௠பà¯à®¤à®¿à®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯ : %(new_password)s "
+
+#: contrib/admin/templates/registration/password_reset_email.html:7
+msgid "Feel free to change this password by going to this page:"
+msgstr "கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மாறà¯à®±à®¿à®¯à®®à¯ˆà®•à¯à®• நீஙà¯à®•ள௠இநà¯à®¤ பகà¯à®•தà¯à®¤à®¿à®±à¯à®•௠தாராளமாக போகலாமà¯."
+
+#: contrib/admin/templates/registration/password_reset_email.html:11
+msgid "Your username, in case you've forgotten:"
+msgstr "உஙà¯à®•ளத௠பயனாளர௠பெயரà¯, (நீஙà¯à®•ள௠மறநà¯à®¤à®¿à®°à¯à®¨à¯à®¤à®¾à®²à¯ ): "
+
+#: contrib/admin/templates/registration/password_reset_email.html:13
+msgid "Thanks for using our site!"
+msgstr "எஙà¯à®•ளத௠வலைதà¯à®¤à®³à®¤à¯à®¤à¯ˆ பயன௠படà¯à®¤à¯à®¤à®¿à®¯à®¤à®±à¯à®•௠மிகà¯à®¨à¯à®¤ நனà¯à®±à®¿"
+
+#: contrib/admin/templates/registration/password_reset_email.html:15
+#, python-format
+msgid "The %(site_name)s team"
+msgstr "இநà¯à®¤ %(site_name)s -இன௠கà¯à®´à¯ "
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+msgid "Bookmarklets"
+msgstr "பà¯à®¤à¯à®¤à®•கà¯à®•à¯à®±à®¿à®•ளà¯"
+
+# translation of django_ad.po to
+# translation of django_ad.po to
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# aukbc-guest, 2006.
+# R Hariram Aatreya <rha@localhost.localdomain>, 2006.
+#: contrib/admin/templates/admin_doc/bookmarklets.html:5
+msgid "Documentation bookmarklets"
+msgstr "ஆவணமாகà¯à®•க௠கà¯à®±à®¿à®¯à¯€à®Ÿà¯"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:9
+msgid ""
+"\n"
+"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n"
+"toolbar, or right-click the link and add it to your bookmarks. Now you can\n"
+"select the bookmarklet from any page in the site. Note that some of these\n"
+"bookmarklets require you to be viewing the site from a computer designated\n"
+"as \"internal\" (talk to your system administrator if you aren't sure if\n"
+"your computer is \"internal\").</p>\n"
+msgstr ""
+"\n"
+"<p class=\"help\"> பà¯à®¤à¯à®¤à®• கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®•ளை நிறà¯à®µ இநà¯à®¤ இணைபà¯à®ªà®¿à®©à¯ˆ பà¯à®¤à¯à®¤à®•கà¯à®•à¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà¯à®ªà¯ \n"
+"படà¯à®Ÿà¯ˆà®•à¯à®•௠இழà¯à®•à¯à®•வà¯à®®à¯. அலà¯à®²à®¤à¯ வலத௠கிிளிக செயà¯à®¤à¯ பà¯à®¤à¯à®¤à®•கà¯à®•à¯à®±à®¿à®¯à¯€à®Ÿà¯à®•ளில௠சேரà¯à®•à¯à®•வà¯à®®à¯. \n"
+" இனி தளதà¯à®¤à®¿à®²à¯ எநà¯à®¤à®ªà¯ பகà¯à®•தà¯à®¤à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯à®®à¯ பà¯à®¤à¯à®¤à®•கà¯à®•à¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà®¿à®©à¯ˆ தேரà¯à®µà¯à®šà¯†à®¯à¯à®¯ à®®à¯à®Ÿà®¿à®¯à¯à®®à¯. \n"
+" நீஙà¯à®•ள௠இநà¯à®¤ தளதà¯à®¤à¯ˆ \"internal\" என கà¯à¯à®±à®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ கணிணியில௠இரà¯à®¨à¯à®¤à¯ மடà¯à®Ÿà¯à®®à¯‡ \n"
+" à®’à®°à¯à®šà®¿à®² பà¯à®¤à¯à®¤à®•கà¯à®•à¯à®±à®¿à®•ளை செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®®à¯à®Ÿà®¿à®¯à¯à®®à¯\n "
+" உஙà¯à®•ளà¯à®•à¯à®•à¯, கணிணி \"internal\" என உறà¯à®¤à®¿ செயà¯à®¯ கணிணிமேளாலரை அணà¯à®•வà¯à®®à¯.</p>\n"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:19
+msgid "Documentation for this page"
+msgstr "இநà¯à®¤ பகà¯à®•தà¯à®¤à®¿à®±à¯à®•ான ஆவணமà¯"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:20
+msgid ""
+"Jumps you from any page to the documentation for the view that generates "
+"that page."
+msgstr "எநà¯à®¤ ஒர௠பகà¯à®•தà¯à®¤à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯à®®à¯ ஆவணபà¯à®ªà®•à¯à®•தà¯à®¤à¯ˆ பாரà¯à®µà¯ˆà®¯à®¿à®Ÿà¯à®¤à®²à¯, அநà¯à®¤ பகà¯à®•தà¯à®¤à¯ˆ உரà¯à®µà®¾à®•à¯à®•à¯à®•ிறதà¯."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:22
+msgid "Show object ID"
+msgstr "object ID-஠காடà¯à®Ÿà¯"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:23
+msgid ""
+"Shows the content-type and unique ID for pages that represent a single "
+"object."
+msgstr "ஒரே object-஠கà¯à®±à®¿à®•à¯à®•à¯à®®à¯ பகà¯à®•à®™à¯à®•ளின௠பொரà¯à®³à®Ÿà®•à¯à®• வகை மறà¯à®±à¯à®®à¯ unique ID-஠காடà¯à®Ÿà¯à®•ிறதà¯."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:25
+msgid "Edit this object (current window)"
+msgstr "இதை திரà¯à®¤à¯à®¤à¯à®• (தறà¯à®ªà¯‹à®¤à¯ˆà®¯ சாளரமà¯)"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:26
+msgid "Jumps to the admin page for pages that represent a single object."
+msgstr "ஒரே object-஠கà¯à®±à®¿à®•à¯à®•à¯à®®à¯ பகà¯à®•à®™à¯à®•ளைக௠காண மேலாளர௠பகà¯à®•தà¯à®¤à®¿à®±à¯à®•௠செலà¯à®•."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:28
+msgid "Edit this object (new window)"
+msgstr "இதை திரà¯à®¤à¯à®¤à¯à®•. (பà¯à®¤à®¿à®¯ சாளரமà¯)"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:29
+msgid "As above, but opens the admin page in a new window."
+msgstr "மேளாலர௠பகà¯à®•தà¯à®¤à¯ˆ à®®à¯à®©à¯à®ªà¯ கணà¯à®Ÿà®¤à¯à®ªà¯‹à®²à¯, ஆனால௠பà¯à®¤à®¿à®¯ சாளரதà¯à®¤à®¿à®²à¯ திறகà¯à®•ிறதà¯."
+
+#: contrib/admin/templates/widget/date_time.html:3
+msgid "Date:"
+msgstr "தேதி:"
+
+#: contrib/admin/templates/widget/date_time.html:4
+msgid "Time:"
+msgstr "நேரமà¯:"
+
+#: contrib/admin/templates/widget/file.html:2
+msgid "Currently:"
+msgstr "தறà¯à®ªà¯‹à®¤à¯:"
+
+#: contrib/admin/templates/widget/file.html:3
+msgid "Change:"
+msgstr "மாறà¯à®±à¯:"
+
+#: contrib/redirects/models.py:7
+msgid "redirect from"
+msgstr "லிரà¯à®¨à¯à®¤à¯ திசைமாறà¯à®±à¯"
+
+#: contrib/redirects/models.py:8
+msgid ""
+"This should be an absolute path, excluding the domain name. Example: '/"
+"events/search/'."
+msgstr ""
+"இத௠ஒர௠மà¯à®´à¯à®®à¯ˆà®¯à®¾à®© பாதையாக இரà¯à®•à¯à®•வேணà¯à®Ÿà¯à®®à¯. "
+"இணையதà¯à®¤à®³à®ªà¯à®ªà¯†à®¯à®°à®¾à®• இரà¯à®•à¯à®•கà¯à®•ூடாதà¯. உதாரணமà¯:'/"
+"events/search/'."
+
+#: contrib/redirects/models.py:9
+msgid "redirect to"
+msgstr "திரà¯à®®à¯à®ª அனà¯à®ªà¯à®ªà¯"
+
+#: contrib/redirects/models.py:10
+msgid ""
+"This can be either an absolute path (as above) or a full URL starting with "
+"'http://'."
+msgstr "இத௠மà¯à®´à¯à®®à¯ˆà®¯à®¾à®© பாதையாக (மேலே உளà¯à®³à®¤à¯ போல) அலà¯à®²à®¤à¯ \"http\"//\" என தொடஙà¯à®•à¯à®®à¯ வலை à®®à¯à®•வரியாக இரà¯à®•à¯à®•லாமà¯."
+
+#: contrib/redirects/models.py:12
+msgid "redirect"
+msgstr "திரà¯à®®à¯à®ª அனà¯à®ªà¯à®ªà¯"
+
+#: contrib/redirects/models.py:13
+msgid "redirects"
+msgstr "திரà¯à®®à¯à®ª அனà¯à®ªà¯à®ªà¯à®•ிறதà¯. "
+
+#: contrib/flatpages/models.py:8
+msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes."
+msgstr "உதாரணமà¯: '/about/contact/'. à®®à¯à®©à¯à®©à¯à®®à¯ பினà¯à®©à¯à®®à¯ '/' உளà¯à®³à®¤à¯ˆ உறà¯à®¤à®¿ செயà¯à®•. "
+
+#: contrib/flatpages/models.py:9
+msgid "title"
+msgstr "தலைபà¯à®ªà¯"
+
+#: contrib/flatpages/models.py:10
+msgid "content"
+msgstr "பொரà¯à®³à®Ÿà®•à¯à®•à®®à¯"
+
+#: contrib/flatpages/models.py:11
+msgid "enable comments"
+msgstr "விமரà¯à®šà®©à®™à¯à®•ளை செயலாகà¯à®•à¯"
+
+#: contrib/flatpages/models.py:12
+msgid "template name"
+msgstr "வாரà¯à®ªà¯à®ªà¯à®°à¯ பெயரà¯"
+
+#: contrib/flatpages/models.py:13
+msgid ""
+"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
+"use 'flatpages/default'."
+msgstr "உதாரணம௠'flatpages/contact_page'. இத௠இலà¯à®²à¯ˆà®¯à¯†à®©à®¿à®²à¯ 'flatpages/default' எனà¯à®ªà®¤à¯‡ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®®à¯.பà¯à®ªà®Ÿà¯à®®à¯."
+
+#: contrib/flatpages/models.py:14
+msgid "registration required"
+msgstr "à®®à¯à®©à¯à®ªà®¤à®¿à®µà¯ தேவை"
+
+#: contrib/flatpages/models.py:14
+msgid "If this is checked, only logged-in users will be able to view the page."
+msgstr "இத௠தெரிவ௠செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®¨à¯à®¤à®¾à®²à¯, உளà¯à®¨à¯à®´à¯ˆà®¨à¯à®¤ பயனரà¯à®•ள௠மடà¯à®Ÿà¯à®®à¯‡ இநà¯à®¤à®ªà¯ பகà¯à®•தà¯à®¤à¯ˆ பாரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à¯à®®à¯."
+
+#: contrib/flatpages/models.py:18
+msgid "flat page"
+msgstr "எளிய பகà¯à®•à®®à¯"
+
+#: contrib/flatpages/models.py:19
+msgid "flat pages"
+msgstr "எளிய பகà¯à®•à®™à¯à®•ளà¯"
+
+#: contrib/auth/models.py:13 contrib/auth/models.py:26
+msgid "name"
+msgstr "பெயரà¯"
+
+#: contrib/auth/models.py:15
+msgid "codename"
+msgstr "கà¯à®±à®¿à®®à¯à®±à¯ˆ பெயரà¯"
+
+#: contrib/auth/models.py:17
+msgid "permission"
+msgstr "அனà¯à®®à®¤à®¿"
+
+#: contrib/auth/models.py:18 contrib/auth/models.py:27
+msgid "permissions"
+msgstr "அனà¯à®®à®¤à®¿à®•ளà¯"
+
+#: contrib/auth/models.py:29
+msgid "group"
+msgstr "கà¯à®´à¯"
+
+#: contrib/auth/models.py:30 contrib/auth/models.py:65
+msgid "groups"
+msgstr "கà¯à®´à¯à®•à¯à®•ளà¯"
+
+#: contrib/auth/models.py:55
+msgid "username"
+msgstr "பயனர௠பெயரà¯"
+
+#: contrib/auth/models.py:56
+msgid "first name"
+msgstr "à®®à¯à®¤à®²à¯ பெயரà¯"
+
+#: contrib/auth/models.py:57
+msgid "last name"
+msgstr "கடைசி பெயரà¯"
+
+#: contrib/auth/models.py:58
+msgid "e-mail address"
+msgstr "மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•வரி"
+
+#: contrib/auth/models.py:59
+msgid "password"
+msgstr "கடவà¯à®šà¯à®šà¯Šà®²à¯"
+
+#: contrib/auth/models.py:59
+msgid "Use '[algo]$[salt]$[hexdigest]'"
+msgstr "பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯ '[algo]$[salt]$[hexdigest]'"
+
+#: contrib/auth/models.py:60
+msgid "staff status"
+msgstr "பணியாளர௠நிலை"
+
+#: contrib/auth/models.py:60
+msgid "Designates whether the user can log into this admin site."
+msgstr "பயனரà¯, 'மேலாளலரà¯' பகà¯à®•தà¯à®¤à®¿à®²à¯ நà¯à®´à¯ˆà¯à®´à¯ˆà®µà®¤à¯ˆ à®®à¯à®Ÿà®¿à®µà¯ செயà¯à®•ிறத௠"
+
+#: contrib/auth/models.py:61
+msgid "active"
+msgstr "செயலà¯à®ªà®Ÿà¯à®®à¯"
+
+#: contrib/auth/models.py:62
+msgid "superuser status"
+msgstr "மேலாளர௠இரà¯à®ªà¯à®ªà¯ நிலை"
+
+#: contrib/auth/models.py:63
+msgid "last login"
+msgstr "கடைசி உளà¯à®¨à¯à®´à¯ˆà®µà¯"
+
+#: contrib/auth/models.py:64
+msgid "date joined"
+msgstr "சேரà¯à®¨à¯à®¤ தேதி"
+
+#: contrib/auth/models.py:66
+msgid ""
+"In addition to the permissions manually assigned, this user will also get "
+"all permissions granted to each group he/she is in."
+msgstr "பயனர௠தனத௠அனà¯à®®à®¤à®¿à®•ளோட௠,தான௠உளà¯à®³ கà¯à®´à¯à®µà®¿à®©à®¤à¯ அனà¯à®®à®¤à®¿à®•ளைையà¯à®®à¯ பெறà¯à®µà®¾à®°à¯."
+
+#: contrib/auth/models.py:67
+msgid "user permissions"
+msgstr "பயனர௠அனà¯à®®à®¤à®¿à®•ளà¯"
+
+#: contrib/auth/models.py:70
+msgid "user"
+msgstr "பயனரà¯"
+
+#: contrib/auth/models.py:71
+msgid "users"
+msgstr "பயனரà¯à®•ளà¯"
+
+#: contrib/auth/models.py:76
+msgid "Personal info"
+msgstr "தனிபà¯à®ªà®Ÿà¯à®Ÿ விவரமà¯"
+
+#: contrib/auth/models.py:77
+msgid "Permissions"
+msgstr "அனà¯à®®à®¤à®¿à®•ளà¯"
+
+#: contrib/auth/models.py:78
+msgid "Important dates"
+msgstr "à®®à¯à®•à¯à®•ியமான தேதிகளà¯"
+
+#: contrib/auth/models.py:79
+msgid "Groups"
+msgstr "கà¯à®´à¯à®•à¯à®•ளà¯"
+
+#: contrib/auth/models.py:219
+msgid "message"
+msgstr "செயà¯à®¤à®¿"
+
+#: contrib/auth/forms.py:30
+msgid ""
+"Your Web browser doesn't appear to have cookies enabled. Cookies are "
+"required for logging in."
+msgstr " உஙà¯à®•ள௠இணைய உலாவியில௠கà¯à®•à¯à®•ிகள௠செயலாகà¯à®•ம௠பெறவிலà¯à®²à¯ˆ. உளà¯à®¨à¯à®´à¯ˆà®µà®¤à®±à¯à®•à¯à®•௠கà¯à®•à¯à®•ிகள௠அவசியமà¯."
+
+#: contrib/contenttypes/models.py:25
+msgid "python model class name"
+msgstr "python model class name"
+
+#: contrib/contenttypes/models.py:28
+msgid "content type"
+msgstr "பொரà¯à®³à®Ÿà®•à¯à®• வகை "
+
+#: contrib/contenttypes/models.py:29
+msgid "content types"
+msgstr "பொரà¯à®³à®Ÿà®•à¯à®• வகைகளà¯"
+
+#: contrib/sessions/models.py:35
+msgid "session key"
+msgstr "அமரà¯à®µà¯ கà¯à®±à®¿à®¯à¯€"
+
+#: contrib/sessions/models.py:36
+msgid "session data"
+msgstr "அமரà¯à®µà¯ தகவலà¯"
+
+#: contrib/sessions/models.py:37
+msgid "expire date"
+msgstr "காலாவதியாகà¯à®®à¯ தேதி"
+
+#: contrib/sessions/models.py:41
+msgid "session"
+msgstr "அமரà¯à®µà¯"
+
+#: contrib/sessions/models.py:42
+msgid "sessions"
+msgstr "அமரà¯à®µà¯à®•ளà¯"
+
+#: contrib/sites/models.py:10
+msgid "domain name"
+msgstr "களப௠பெயரà¯"
+
+#: contrib/sites/models.py:11
+msgid "display name"
+msgstr "காடà¯à®Ÿà¯à®®à¯ பெயரà¯"
+
+#: contrib/sites/models.py:15
+msgid "site"
+msgstr "வலைதà¯à®¤à®³à®®à¯"
+
+#: contrib/sites/models.py:16
+msgid "sites"
+msgstr "வலைதà¯à®¤à®³à®™à¯à®•ளà¯"
+
+#: utils/translation.py:360
+msgid "DATE_FORMAT"
+msgstr "தேதி வடிவமà¯"
+
+#: utils/translation.py:361
+msgid "DATETIME_FORMAT"
+msgstr "தேதிநேர வடிவமà¯"
+
+# translation of django_ae.po to
+# translation of django_ae.po to
+# R Hariram Aatreya <rha@localhost.localdomain>, 2006.
+#: utils/translation.py:362
+msgid "TIME_FORMAT"
+msgstr "நேரதà¯à®¤à®¿à®©à¯ அமைபà¯à®ªà¯à®®à¯"
+
+#: utils/dates.py:6
+msgid "Monday"
+msgstr "திஙà¯à®•ளà¯"
+
+#: utils/dates.py:6
+msgid "Tuesday"
+msgstr "செவà¯à®µà®¾à®¯à¯"
+
+#: utils/dates.py:6
+msgid "Wednesday"
+msgstr "பà¯à®¤à®©à¯"
+
+#: utils/dates.py:6
+msgid "Thursday"
+msgstr "வியாழனà¯"
+
+#: utils/dates.py:6
+msgid "Friday"
+msgstr "வெளà¯à®³à®¿"
+
+#: utils/dates.py:7
+msgid "Saturday"
+msgstr "சனி"
+
+#: utils/dates.py:7
+msgid "Sunday"
+msgstr "ஞாயிறà¯"
+
+#: utils/dates.py:14
+msgid "January"
+msgstr "ஜனவரி"
+
+#: utils/dates.py:14
+msgid "February"
+msgstr "பிபà¯à®°à®µà®°à®¿"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "March"
+msgstr "மாரà¯à®šà¯"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "April"
+msgstr "à®à®ªà¯à®°à®²à¯"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "May"
+msgstr "மே"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "June"
+msgstr "ஜூனà¯"
+
+#: utils/dates.py:15 utils/dates.py:27
+msgid "July"
+msgstr "ஜூலை"
+
+#: utils/dates.py:15
+msgid "August"
+msgstr "ஆகஸà¯à®Ÿà¯"
+
+#: utils/dates.py:15
+msgid "September"
+msgstr "செபà¯à®Ÿà®®à¯à®ªà®°à¯"
+
+#: utils/dates.py:15
+msgid "October"
+msgstr "அகà¯à®Ÿà¯‹à®ªà®°à¯"
+
+#: utils/dates.py:15
+msgid "November"
+msgstr "நவமà¯à®ªà®°à¯"
+
+#: utils/dates.py:16
+msgid "December"
+msgstr "டிசமà¯à®ªà®°à¯"
+
+#: utils/dates.py:19
+msgid "jan"
+msgstr "ஜன"
+
+#: utils/dates.py:19
+msgid "feb"
+msgstr "பிபà¯"
+
+#: utils/dates.py:19
+msgid "mar"
+msgstr "மாரà¯"
+
+#: utils/dates.py:19
+msgid "apr"
+msgstr "à®à®ªà¯"
+
+#: utils/dates.py:19
+msgid "may"
+msgstr "மே"
+
+#: utils/dates.py:19
+msgid "jun"
+msgstr "ஜூனà¯"
+
+#: utils/dates.py:20
+msgid "jul"
+msgstr "ஜூலை"
+
+#: utils/dates.py:20
+msgid "aug"
+msgstr "ஆக"
+
+#: utils/dates.py:20
+msgid "sep"
+msgstr "செபà¯"
+
+#: utils/dates.py:20
+msgid "oct"
+msgstr "அகà¯"
+
+#: utils/dates.py:20
+msgid "nov"
+msgstr "நவ"
+
+#: utils/dates.py:20
+msgid "dec"
+msgstr "டிச"
+
+#: utils/dates.py:27
+msgid "Jan."
+msgstr "ஜன."
+
+#: utils/dates.py:27
+msgid "Feb."
+msgstr "பிபà¯."
+
+#: utils/dates.py:28
+msgid "Aug."
+msgstr "ஆக."
+
+#: utils/dates.py:28
+msgid "Sept."
+msgstr "செபà¯."
+
+#: utils/dates.py:28
+msgid "Oct."
+msgstr "அகà¯."
+
+#: utils/dates.py:28
+msgid "Nov."
+msgstr "நவ."
+
+#: utils/dates.py:28
+msgid "Dec."
+msgstr "டிச."
+
+#: utils/timesince.py:12
+msgid "year"
+msgstr "வரà¯à®Ÿà®®à¯"
+
+#: utils/timesince.py:13
+msgid "month"
+msgstr "மாதமà¯"
+
+#: utils/timesince.py:14
+msgid "week"
+msgstr "வாரமà¯"
+
+#: utils/timesince.py:15
+msgid "day"
+msgstr "நாளà¯"
+
+#: utils/timesince.py:16
+msgid "hour"
+msgstr "மணி"
+
+#: utils/timesince.py:17
+msgid "minute"
+msgstr "நிமிடமà¯"
+
+#: conf/global_settings.py:37
+msgid "Bengali"
+msgstr "பெஙà¯à®•ாலி"
+
+#: conf/global_settings.py:38
+msgid "Czech"
+msgstr "செகà¯"
+
+#: conf/global_settings.py:39
+msgid "Welsh"
+msgstr "வெலà¯à®¸à¯"
+
+#: conf/global_settings.py:40
+msgid "Danish"
+msgstr "டேனிஷà¯"
+
+#: conf/global_settings.py:41
+msgid "German"
+msgstr "ஜெரà¯à®®à®©à¯"
+
+#: conf/global_settings.py:42
+msgid "Greek"
+msgstr "கிரேகà¯à®•à®®à¯"
+
+#: conf/global_settings.py:43
+msgid "English"
+msgstr "ஆஙà¯à®•ிலமà¯"
+
+#: conf/global_settings.py:44
+msgid "Spanish"
+msgstr "ஸà¯à®ªà®¾à®©à®¿à®·à¯"
+
+#: conf/global_settings.py:45
+msgid "French"
+msgstr "பà¯à®°à¯†à®©à¯à®šà¯"
+
+#: conf/global_settings.py:46
+msgid "Galician"
+msgstr "கலீஷீயனà¯"
+
+#: conf/global_settings.py:47
+msgid "Hungarian"
+msgstr "ஹஙà¯à®•ேரியனà¯"
+
+#: conf/global_settings.py:48
+msgid "Hebrew"
+msgstr "ஹீபà¯à®°à¯"
+
+#: conf/global_settings.py:49
+msgid "Icelandic"
+msgstr "à®à®¸à¯à®²à®¾à®©à¯à®Ÿà®¿à®•à¯"
+
+#: conf/global_settings.py:50
+msgid "Italian"
+msgstr "இதà¯à®¤à®¾à®²à®¿à®¯à®©à¯"
+
+#: conf/global_settings.py:51
+msgid "Japanese"
+msgstr "ஜபà¯à®ªà®¾à®©à®¿à®¯"
+
+#: conf/global_settings.py:52
+msgid "Dutch"
+msgstr "டசà¯à®šà¯"
+
+#: conf/global_settings.py:53
+msgid "Norwegian"
+msgstr "நாரà¯à®µà¯€à®šà®¿à®¯à®©à¯"
+
+#: conf/global_settings.py:54
+msgid "Brazilian"
+msgstr "பிரேசிலியனà¯"
+
+#: conf/global_settings.py:55
+msgid "Romanian"
+msgstr "ரோமானியனà¯"
+
+#: conf/global_settings.py:56
+msgid "Russian"
+msgstr "à®°à®·à¯à®¯à®©à¯"
+
+#: conf/global_settings.py:57
+msgid "Slovak"
+msgstr "சà¯à®²à¯‹à®µà®¾à®•à¯"
+
+#: conf/global_settings.py:58
+msgid "Slovenian"
+msgstr "ஸà¯à®²à¯‹à®µà¯‡à®©à®¿à®¯à®©à¯"
+
+#: conf/global_settings.py:59
+msgid "Serbian"
+msgstr "செரà¯à®ªà®¿à®¯à®©à¯"
+
+#: conf/global_settings.py:60
+msgid "Swedish"
+msgstr "சà¯à®µà®¿à®Ÿà®¿à®·à¯"
+
+#: conf/global_settings.py:61
+msgid "Ukrainian"
+msgstr "உகà¯à®°à¯‡à®©à®¿à®¯à®©à¯"
+
+#: conf/global_settings.py:62
+msgid "Simplified Chinese"
+msgstr "எளிய சீன மொழி"
+
+#: conf/global_settings.py:63
+msgid "Traditional Chinese"
+msgstr "மரப௠சீன மொழி"
+
+#: core/validators.py:60
+msgid "This value must contain only letters, numbers and underscores."
+msgstr "இநà¯à®¤ மதிபà¯à®ªà¯ எழà¯à®¤à¯à®¤à¯à®•ள௠எணà¯à®•ள௠அனà¯à®Ÿà®°à¯à®¸à¯à®•ோர௠மறà¯à®±à¯à®®à¯ உளà¯à®³à®Ÿà®•à¯à®• வேணà¯à®Ÿà¯à®®à¯ "
+
+#: core/validators.py:64
+msgid ""
+"This value must contain only letters, numbers, underscores, dashes or "
+"slashes."
+msgstr "இநà¯à®¤ மதிபà¯à®ªà¯ எழà¯à®¤à¯à®¤à¯à®•ள௠எணà¯à®•ள௠அனà¯à®Ÿà®°à¯à®¸à¯à®•ோர௠டஷ௠அலà¯à®²à®¤à¯ சலஷ௠மறà¯à®±à¯à®®à¯ உளà¯à®³à®Ÿà®•à¯à®• வேணà¯à®Ÿà¯à®®à¯"
+
+#: core/validators.py:72
+msgid "Uppercase letters are not allowed here."
+msgstr "பெரிய எழà¯à®¤à¯à®¤à¯à®•ளà¯à®•à¯à®•௠இஙà¯à®•௠அனà¯à®®à®¤à®¿ இலà¯à®²à¯ˆ இலà¯à®²à¯ˆ."
+
+#: core/validators.py:76
+msgid "Lowercase letters are not allowed here."
+msgstr "சிறிய ய எழà¯à®¤à¯à®¤à¯à®•ளà¯à®•à¯à®•௠இஙà¯à®•௠அனà¯à®®à®¤à®¿ இலà¯à®²à¯ˆ"
+
+# translation of django_af.po to
+# translation of django_af.po to
+# translation of django_af.po to
+# translation of django_af.po to
+# translation of django_af.po to
+# translation of django_af.po to
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# , 2006.
+# R Hariram Aatreya <rha@localhost.localdomain>, 2006.
+#: core/validators.py:83
+msgid "Enter only digits separated by commas."
+msgstr "காறà¯à®ªà¯à®³à¯à®³à®¿à®•ளால௠தனிமைபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®¯ இலகà¯à®•ஙகள மடà¯à®Ÿà¯à®®à¯ எழà¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:95
+msgid "Enter valid e-mail addresses separated by commas."
+msgstr "காறà¯à®ªà¯à®³à¯à®³à®¿à®•ளால௠தனிமைபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®¯ à®®à¯à®±à¯ˆà®¯à®¾à®© e à®®à¯à®•வரிகளà¯à¯ மடà¯à®Ÿà¯à®®à¯ எழà¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:99
+msgid "Please enter a valid IP address."
+msgstr "தயவ௠செயà¯à®¤à¯ à®®à¯à®±à¯ˆà®¯à®¾à®© à®.பி à®®à¯à®•வறி மடà¯à®Ÿà¯à®®à¯ எழà¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:103
+msgid "Empty values are not allowed here."
+msgstr "காலியான மதிபà¯à®ªà¯à®•à¯à®•ள௠அனà¯à®®à®¤à®¿Â à®‡à®²à¯à®²à¯ˆ"
+
+#: core/validators.py:107
+msgid "Non-numeric characters aren't allowed here."
+msgstr "எண௠வடிவமிலà¯à®²à®¾à®¤ எழà¯à®¤à¯à®¤à¯à®•à¯à®•ள௠அனà¯à®®à®¤à®¿Â à®‡à®²à¯à®²à¯ˆ"
+
+#: core/validators.py:111
+msgid "This value can't be comprised solely of digits."
+msgstr "இநà¯à®¤ மதிபà¯à®ªà¯ இலகà¯à®•à®™à¯à®•ள௠மடà¯à®Ÿà¯à®®à¯‡ கொணà¯à®Ÿà®¤à®¾à®• இரà¯à®•à¯à®• கூடாதà¯"
+
+#: core/validators.py:116
+msgid "Enter a whole number."
+msgstr "à®®à¯à®´à¯ எண௠மடà¯à®Ÿà¯à®®à¯‡ எழà¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:120
+msgid "Only alphabetical characters are allowed here."
+msgstr "அகர வரிசை எழà¯à®¤à¯à®¤à¯à®•à¯à®•ள௠மடà¯à®Ÿà¯à®®à¯‡ அனà¯à®®à®¤à®¿ உனà¯à®Ÿà¯"
+
+#: core/validators.py:124
+msgid "Enter a valid date in YYYY-MM-DD format."
+msgstr "வவவவ-மாமா-நாநா எனà¯à®± அமைபà¯à®ªà®¿à®²à¯ உளà¯à®³ à®®à¯à®±à¯ˆà®¯à®¾à®© தேதி மடà¯à®Ÿà¯à®®à¯‡ எழà¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:128
+msgid "Enter a valid time in HH:MM format."
+msgstr "மம-நிநி எனà¯à®± அமைபà¯à®ªà®¿à®²à¯ உளà¯à®³ à®®à¯à®±à¯ˆà®¯à®¾à®© நேரம௠மடà¯à®Ÿà¯à®®à¯‡ எழà¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:132 db/models/fields/__init__.py:468
+msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
+msgstr "வவவவ-மாமா-நாநா மம-நிநி எனà¯à®± அமைபà¯à®ªà®¿à®²à¯ உளà¯à®³ à®®à¯à®±à¯ˆà®¯à®¾à®© தேதி/நேரம௠மடà¯à®Ÿà¯à®®à¯‡ எழà¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:136
+msgid "Enter a valid e-mail address."
+msgstr "à®®à¯à®±à¯ˆà®¯à®¾à®© e à®®à¯à®•வரிகளà¯à¯ மடà¯à®Ÿà¯à®®à¯ எழà¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:148
+msgid ""
+"Upload a valid image. The file you uploaded was either not an image or a "
+"corrupted image."
+msgstr "à®®à¯à®±à¯ˆà®¯à®¾à®© படம௠மடà¯à®Ÿà¯à®®à¯‡ பதிவேறà¯à®±à®®à¯ செயà¯à®¯à®µà¯à®®à¯. நீஙà¯à®•ள௠பதிவேறà¯à®±à®®à¯ செயà¯à®¤ கோபà¯à®ªà¯ படம௠அளà¯à®³à®¾à®¤ அளà¯à®³à®¤à¯ கெடà¯à®Ÿà¯à®ªà¯à®ªà¯‹à®© கோபà¯à®ªà®¾à®•à¯à®®à¯"
+
+#: core/validators.py:155
+#, python-format
+msgid "The URL %s does not point to a valid image."
+msgstr "%s எனà¯à®± இணையதள à®®à¯à®•வறி சறியான படதà¯à®¤à¯ˆà®šà¯ சà¯à®Ÿà¯à®Ÿà®µà®¿à®²à¯à®²à¯ˆ"
+
+#: core/validators.py:159
+#, python-format
+msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
+msgstr "தொலைபேசி எணà¯à®•ள௠XXX-XXX-XXXX எனà¯à®± அமைபà¯à®ªà®¿à®²à¯ இரà¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯. \"%s\" எனà¯à®ªà®¤à¯ à®®à¯à®±à¯ˆà®¯à®³à¯à®³"
+
+#: core/validators.py:167
+#, python-format
+msgid "The URL %s does not point to a valid QuickTime video."
+msgstr "%s எனà¯à®± இணையதள à®®à¯à®•வறி à®®à¯à®±à¯ˆà®¯à®¾à®© கà¯à®¯à®¿à®•௠டைம௠படகà¯à®•ாடà¯à®šà®¿à®¯à¯ˆà®šà¯ சà¯à®Ÿà¯à®Ÿà®µà®¿à®²à¯à®²à¯ˆ"
+
+#: core/validators.py:171
+msgid "A valid URL is required."
+msgstr "à®®à¯à®±à¯ˆà®¯à®¾à®© இணையதள à®®à¯à®•வறி தேவை"
+
+#: core/validators.py:185
+#, python-format
+msgid ""
+"Valid HTML is required. Specific errors are:\n"
+"%s"
+msgstr ""
+"à®®à¯à®±à¯ˆà®¯à®¾à®© இணையதள à®®à¯à®•வறி தேவை. கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®¤à¯à®¤à®•à¯à®•த௠தவறà¯à®•ளாவன:\n"
+"%s"
+
+#: core/validators.py:192
+#, python-format
+msgid "Badly formed XML: %s"
+msgstr "à®®à¯à®±à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà®¾à®¤ XML: %s"
+
+#: core/validators.py:202
+#, python-format
+msgid "Invalid URL: %s"
+msgstr "à®®à¯à®±à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà®¾à®¤ இணையதள à®®à¯à®•வறி: %s"
+
+#: core/validators.py:206 core/validators.py:208
+#, python-format
+msgid "The URL %s is a broken link."
+msgstr "%s எனà¯à®± இணையதள à®®à¯à®•வறி உடைநà¯à®¤à¯à®³à¯à®³à®¤à¯"
+
+#: core/validators.py:214
+msgid "Enter a valid U.S. state abbreviation."
+msgstr "à®®à¯à®±à¯ˆà®¯à®¾à®© U.S மாநில பெயர௠சà¯à®°à¯à®•à¯à®•ம௠எழà¯à®¤à®µà¯à®®à¯à®´à¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:229
+#, python-format
+msgid "Watch your mouth! The word %s is not allowed here."
+msgstr "வாரà¯à®¤à¯à®¤à¯ˆà®•ளை அளனà¯à®¤à¯ பேசà¯à®™à¯à®•ளà¯. %s எனà¯à®± வாரà¯à®¤à¯à®¤à¯ˆ இஙà¯à®•௠அனà¯à®®à®¤à®¿ இலà¯à®²à¯ˆ"
+
+#: core/validators.py:236
+#, python-format
+msgid "This field must match the '%s' field."
+msgstr "இநà¯à®¤ பà¯à®²à®®à¯ %s எனà¯à®± பà¯à®²à®¤à¯à®¤à¯à®Ÿà®©à¯ ஒதà¯à®¤à®¿à®±à¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯"
+
+#: core/validators.py:255
+msgid "Please enter something for at least one field."
+msgstr "தயவ௠செயà¯à®¤à¯ ஒர௠பà¯à®²à®¤à¯à®¤à®¿à®²à®¾à®µà®¤à¯ à®à®¤à®¾à®µà®¤à¯ எழà¯à®¤à®µà¯à®®à¯"
+
+#: core/validators.py:264 core/validators.py:275
+msgid "Please enter both fields or leave them both empty."
+msgstr "தயவ௠செயà¯à®¤à¯ இரà¯à¯à®ªà¯à®²à®™à¯à®•லையà¯à®®à¯à¯à®®à¯ நிரபà¯à®ªà®µà¯à®®à¯; அலà¯à®²à®¤à¯ இரணà¯à®Ÿà¯ˆà®¯à¯à®®à¯ காலியாக விடவà¯à®®à¯"
+
+#: core/validators.py:282
+#, python-format
+msgid "This field must be given if %(field)s is %(value)s"
+msgstr "%(field)s, %(value)s ஆக இரà¯à®¨à¯à®¤à®¾à®²à¯ இனà¯à®¤ பà¯à®²à®®à¯ இரà¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯"
+
+#: core/validators.py:294
+#, python-format
+msgid "This field must be given if %(field)s is not %(value)s"
+msgstr "%(field)s, %(value)s ஆக இலà¯à®²à¯ˆ எனà¯à®±à®¾à®²à¯ இனà¯à®¤ பà¯à®²à®®à¯ இரà¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯"
+
+#: core/validators.py:313
+msgid "Duplicate values are not allowed."
+msgstr "போலியான மதிபà¯à®ªà¯à®•ள௠அனà¯à®®à®¤à®¿ இலà¯à®²à¯ˆ"
+
+#: core/validators.py:336
+#, python-format
+msgid "This value must be a power of %s."
+msgstr "இநà¯à®¤ மதிபà¯à®ªà¯ %s இன௠அடà¯à®•à¯à®•ாக இரà¯à®•à¯à®• வேனà¯à®Ÿà¯à®®à¯"
+
+#: core/validators.py:347
+msgid "Please enter a valid decimal number."
+msgstr "தயவà¯à®šà¯†à®¯à¯à®¤à¯ à®®à¯à®±à¯ˆà®¯à®¾à®© பதினà¯à®® எணà¯à®£à¯ˆ நழைகà¯à®•cவà¯à®®à¯"
+
+#: core/validators.py:349
+#, python-format
+msgid ""
+"Please enter a valid decimal number with at most %s total digit."
+"Please enter a valid decimal number with at most %s total digits."
+msgstr ""
+"அதிகபடà¯à®šà®®à¯ %s எணà¯à®£à¯ˆ உளà¯à®³ பதினà¯à®® எணà¯à®£à¯ˆ நà¯à®´à¯ˆ."
+"அதிகபடà¯à®šà®®à¯ %s எணà¯à®•ள௠உளà¯à®³ பதினà¯à®® எணà¯à®£à¯ˆ நà¯à®´à¯ˆ."
+
+#: core/validators.py:352
+#, python-format
+msgid ""
+"Please enter a valid decimal number with at most %s decimal place."
+"Please enter a valid decimal number with at most %s decimal places."
+msgstr ""
+"அதிகபடà¯à®šà®®à¯ %s பà¯à®³à¯à®³à®¿ இடம௠ள௠உளà¯à®³ பதினà¯à®® எணà¯à¯ˆ நà¯à®´à¯ˆ"
+"அதிகபடà¯à®šà®®à¯ %s பà¯à®³à¯à®³à®¿ இடஙà¯à®•ள௠உளà¯à®³ பதினà¯à®® எணà¯à¯ˆ நà¯à®´à¯ˆ"
+
+#: core/validators.py:362
+#, python-format
+msgid "Make sure your uploaded file is at least %s bytes big."
+msgstr "மேலà¯à®à®±à¯à®±à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿ கோபà¯à®ªà¯ கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®šà®®à¯ %s பைடà¯à®Ÿà¯à®•ள௠உளà¯à®³à®©à®µà®¾ என சரி பாரà¯à®•à¯à®•வà¯à®®à¯"
+
+#: core/validators.py:363
+#, python-format
+msgid "Make sure your uploaded file is at most %s bytes big."
+msgstr "மேலà¯à®à®±à¯à®±à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿ கோபà¯à®ªà¯ அதிகபடà¯à®šà®®à¯ %s பைடà¯à®Ÿà¯à®•ள௠உளà¯à®³à®©à®µà®¾ என சரி பாரà¯à®•à¯à®•வà¯à®®à¯."
+
+#: core/validators.py:376
+msgid "The format for this field is wrong."
+msgstr "பà¯à®²à®©à¯à®Ÿà¯ˆà®¯ அமைபà¯à®ªà¯ தவறà¯"
+
+#: core/validators.py:391
+msgid "This field is invalid."
+msgstr "இநà¯à®¤ பà¯à®²à®®à¯ செலà¯à®²à®¾à®¤à¯."
+
+#: core/validators.py:426
+#, python-format
+msgid "Could not retrieve anything from %s."
+msgstr "%s இரà¯à®¨à¯à®¤à¯ எதà¯à®µà¯à®®à¯ எடà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ"
+
+#: core/validators.py:429
+#, python-format
+msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
+msgstr "வலைமனை %(url)s எனà¯à®ªà®¤à¯ செலà¯à®²à®¾à®¤ உளà¯à®³à®Ÿà®•à¯à®•-வகை தலைபà¯à®ªà®¾à®© '%(contenttype)s' ஠திரà¯à®ªà¯à®ªà®¿ தநà¯à®¤à¯à®³à¯à®³à®¤à¯."
+
+#: core/validators.py:462
+#, python-format
+msgid ""
+"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
+"\"%(start)s\".)"
+msgstr " %(line)s கோட௠லிரà¯à®¨à¯à®¤à¯ மூடாத %(tag)s டாகை மூடà¯. ( வரி,\"%(start)s\"வà¯à®Ÿà®©à¯ தà¯à®µà®™à¯à®•à¯à®•ினà¯à®±à®¤à¯)"
+
+#: core/validators.py:466
+#, python-format
+msgid ""
+"Some text starting on line %(line)s is not allowed in that context. (Line "
+"starts with \"%(start)s\".)"
+msgstr "வரி %(line)s இல௠உளà¯à®³ சில உரைகள௠இரà¯à®ªà¯à®ªà®¤à®±à¯à®•௠அனà¯à®®à®¤à®¿ இலà¯à®²à¯ˆ.( வரி,\"%(start)s\"வà¯à®Ÿà®©à¯ தà¯à®µà®™à¯à®•à¯à®•ினà¯à®±à®¤à¯)"
+
+#: core/validators.py:471
+#, python-format
+msgid ""
+"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
+"(start)s\".)"
+msgstr "வரி %(line)s இல௠உளà¯à®³ \"%(attr)s\" எனà¯à®ªà®¤à¯ தவறான பணà¯à®ªà®¾à®•à¯à®®.( வரி,\"%(start)s\"வà¯à®Ÿà®©à¯ தà¯à®µà®™à¯à®•à¯à®•ினà¯à®±à®¤à¯)"
+
+#: core/validators.py:476
+#, python-format
+msgid ""
+"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
+"(start)s\".)"
+msgstr "வரி %(line)s இல௠உளà¯à®³ \"<%(tag)s>\" எனà¯à®ªà®¤à¯ தவறான ஒடà¯à®Ÿà®¾à®•à¯à®®à¯ .( வரி,\"%(start)s\"வà¯à®Ÿà®©à¯ தà¯à®µà®™à¯à®•à¯à®•ினà¯à®±à®¤à¯)"
+
+#: core/validators.py:480
+#, python-format
+msgid ""
+"A tag on line %(line)s is missing one or more required attributes. (Line "
+"starts with \"%(start)s\".)"
+msgstr "வரி %(line)s இல௠உளà¯à®³ ஒடà¯à®Ÿà¯ இன பணà¯à®ªà¯à®•ள௠தேவைபà¯à®ªà®Ÿà¯à®•ினà¯à®±à®©.(வரி,\"%(start)s\" வà¯à®Ÿà®©à¯ தà¯à®µà®™à¯à®•à¯à®•ினà¯à®±à®¤à¯)"
+
+#: core/validators.py:485
+#, python-format
+msgid ""
+"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
+"starts with \"%(start)s\".)"
+msgstr "வரி %(line)s இல௠உளà¯à®³ \"%(attr)s\" பணà¯à®ªà®¿à®©à¯ மதிபà¯à®ªà¯ தவறானதà¯.(வரி \"%(start)s\" இரà¯à®¨à¯à®¤à¯ ஆரமà¯à®ªà®®à¯)"
+
+#: db/models/manipulators.py:302
+#, python-format
+#, fuzzy
+msgid "%(object)s with this %(type)s already exists for the given %(field)s."
+msgstr "%(type)s உடன௠உளà¯à®³ %(object)s உளà¯à®³à®¤à¯"
+
+#: db/models/fields/__init__.py:40
+#, python-format
+msgid "%(optname)s with this %(fieldname)s already exists."
+msgstr "%(fieldname)s உடன௠உளà¯à®³ %(optname)s உயிரà¯à®Ÿà®© உளà¯à®³à®¤à¯"
+
+#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
+#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
+#: forms/__init__.py:346
+msgid "This field is required."
+msgstr "இநà¯à®¤ பà¯à®²à®¤à¯à®¤à®¿à®²à¯ மதிபà¯à®ªà¯ தேவை"
+
+#: db/models/fields/__init__.py:337
+msgid "This value must be an integer."
+msgstr "இநà¯à®¤ மதிபà¯à®ªà¯ à®®à¯à®´à¯à®µà¯†à®£à¯à®£à®¾à®• இரà¯à®•à¯à®• வேணà¯à®Ÿà¯à®®"
+
+#: db/models/fields/__init__.py:369
+msgid "This value must be either True or False."
+msgstr "இநà¯à®¤ மதிபà¯à®ªà¯ சரி அலà¯à®²à®¤à¯ தவறாக இரà¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯"
+
+#: db/models/fields/__init__.py:385
+msgid "This field cannot be null."
+msgstr "இநà¯à®¤ பà¯à®²à®®à¯ காலியாக இரà¯à®•à¯à®•க௠கூடாதà¯"
+
+#: db/models/fields/__init__.py:562
+msgid "Enter a valid filename."
+msgstr "à®®à¯à®±à¯ˆà®¯à®¾à®© கோபà¯à®ªà¯à®ªà¯ பெயரை எழà¯à®¤à®µà¯à®®à¯"
+
+#: db/models/fields/related.py:43
+#, python-format
+msgid "Please enter a valid %s."
+msgstr "தயவ௠செயà¯à®¤à¯ à®®à¯à®±à¯ˆà®¯à®¾à®© %s எழà¯à®¤à®µà¯à®®à¯"
+
+#: db/models/fields/related.py:579
+msgid "Separate multiple IDs with commas."
+msgstr "பனà¯à®®à¯ˆà®¯à®¿à®²à¯à®³à¯à®³ அடையாளஙà¯à®•ளை காறà¯à®ªà¯à®³à¯à®³à®¿à®•ளால௠பிரிகà¯à®•வà¯à®®à¯"
+
+#: db/models/fields/related.py:581
+msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
+msgstr "Mac இலà¯, ஒனà¯à®±à¯à®•à¯à®•௠மேறà¯à®ªà®Ÿà¯à®Ÿà®µà®±à¯à®±à¯ˆ தேரà¯à®µà¯ செயà¯à®¯ \"Control\" அலà¯à®²à®¤à¯ \"Command\" à® à®…à®´à¯à®¤à¯à®¤à®µà¯à®®à¯"
+
+#: db/models/fields/related.py:625
+#, python-format
+msgid ""
+"Please enter valid %(self)s IDs. The value %(value)r is invalid."
+"Please enter valid %(self)s IDs. The values %(value)r are invalid."
+msgstr ""
+"தயவ௠செயà¯à®¤à¯ à®®à¯à®±à¯ˆà®¯à®¾à®© %(self)s அடையாளஙà¯à®•ளை எழà¯à®¤à®µà¯à®®à¯. %(value)r எனà¯à®± மதிபà¯à®ªà¯ à®®à¯à®±à¯ˆà®¯à®¾à®©à®¤à®²à¯à®². "
+"தயவ௠செயà¯à®¤à¯ à®®à¯à®±à¯ˆà®¯à®¾à®© %(self)s அடையாளஙà¯à®•ளை எழà¯à®¤à®µà¯à®®à¯. %(value)r எனà¯à®± மதிபà¯à®ªà¯à®•ள௠மà¯à®±à¯ˆà®¯à®¾à®©à®¤à®²à¯à®². "
+
+#: forms/__init__.py:380
+#, python-format
+msgid "Ensure your text is less than %s character."
+msgstr "உஙà¯à®•ள௠உரை %s ஠விட கà¯à®±à¯ˆà®µà®¾à®© எழà¯à®¤à¯à®¤à¯à®•à¯à®•ளை உடையதென உறà¯à®¤à®¿ செயà¯à®¤à¯ கொளà¯à®³à¯à®™à¯à®•ளà¯"
+
+#: forms/__init__.py:385
+msgid "Line breaks are not allowed here."
+msgstr "வரி உடைவà¯à®•ள௠அனà¯à®®à®¤à®¿ இலà¯à®²à¯ˆ"
+
+#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
+#, python-format
+msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
+msgstr "à®®à¯à®±à¯ˆà®¯à®¾à®© விரà¯à®ªà¯à®ªà®¤à¯à®¤à¯ˆ தேரà¯à®µà¯ செயà¯à®¯à®µà¯à®®à¯; '%(data)s எனà¯à®ªà®¤à¯ %(choices)s இல௠இலà¯à®²à¯ˆ"
+
+#: forms/__init__.py:645
+msgid "The submitted file is empty."
+msgstr "சமரà¯à®ªà®¿à®•à¯à®•ப௠படà¯à®Ÿ கோபà¯à®ªà¯ காலியாக உளà¯à®³à®¤à¯"
+
+#: forms/__init__.py:699
+msgid "Enter a whole number between -32,768 and 32,767."
+msgstr "-32,768 மறà¯à®±à¯à®®à¯ 32,767 க௠நடà¯à®µà®¿à®²à¯ ஒர௠மà¯à®´à¯ எணà¯à®£à¯ˆ எழà¯à®¤à®µà¯à®®à¯"
+
+#: forms/__init__.py:708
+msgid "Enter a positive number."
+msgstr "ஒர௠நேரà¯à®•à¯à®•à¯à®±à®¿Â à®Žà®£à¯à®£à¯ˆ எழà¯à®¤à®µà¯à®®à¯"
+
+#: forms/__init__.py:717
+msgid "Enter a whole number between 0 and 32,767."
+msgstr "0 மறà¯à®±à¯à®®à¯ 32,767 க௠நடà¯à®µà®¿à®²à¯ ஒர௠மà¯à®´à¯ எணà¯à®£à¯ˆ எழà¯à®¤à®µà¯à®®à¯"
+
+#: template/defaultfilters.py:379
+msgid "yes,no,maybe"
+msgstr "ஆமà¯, இலà¯à®²à¯ˆ, இரà¯à®•à¯à®•லாமà¯"
+
diff --git a/django/conf/locale/tr/LC_MESSAGES/django.mo b/django/conf/locale/tr/LC_MESSAGES/django.mo
new file mode 100644
index 0000000000..2415d26ee9
--- /dev/null
+++ b/django/conf/locale/tr/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/tr/LC_MESSAGES/django.po b/django/conf/locale/tr/LC_MESSAGES/django.po
new file mode 100644
index 0000000000..daa299ca66
--- /dev/null
+++ b/django/conf/locale/tr/LC_MESSAGES/django.po
@@ -0,0 +1,2209 @@
+# translation of django.po to Turkish
+# Django 0.95
+# Copyright (C) 2006 Django
+# This file is distributed under the same license as the Django package.
+#
+# Bahadır Kandemir <bahadir@pardus.org.tr>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: django\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-10-01 21:09+0300\n"
+"PO-Revision-Date: 2006-10-01 21:19+0300\n"
+"Last-Translator: Bahadır Kandemir <bahadir@pardus.org.tr>\n"
+"Language-Team: Turkish <bahadir@pardus.org.tr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: db/models/manipulators.py:305
+#, python-format
+msgid "%(object)s with this %(type)s already exists for the given %(field)s."
+msgstr "%(type)s ve %(field)s değerine sahip %(object)s kaydı zaten var."
+
+#: db/models/manipulators.py:332
+#, python-format
+msgid ""
+"Please enter a different %s. The one you entered is already being used for %"
+"s."
+msgstr "Lütfen farklı bir %s girin. Girdiğiniz, %s tarihinde bir kez kullanılmış."
+
+#: db/models/fields/__init__.py:41
+#, python-format
+msgid "%(optname)s with this %(fieldname)s already exists."
+msgstr "%(fieldname)s için %(optname)s değeri zaten seçilmiş."
+
+#: db/models/fields/__init__.py:115 db/models/fields/__init__.py:266
+#: db/models/fields/__init__.py:560 db/models/fields/__init__.py:571
+#: forms/__init__.py:347
+msgid "This field is required."
+msgstr "Bu alan gerekli."
+
+#: db/models/fields/__init__.py:349
+msgid "This value must be an integer."
+msgstr "Bu değer tamsayı olmalı."
+
+#: db/models/fields/__init__.py:381
+msgid "This value must be either True or False."
+msgstr "Bu deÄŸer True ya da False olabilir."
+
+#: db/models/fields/__init__.py:397
+msgid "This field cannot be null."
+msgstr "Bu alan boş bırakılamaz."
+
+#: db/models/fields/__init__.py:424 core/validators.py:146
+msgid "Enter a valid date in YYYY-MM-DD format."
+msgstr "YYYY-AA-GG formatında tarih girin."
+
+#: db/models/fields/__init__.py:486 core/validators.py:155
+msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
+msgstr "YYYY-AA-GG SS:DD formatında tarih girin."
+
+#: db/models/fields/__init__.py:580
+msgid "Enter a valid filename."
+msgstr "Geçerli bir dosya adı girin."
+
+#: db/models/fields/related.py:51
+#, python-format
+msgid "Please enter a valid %s."
+msgstr "Lütfen geçerli bir %s girin."
+
+#: db/models/fields/related.py:618
+msgid "Separate multiple IDs with commas."
+msgstr "Birden fazla numarayı virgül ile ayırın."
+
+#: db/models/fields/related.py:620
+msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
+msgstr ""
+"\"Ctrl\" ve Mac'de \"Command\" tuşunu basılı tutarak birden fazla seçimde "
+"bulunabilirsiniz."
+
+#: db/models/fields/related.py:664
+#, python-format
+msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
+msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid."
+msgstr[0] "Lütfen geçerli bir %(self)s numarası girin. %(value)r değeri geçersiz."
+msgstr[1] "Lütfen geçerli %(self)s numaraları girin. %(value)r değerleri geçersiz."
+
+#: conf/global_settings.py:39
+msgid "Arabic"
+msgstr "Arapça"
+
+#: conf/global_settings.py:40
+msgid "Bengali"
+msgstr "Bengali Dili"
+
+#: conf/global_settings.py:41
+msgid "Czech"
+msgstr "Çekçe"
+
+#: conf/global_settings.py:42
+msgid "Welsh"
+msgstr "Galce"
+
+#: conf/global_settings.py:43
+msgid "Danish"
+msgstr "Danca"
+
+#: conf/global_settings.py:44
+msgid "German"
+msgstr "Almanca"
+
+#: conf/global_settings.py:45
+msgid "Greek"
+msgstr "Yunanca"
+
+#: conf/global_settings.py:46
+msgid "English"
+msgstr "İngilizce"
+
+#: conf/global_settings.py:47
+msgid "Spanish"
+msgstr "İspanyolca"
+
+#: conf/global_settings.py:48
+msgid "Argentinean Spanish"
+msgstr "Arjantin İspanyolcası"
+
+#: conf/global_settings.py:49
+msgid "Finnish"
+msgstr "Fince"
+
+#: conf/global_settings.py:50
+msgid "French"
+msgstr "Fransızca"
+
+#: conf/global_settings.py:51
+msgid "Galician"
+msgstr "Galler Dili"
+
+#: conf/global_settings.py:52
+msgid "Hungarian"
+msgstr "Macarca"
+
+#: conf/global_settings.py:53
+msgid "Hebrew"
+msgstr "İbranice"
+
+#: conf/global_settings.py:54
+msgid "Icelandic"
+msgstr "İzlanda dili"
+
+#: conf/global_settings.py:55
+msgid "Italian"
+msgstr "İtalyanca"
+
+#: conf/global_settings.py:56
+msgid "Japanese"
+msgstr "Japonca"
+
+#: conf/global_settings.py:57
+msgid "Dutch"
+msgstr "Flamanca"
+
+#: conf/global_settings.py:58
+msgid "Norwegian"
+msgstr "Norveç Dili"
+
+#: conf/global_settings.py:59
+msgid "Brazilian"
+msgstr "Brezilya Dili"
+
+#: conf/global_settings.py:60
+msgid "Romanian"
+msgstr "Romence"
+
+#: conf/global_settings.py:61
+msgid "Russian"
+msgstr "Rusça"
+
+#: conf/global_settings.py:62
+msgid "Slovak"
+msgstr "Slovakça"
+
+#: conf/global_settings.py:63
+msgid "Slovenian"
+msgstr "Slovence"
+
+#: conf/global_settings.py:64
+msgid "Serbian"
+msgstr "Sırpça"
+
+#: conf/global_settings.py:65
+msgid "Swedish"
+msgstr "İsveççe"
+
+#: conf/global_settings.py:66
+msgid "Tamil"
+msgstr "Tamilce"
+
+#: conf/global_settings.py:67
+msgid "Turkish"
+msgstr "Türkçe"
+
+#: conf/global_settings.py:68
+msgid "Ukrainian"
+msgstr "Ukraynaca"
+
+#: conf/global_settings.py:69
+msgid "Simplified Chinese"
+msgstr "Basiteştirilmiş Çince"
+
+#: conf/global_settings.py:70
+msgid "Traditional Chinese"
+msgstr "Gelenelsek Çince"
+
+#: forms/__init__.py:382
+#, python-format
+msgid "Ensure your text is less than %s character."
+msgid_plural "Ensure your text is less than %s characters."
+msgstr[0] "Metnin %s karakterden az olmasına dikkat edin."
+msgstr[1] "Metnin %s karakterden az olmasına dikkat edin."
+
+#: forms/__init__.py:387
+msgid "Line breaks are not allowed here."
+msgstr "Burada birden fazla satır olamaz."
+
+#: forms/__init__.py:488 forms/__init__.py:561 forms/__init__.py:600
+#, python-format
+msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
+msgstr "Geçerli bir seçimde bulunun; %(choices)s değerleri içinde '%(data)s' yok."
+
+#: forms/__init__.py:662 core/validators.py:172 core/validators.py:401
+msgid "No file was submitted. Check the encoding type on the form."
+msgstr "Dosya gönderilmedi. Formdaki kodlama türünü kontrol edin."
+
+#: forms/__init__.py:664
+msgid "The submitted file is empty."
+msgstr "Gönderilen dosya boş."
+
+#: forms/__init__.py:720
+msgid "Enter a whole number between -32,768 and 32,767."
+msgstr "-32,768 ve 32,767 arası bir sayı girin."
+
+#: forms/__init__.py:730
+msgid "Enter a positive number."
+msgstr "Pozitif tamsayı girin."
+
+#: forms/__init__.py:740
+msgid "Enter a whole number between 0 and 32,767."
+msgstr "0 ve 32,767 arası bir sayı girin."
+
+#: core/validators.py:63
+msgid "This value must contain only letters, numbers and underscores."
+msgstr "Bu değer sadece karakter, rakam ve altçizgiden oluşabilir."
+
+#: core/validators.py:67
+msgid ""
+"This value must contain only letters, numbers, underscores, dashes or "
+"slashes."
+msgstr "Bu değer sadece harf, rakam, altçizgi, bölü ve ters bölüden oluşabilir."
+
+#: core/validators.py:71
+msgid "This value must contain only letters, numbers, underscores or hyphens."
+msgstr "Bu değer sadece harf, rakam, altçizgi veya çizgiden oluşabilir."
+
+#: core/validators.py:75
+msgid "Uppercase letters are not allowed here."
+msgstr "Burada büyük harf kullanılamaz."
+
+#: core/validators.py:79
+msgid "Lowercase letters are not allowed here."
+msgstr "Burada küçük harf kullanılamaz."
+
+#: core/validators.py:86
+msgid "Enter only digits separated by commas."
+msgstr "Sadece virgülle ayrılmış sayılar girin."
+
+#: core/validators.py:98
+msgid "Enter valid e-mail addresses separated by commas."
+msgstr "Virgülle ayrılmış geçerli e-posta adresleri girin."
+
+#: core/validators.py:102
+msgid "Please enter a valid IP address."
+msgstr "Lütfen geçerli bir IP adresi girin."
+
+#: core/validators.py:106
+msgid "Empty values are not allowed here."
+msgstr "Burada boş değer kullanılamaz."
+
+#: core/validators.py:110
+msgid "Non-numeric characters aren't allowed here."
+msgstr "Burada numerik olmayan karakterler kullanılamaz."
+
+#: core/validators.py:114
+msgid "This value can't be comprised solely of digits."
+msgstr "Bu alanda sadece rakam kullanılamaz."
+
+#: core/validators.py:119
+msgid "Enter a whole number."
+msgstr "Sayı girin."
+
+#: core/validators.py:123
+msgid "Only alphabetical characters are allowed here."
+msgstr "Burada sadece alfabetik karakterler kullanılabilir."
+
+#: core/validators.py:138
+msgid "Year must be 1900 or later."
+msgstr "Yıl 1900 ya da sonrası olabilir."
+
+#: core/validators.py:142
+#, python-format
+msgid "Invalid date: %s."
+msgstr "Geçersiz tarih: %s"
+
+#: core/validators.py:151
+msgid "Enter a valid time in HH:MM format."
+msgstr "SS:DD formatında geçerli bir saat girin."
+
+#: core/validators.py:160
+msgid "Enter a valid e-mail address."
+msgstr "Geçerli bir e-posta adresi girin."
+
+#: core/validators.py:176
+msgid ""
+"Upload a valid image. The file you uploaded was either not an image or a "
+"corrupted image."
+msgstr ""
+"Geçerli bir resim girin. Gönderdiğiniz dosya resim değil, ya da bozuk bir "
+"dosya."
+
+#: core/validators.py:183
+#, python-format
+msgid "The URL %s does not point to a valid image."
+msgstr "%s adresi geçerli bir resme işaret etmiyor."
+
+#: core/validators.py:187
+#, python-format
+msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
+msgstr "Telefon numarası XXX-XXX-XXXX formatında olmalı. \"%s\" geçersiz."
+
+#: core/validators.py:195
+#, python-format
+msgid "The URL %s does not point to a valid QuickTime video."
+msgstr "%s adresi geçerli bir QuickTime dosyasına işaret etmiyor."
+
+#: core/validators.py:199
+msgid "A valid URL is required."
+msgstr "Geçerli bir URL gerekli."
+
+#: core/validators.py:213
+#, python-format
+msgid ""
+"Valid HTML is required. Specific errors are:\n"
+"%s"
+msgstr ""
+"Metnin geçerli bir HTML kodu olması gerekir. Hatalar:\n"
+"%s"
+
+#: core/validators.py:220
+#, python-format
+msgid "Badly formed XML: %s"
+msgstr "Geçersiz XML kodu: %s"
+
+#: core/validators.py:230
+#, python-format
+msgid "Invalid URL: %s"
+msgstr "Geçersiz adres: %s"
+
+#: core/validators.py:234 core/validators.py:236
+#, python-format
+msgid "The URL %s is a broken link."
+msgstr "%s kırık bir link."
+
+#: core/validators.py:242
+msgid "Enter a valid U.S. state abbreviation."
+msgstr "Geçerli bir şehir kodu girin."
+
+#: core/validators.py:256
+#, python-format
+msgid "Watch your mouth! The word %s is not allowed here."
+msgid_plural "Watch your mouth! The words %s are not allowed here."
+msgstr[0] "Söylediğinize dikkat edin! %s kelimesi burada kullanılamaz."
+msgstr[1] "Söylediğinize dikkat edin! %s kelimeleri burada kullanılamaz."
+
+#: core/validators.py:263
+#, python-format
+msgid "This field must match the '%s' field."
+msgstr "Bu alan '%s' ile alanı ile uyuşmalı."
+
+#: core/validators.py:282
+msgid "Please enter something for at least one field."
+msgstr "Lütfen en az bir alana giriş yapın."
+
+#: core/validators.py:291 core/validators.py:302
+msgid "Please enter both fields or leave them both empty."
+msgstr "Lütfen tüm alanları doldurun ya da hepsini boş bırakın."
+
+#: core/validators.py:309
+#, python-format
+msgid "This field must be given if %(field)s is %(value)s"
+msgstr "Bu alan %(field)s alanı %(value)s değerine sahipse doldurulmalı."
+
+#: core/validators.py:321
+#, python-format
+msgid "This field must be given if %(field)s is not %(value)s"
+msgstr "Bu alan %(field)s alanı %(value)s değerine sahip değilse doldurulmalı."
+
+#: core/validators.py:340
+msgid "Duplicate values are not allowed."
+msgstr "Tekrarlanan deÄŸerler kabul edilmez."
+
+#: core/validators.py:363
+#, python-format
+msgid "This value must be a power of %s."
+msgstr "Bu deÄŸer %s ya da kuvvetleri olabilir."
+
+#: core/validators.py:374
+msgid "Please enter a valid decimal number."
+msgstr "Lütfen geçerli bir ondalık sayı girin."
+
+#: core/validators.py:378
+#, python-format
+msgid "Please enter a valid decimal number with at most %s total digit."
+msgid_plural "Please enter a valid decimal number with at most %s total digits."
+msgstr[0] "Lütfen en fazla %s basamaklı bir ondalık sayı girin."
+msgstr[1] "Lütfen en fazla %s basamaklı bir ondalık sayı girin."
+
+#: core/validators.py:381
+#, python-format
+msgid "Please enter a valid decimal number with a whole part of at most %s digit."
+msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits."
+msgstr[0] "Lütfen tamsayı kısmı en fazla %s basamaklı bir ondalık sayı girin."
+msgstr[1] "Lütfen tamsayı kısmı en fazla %s basamaklı bir ondalık sayı girin."
+
+#: core/validators.py:384
+#, python-format
+msgid "Please enter a valid decimal number with at most %s decimal place."
+msgid_plural "Please enter a valid decimal number with at most %s decimal places."
+msgstr[0] "Lütfen ondalıklı kısmı en fazla %s basamaklı bir ondalık sayı girin."
+msgstr[1] "Lütfen ondalıklı kısmı en fazla %s basamaklı bir ondalık sayı girin."
+
+#: core/validators.py:394
+#, python-format
+msgid "Make sure your uploaded file is at least %s bytes big."
+msgstr "Gönderdiğiniz dosyanın en az %s byte uzunlukta olduğundan emin olun."
+
+#: core/validators.py:395
+#, python-format
+msgid "Make sure your uploaded file is at most %s bytes big."
+msgstr "Gönderdiğiniz dosyanın en fazl %s byte uzunlukta olduğundan emin olun."
+
+#: core/validators.py:412
+msgid "The format for this field is wrong."
+msgstr "Bu alandaki veri formatı hatalı."
+
+#: core/validators.py:427
+msgid "This field is invalid."
+msgstr "Alan geçersiz."
+
+#: core/validators.py:463
+#, python-format
+msgid "Could not retrieve anything from %s."
+msgstr "%s içinden hiçbirşey aktarılamıyor."
+
+#: core/validators.py:466
+#, python-format
+msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
+msgstr "%(url)s adresi geçersiz içerik türü (%(contenttype)s) gönderdi."
+
+#: core/validators.py:499
+#, python-format
+msgid ""
+"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
+"\"%(start)s\".)"
+msgstr ""
+"Lütfen %(line)s. satırdaki kapatılmayan %(tag)s etiketini kapatın. (Satır, "
+"\"%(start)s\" ile başlıyor.)"
+
+#: core/validators.py:503
+#, python-format
+msgid ""
+"Some text starting on line %(line)s is not allowed in that context. (Line "
+"starts with \"%(start)s\".)"
+msgstr ""
+"%(line)s. satırda başlayan bazı kelimeler içerik olarak kabul edilmiyor. "
+"(Satır, \"%(start)s\" ile başlıyor.)"
+
+#: core/validators.py:508
+#, python-format
+msgid ""
+"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
+"(start)s\".)"
+msgstr ""
+"%(line)s. satırdaki \"%(attr)s\" özelliği geçersiz. (Satır, \"%(start)s\" "
+"ile başlıyor.)"
+
+#: core/validators.py:513
+#, python-format
+msgid ""
+"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
+"(start)s\".)"
+msgstr ""
+"%(line)s. satırdaki \"<%(tag)s>\" etiketi geçersiz. (Satır, \"%(start)s\" "
+"ile başlıyor.)"
+
+#: core/validators.py:517
+#, python-format
+msgid ""
+"A tag on line %(line)s is missing one or more required attributes. (Line "
+"starts with \"%(start)s\".)"
+msgstr ""
+"%(line)s. satırdaki bir etiket eksik ya da eklenmesi gereken özellikleri "
+"var. (Satır, \"%(start)s\" ile başlıyor.)"
+
+#: core/validators.py:522
+#, python-format
+msgid ""
+"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
+"starts with \"%(start)s\".)"
+msgstr ""
+"%(line)s. satırdaki \"%(attr)s\" özelliği geçersiz bir değere sahip. (Satır, "
+"\"%(start)s\" ile başlıyor.)"
+
+#: views/generic/create_update.py:43
+#, python-format
+msgid "The %(verbose_name)s was created successfully."
+msgstr "%(verbose_name)s başarıyla yaratıldı."
+
+#: views/generic/create_update.py:117
+#, python-format
+msgid "The %(verbose_name)s was updated successfully."
+msgstr "%(verbose_name)s başarıyla güncellendi."
+
+#: views/generic/create_update.py:184
+#, python-format
+msgid "The %(verbose_name)s was deleted."
+msgstr "%(verbose_name)s silindi."
+
+#: utils/dates.py:6
+msgid "Monday"
+msgstr "Pazartesi"
+
+#: utils/dates.py:6
+msgid "Tuesday"
+msgstr "Salı"
+
+#: utils/dates.py:6
+msgid "Wednesday"
+msgstr "Çarşamba"
+
+#: utils/dates.py:6
+msgid "Thursday"
+msgstr "PerÅŸembe"
+
+#: utils/dates.py:6
+msgid "Friday"
+msgstr "Cuma"
+
+#: utils/dates.py:7
+msgid "Saturday"
+msgstr "Cumartesi"
+
+#: utils/dates.py:7
+msgid "Sunday"
+msgstr "Pazar"
+
+#: utils/dates.py:14
+msgid "January"
+msgstr "Ocak"
+
+#: utils/dates.py:14
+msgid "February"
+msgstr "Åžubat"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "March"
+msgstr "Mart"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "April"
+msgstr "Nisan"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "May"
+msgstr "Mayıs"
+
+#: utils/dates.py:14 utils/dates.py:27
+msgid "June"
+msgstr "Haziran"
+
+#: utils/dates.py:15 utils/dates.py:27
+msgid "July"
+msgstr "Temmuz"
+
+#: utils/dates.py:15
+msgid "August"
+msgstr "AÄŸustos"
+
+#: utils/dates.py:15
+msgid "September"
+msgstr "Eylül"
+
+#: utils/dates.py:15
+msgid "October"
+msgstr "Ekim"
+
+#: utils/dates.py:15
+msgid "November"
+msgstr "Kasım"
+
+#: utils/dates.py:16
+msgid "December"
+msgstr "Aralık"
+
+#: utils/dates.py:19
+msgid "jan"
+msgstr "oca"
+
+#: utils/dates.py:19
+msgid "feb"
+msgstr "ÅŸub"
+
+#: utils/dates.py:19
+msgid "mar"
+msgstr "mar"
+
+#: utils/dates.py:19
+msgid "apr"
+msgstr "nis"
+
+#: utils/dates.py:19
+msgid "may"
+msgstr "may"
+
+#: utils/dates.py:19
+msgid "jun"
+msgstr "haz"
+
+#: utils/dates.py:20
+msgid "jul"
+msgstr "tem"
+
+#: utils/dates.py:20
+msgid "aug"
+msgstr "aÄŸu"
+
+#: utils/dates.py:20
+msgid "sep"
+msgstr "eyl"
+
+#: utils/dates.py:20
+msgid "oct"
+msgstr "eki"
+
+#: utils/dates.py:20
+msgid "nov"
+msgstr "kas"
+
+#: utils/dates.py:20
+msgid "dec"
+msgstr "ara"
+
+#: utils/dates.py:27
+msgid "Jan."
+msgstr "Oca."
+
+#: utils/dates.py:27
+msgid "Feb."
+msgstr "Åžub."
+
+#: utils/dates.py:28
+msgid "Aug."
+msgstr "AÄŸu."
+
+#: utils/dates.py:28
+msgid "Sept."
+msgstr "Eyl."
+
+#: utils/dates.py:28
+msgid "Oct."
+msgstr "Eki."
+
+#: utils/dates.py:28
+msgid "Nov."
+msgstr "Kas."
+
+#: utils/dates.py:28
+msgid "Dec."
+msgstr "Ara."
+
+#: utils/timesince.py:12
+msgid "year"
+msgid_plural "years"
+msgstr[0] "yıl"
+msgstr[1] "yıl"
+
+#: utils/timesince.py:13
+msgid "month"
+msgid_plural "months"
+msgstr[0] "ay"
+msgstr[1] "ay"
+
+#: utils/timesince.py:14
+msgid "week"
+msgid_plural "weeks"
+msgstr[0] "hafta"
+msgstr[1] "hafta"
+
+#: utils/timesince.py:15
+msgid "day"
+msgid_plural "days"
+msgstr[0] "gün"
+msgstr[1] "gün"
+
+#: utils/timesince.py:16
+msgid "hour"
+msgid_plural "hours"
+msgstr[0] "saat"
+msgstr[1] "saat"
+
+#: utils/timesince.py:17
+msgid "minute"
+msgid_plural "minutes"
+msgstr[0] "dakika"
+msgstr[1] "dakika"
+
+#: utils/translation/trans_real.py:362
+msgid "DATE_FORMAT"
+msgstr "DATE_FORMAT"
+
+#: utils/translation/trans_real.py:363
+msgid "DATETIME_FORMAT"
+msgstr "DATETIME_FORMAT"
+
+#: utils/translation/trans_real.py:364
+msgid "TIME_FORMAT"
+msgstr "TIME_FORMAT"
+
+#: utils/translation/trans_real.py:380
+msgid "YEAR_MONTH_FORMAT"
+msgstr "YEAR_MONTH_FORMAT"
+
+#: utils/translation/trans_real.py:381
+msgid "MONTH_DAY_FORMAT"
+msgstr "MONTH_DAY_FORMAT"
+
+#: contrib/contenttypes/models.py:20
+msgid "python model class name"
+msgstr "python model sınıfı"
+
+#: contrib/contenttypes/models.py:23
+msgid "content type"
+msgstr "içerik türü"
+
+#: contrib/contenttypes/models.py:24
+msgid "content types"
+msgstr "içerik türleri"
+
+#: contrib/auth/views.py:39
+msgid "Logged out"
+msgstr "Çıkış yapıldı"
+
+#: contrib/auth/models.py:38 contrib/auth/models.py:57
+msgid "name"
+msgstr "isim"
+
+#: contrib/auth/models.py:40
+msgid "codename"
+msgstr "takma ad"
+
+#: contrib/auth/models.py:42
+msgid "permission"
+msgstr "izin"
+
+#: contrib/auth/models.py:43 contrib/auth/models.py:58
+msgid "permissions"
+msgstr "izinler"
+
+#: contrib/auth/models.py:60
+msgid "group"
+msgstr "grup"
+
+#: contrib/auth/models.py:61 contrib/auth/models.py:100
+msgid "groups"
+msgstr "gruplar"
+
+#: contrib/auth/models.py:90
+msgid "username"
+msgstr "kullanıcı adı"
+
+#: contrib/auth/models.py:90
+msgid ""
+"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
+"digits and underscores)."
+msgstr ""
+"Gerekli. 30 karakter ya da da az olmalı. Alfanumerik (harf, rakam ve alt "
+"çizgi) karakterler kullanılabilir."
+
+#: contrib/auth/models.py:91
+msgid "first name"
+msgstr "isim"
+
+#: contrib/auth/models.py:92
+msgid "last name"
+msgstr "soyisim"
+
+#: contrib/auth/models.py:93
+msgid "e-mail address"
+msgstr "e-posta adresi"
+
+#: contrib/auth/models.py:94
+msgid "password"
+msgstr "parola"
+
+#: contrib/auth/models.py:94
+msgid "Use '[algo]$[salt]$[hexdigest]'"
+msgstr "'[algo]$[salt]$[hexdigest]' formatında"
+
+#: contrib/auth/models.py:95
+msgid "staff status"
+msgstr "yönetici modu"
+
+#: contrib/auth/models.py:95
+msgid "Designates whether the user can log into this admin site."
+msgstr "Kullanıcının yönetici sayfasına girip giremeyeceğini belirler."
+
+#: contrib/auth/models.py:96
+msgid "active"
+msgstr "aktif"
+
+#: contrib/auth/models.py:96
+msgid ""
+"Designates whether this user can log into the Django admin. Unselect this "
+"instead of deleting accounts."
+msgstr ""
+"Kullanıcının Django yönetim sayfasına girip giremeyeceğini belirler. "
+"Kullanıcı hesabı silmek yerine işareti kaldırın."
+
+#: contrib/auth/models.py:97
+msgid "superuser status"
+msgstr "süper kullanıcı modu"
+
+#: contrib/auth/models.py:97
+msgid ""
+"Designates that this user has all permissions without explicitly assigning "
+"them."
+msgstr ""
+"Kullanıcının tek tek hak atamasına gerek kalmadan tüm haklara sahip olup "
+"olamayacağını belirler."
+
+#: contrib/auth/models.py:98
+msgid "last login"
+msgstr "son ziyaret"
+
+#: contrib/auth/models.py:99
+msgid "date joined"
+msgstr "kayıt tarihi"
+
+#: contrib/auth/models.py:101
+msgid ""
+"In addition to the permissions manually assigned, this user will also get "
+"all permissions granted to each group he/she is in."
+msgstr ""
+"Özel olarak atanmış hakların yanı sıra, kullanıcının üyesi olduğu grupların "
+"hakları alır."
+
+#: contrib/auth/models.py:102
+msgid "user permissions"
+msgstr "kullanıcı izinleri"
+
+#: contrib/auth/models.py:105
+msgid "user"
+msgstr "kullanıcı"
+
+#: contrib/auth/models.py:106
+msgid "users"
+msgstr "kullanıcılar"
+
+#: contrib/auth/models.py:111
+msgid "Personal info"
+msgstr "KiÅŸisel bilgiler"
+
+#: contrib/auth/models.py:112
+msgid "Permissions"
+msgstr "İzinler"
+
+#: contrib/auth/models.py:113
+msgid "Important dates"
+msgstr "Önemli tarihler"
+
+#: contrib/auth/models.py:114
+msgid "Groups"
+msgstr "Gruplar"
+
+#: contrib/auth/models.py:258
+msgid "message"
+msgstr "mesaj"
+
+#: contrib/auth/forms.py:16
+msgid "The two password fields didn't match."
+msgstr "İki parola alanı uyuşmuyor."
+
+#: contrib/auth/forms.py:24
+msgid "A user with that username already exists."
+msgstr "Bu isimde bir kullanıcı zaten var."
+
+#: contrib/auth/forms.py:52
+msgid ""
+"Your Web browser doesn't appear to have cookies enabled. Cookies are "
+"required for logging in."
+msgstr ""
+"Web tarayıcınızın çerezleri desteklemediği görülüyor. Çerezler giriş için "
+"gerekli."
+
+#: contrib/auth/forms.py:59 contrib/admin/views/decorators.py:10
+msgid ""
+"Please enter a correct username and password. Note that both fields are case-"
+"sensitive."
+msgstr ""
+"Lütfen geçerli bir kullanıcı adı ve parola girin. Tüm alanlar büyük/küçük "
+"harf duyarlıdır."
+
+#: contrib/auth/forms.py:61
+msgid "This account is inactive."
+msgstr "Bu hesap aktif deÄŸil."
+
+#: contrib/auth/forms.py:84
+msgid ""
+"That e-mail address doesn't have an associated user acount. Are you sure "
+"you've registered?"
+msgstr "Bu e-posta hesabıyla ilişkili kullanıcı bulunmuyor. Kayıtlı olduğunuzdan emin misiniz?"
+
+#: contrib/auth/forms.py:116
+msgid "The two 'new password' fields didn't match."
+msgstr "İki parola alanı uyuşmuyor."
+
+#: contrib/auth/forms.py:123
+msgid "Your old password was entered incorrectly. Please enter it again."
+msgstr "Eski parolanız hatalı. Lütfen tekrar girin."
+
+#: contrib/redirects/models.py:7
+msgid "redirect from"
+msgstr "eski adres"
+
+#: contrib/redirects/models.py:8
+msgid ""
+"This should be an absolute path, excluding the domain name. Example: '/"
+"events/search/'."
+msgstr ""
+"Buraya tam dosya yolu, alan adı kullanılmadan yazılmalı. Örnek: '/events/"
+"search/'."
+
+#: contrib/redirects/models.py:9
+msgid "redirect to"
+msgstr "yeni adres"
+
+#: contrib/redirects/models.py:10
+msgid ""
+"This can be either an absolute path (as above) or a full URL starting with "
+"'http://'."
+msgstr ""
+"Buraya tam dosya yolu (yukarıdaki gibi), ya da 'http://' ile başlayan tam "
+"adres yazılmalı."
+
+#: contrib/redirects/models.py:13
+msgid "redirect"
+msgstr "yönlendirme"
+
+#: contrib/redirects/models.py:14
+msgid "redirects"
+msgstr "yönlendirmeler"
+
+#: contrib/comments/models.py:67 contrib/comments/models.py:166
+msgid "object ID"
+msgstr "nesne no"
+
+#: contrib/comments/models.py:68
+msgid "headline"
+msgstr "başlık"
+
+#: contrib/comments/models.py:69 contrib/comments/models.py:90
+#: contrib/comments/models.py:167
+msgid "comment"
+msgstr "yorum"
+
+#: contrib/comments/models.py:70
+msgid "rating #1"
+msgstr "reyting 1"
+
+#: contrib/comments/models.py:71
+msgid "rating #2"
+msgstr "reyting 2"
+
+#: contrib/comments/models.py:72
+msgid "rating #3"
+msgstr "reyting 3"
+
+#: contrib/comments/models.py:73
+msgid "rating #4"
+msgstr "reyting 4"
+
+#: contrib/comments/models.py:74
+msgid "rating #5"
+msgstr "reyting 5"
+
+#: contrib/comments/models.py:75
+msgid "rating #6"
+msgstr "reyting 6"
+
+#: contrib/comments/models.py:76
+msgid "rating #7"
+msgstr "reyting 7"
+
+#: contrib/comments/models.py:77
+msgid "rating #8"
+msgstr "reyting 8"
+
+#: contrib/comments/models.py:82
+msgid "is valid rating"
+msgstr "geçerli reyting"
+
+#: contrib/comments/models.py:83 contrib/comments/models.py:169
+msgid "date/time submitted"
+msgstr "gönderim tarihi/saati"
+
+#: contrib/comments/models.py:84 contrib/comments/models.py:170
+msgid "is public"
+msgstr "görünürlük"
+
+#: contrib/comments/models.py:85 contrib/admin/views/doc.py:304
+msgid "IP address"
+msgstr "IP adresi"
+
+#: contrib/comments/models.py:86
+msgid "is removed"
+msgstr "silinmiÅŸ"
+
+#: contrib/comments/models.py:86
+msgid ""
+"Check this box if the comment is inappropriate. A \"This comment has been "
+"removed\" message will be displayed instead."
+msgstr ""
+"Yorum uygunsuz ise bu işareti kaldırın. \"Yorum silindi\" uyarısı "
+"görüntülenecek."
+
+#: contrib/comments/models.py:91
+msgid "comments"
+msgstr "yorumlar"
+
+#: contrib/comments/models.py:131 contrib/comments/models.py:207
+msgid "Content object"
+msgstr "İçerik nesnesi"
+
+#: contrib/comments/models.py:159
+#, python-format
+msgid ""
+"Posted by %(user)s at %(date)s\n"
+"\n"
+"%(comment)s\n"
+"\n"
+"http://%(domain)s%(url)s"
+msgstr ""
+"%(date)s tarihinde %(user)s göndermiş:\n"
+"\n"
+"%(comment)s\n"
+"\n"
+"http://%(domain)s%(url)s"
+
+#: contrib/comments/models.py:168
+msgid "person's name"
+msgstr "isim"
+
+#: contrib/comments/models.py:171
+msgid "ip address"
+msgstr "ip adresi"
+
+#: contrib/comments/models.py:173
+msgid "approved by staff"
+msgstr "yönetici onayı"
+
+#: contrib/comments/models.py:176
+msgid "free comment"
+msgstr "serbest yorum"
+
+#: contrib/comments/models.py:177
+msgid "free comments"
+msgstr "serbest yorumlar"
+
+#: contrib/comments/models.py:233
+msgid "score"
+msgstr "puan"
+
+#: contrib/comments/models.py:234
+msgid "score date"
+msgstr "puan tarihi"
+
+#: contrib/comments/models.py:237
+msgid "karma score"
+msgstr "karma puanı"
+
+#: contrib/comments/models.py:238
+msgid "karma scores"
+msgstr "karma puanları"
+
+#: contrib/comments/models.py:242
+#, python-format
+msgid "%(score)d rating by %(user)s"
+msgstr "%(user)s tarafından %(score)d puan"
+
+#: contrib/comments/models.py:258
+#, python-format
+msgid ""
+"This comment was flagged by %(user)s:\n"
+"\n"
+"%(text)s"
+msgstr ""
+"Bu yorum %(user)s tarafından işaretlenmiş:\n"
+"\n"
+"%(text)s"
+
+#: contrib/comments/models.py:265
+msgid "flag date"
+msgstr "iÅŸaretleme tarihi"
+
+#: contrib/comments/models.py:268
+msgid "user flag"
+msgstr "kullanıcı işareti"
+
+#: contrib/comments/models.py:269
+msgid "user flags"
+msgstr "kullanıcı işaretleri"
+
+#: contrib/comments/models.py:273
+#, python-format
+msgid "Flag by %r"
+msgstr "%r tarafından işaret"
+
+#: contrib/comments/models.py:278
+msgid "deletion date"
+msgstr "silme tarihi"
+
+#: contrib/comments/models.py:280
+msgid "moderator deletion"
+msgstr "yönetici tarafından silinme"
+
+#: contrib/comments/models.py:281
+msgid "moderator deletions"
+msgstr "yönetici tarafından silinme"
+
+#: contrib/comments/models.py:285
+#, python-format
+msgid "Moderator deletion by %r"
+msgstr "%s tarafından silme işlemi"
+
+#: contrib/comments/views/karma.py:19
+msgid "Anonymous users cannot vote"
+msgstr "Kayıtsız kullanıcılar oy veremez"
+
+#: contrib/comments/views/karma.py:23
+msgid "Invalid comment ID"
+msgstr "Geçersiz yorum numarası"
+
+#: contrib/comments/views/karma.py:25
+msgid "No voting for yourself"
+msgstr "Kendinize oy veremezsiniz"
+
+#: contrib/comments/views/comments.py:27
+msgid "This rating is required because you've entered at least one other rating."
+msgstr "Reyting gerekli, çünkü en az bir reyting tanımladınız."
+
+#: contrib/comments/views/comments.py:111
+#, python-format
+msgid ""
+"This comment was posted by a user who has posted fewer than %(count)s "
+"comment:\n"
+"\n"
+"%(text)s"
+msgid_plural ""
+"This comment was posted by a user who has posted fewer than %(count)s "
+"comments:\n"
+"\n"
+"%(text)s"
+msgstr[0] ""
+"Bu yorum, %(count)s yorumdan daha az gönderide bulunmuş bir kullanıcıya "
+"ait:\n"
+"\n"
+"%(text)s"
+msgstr[1] ""
+"Bu yorum, %(count)s yorumdan daha az gönderide bulunmuş bir kullanıcıya "
+"ait:\n"
+"\n"
+"%(text)s"
+
+#: contrib/comments/views/comments.py:116
+#, python-format
+msgid ""
+"This comment was posted by a sketchy user:\n"
+"\n"
+"%(text)s"
+msgstr ""
+"Bu yorum kusurlu bir kullanıcı tarafından gönderildi:\n"
+"\n"
+"%(text)s"
+
+#: contrib/comments/views/comments.py:188
+#: contrib/comments/views/comments.py:280
+msgid "Only POSTs are allowed"
+msgstr "Sadece POST yapılabilir"
+
+#: contrib/comments/views/comments.py:192
+#: contrib/comments/views/comments.py:284
+msgid "One or more of the required fields wasn't submitted"
+msgstr "Bir ya da daha fazla gerekli alan doldurulmadı"
+
+#: contrib/comments/views/comments.py:196
+#: contrib/comments/views/comments.py:286
+msgid "Somebody tampered with the comment form (security violation)"
+msgstr "Birisi yorum gönderme formunu kötüye kullanmaya çalıştı (güvenlik ihlali)"
+
+#: contrib/comments/views/comments.py:206
+#: contrib/comments/views/comments.py:292
+msgid ""
+"The comment form had an invalid 'target' parameter -- the object ID was "
+"invalid"
+msgstr "Bu yorumun geçersiz bir 'hedef' parametresi var -- nesne narası geçersiz"
+
+#: contrib/comments/views/comments.py:257
+#: contrib/comments/views/comments.py:321
+msgid "The comment form didn't provide either 'preview' or 'post'"
+msgstr "Yorum görüntülememe mi yoksa gönderme amaçlı mı belirsiz"
+
+#: contrib/comments/templates/comments/form.html:6
+#: contrib/comments/templates/comments/form.html:8
+#: contrib/admin/templates/admin/login.html:17
+msgid "Username:"
+msgstr "Kullanıcı:"
+
+#: contrib/comments/templates/comments/form.html:6
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/base.html:25
+#: contrib/admin/templates/registration/password_change_done.html:3
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/admin_doc/view_detail.html:4
+#: contrib/admin/templates/admin_doc/bookmarklets.html:4
+#: contrib/admin/templates/admin_doc/template_detail.html:4
+#: contrib/admin/templates/admin_doc/template_tag_index.html:5
+#: contrib/admin/templates/admin_doc/missing_docutils.html:4
+#: contrib/admin/templates/admin_doc/view_index.html:5
+#: contrib/admin/templates/admin_doc/model_detail.html:3
+#: contrib/admin/templates/admin_doc/index.html:4
+#: contrib/admin/templates/admin_doc/model_index.html:5
+#: contrib/admin/templates/admin_doc/template_filter_index.html:5
+msgid "Log out"
+msgstr "Çık"
+
+#: contrib/comments/templates/comments/form.html:8
+#: contrib/admin/templates/admin/login.html:20
+msgid "Password:"
+msgstr "Parola:"
+
+#: contrib/comments/templates/comments/form.html:8
+msgid "Forgotten your password?"
+msgstr "Parolanızı mı unuttunuz?"
+
+#: contrib/comments/templates/comments/form.html:12
+msgid "Ratings"
+msgstr "Reytingler"
+
+#: contrib/comments/templates/comments/form.html:12
+#: contrib/comments/templates/comments/form.html:23
+msgid "Required"
+msgstr "Gerekli"
+
+#: contrib/comments/templates/comments/form.html:12
+#: contrib/comments/templates/comments/form.html:23
+msgid "Optional"
+msgstr "Opsiyonel"
+
+#: contrib/comments/templates/comments/form.html:23
+msgid "Post a photo"
+msgstr "Resim gönder"
+
+#: contrib/comments/templates/comments/form.html:28
+#: contrib/comments/templates/comments/freeform.html:5
+msgid "Comment:"
+msgstr "Yorum:"
+
+#: contrib/comments/templates/comments/form.html:35
+#: contrib/comments/templates/comments/freeform.html:10
+msgid "Preview comment"
+msgstr "Yorumu görüntüle"
+
+#: contrib/comments/templates/comments/freeform.html:4
+msgid "Your name:"
+msgstr "İsminiz:"
+
+#: contrib/flatpages/models.py:7 contrib/admin/views/doc.py:315
+msgid "URL"
+msgstr "URL"
+
+#: contrib/flatpages/models.py:8
+msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes."
+msgstr ""
+"Örnek: '/about/contact/'. Başında ve sonunda bölü işareti olduğundan emin "
+"olun."
+
+#: contrib/flatpages/models.py:9
+msgid "title"
+msgstr "başlık"
+
+#: contrib/flatpages/models.py:10
+msgid "content"
+msgstr "içerik"
+
+#: contrib/flatpages/models.py:11
+msgid "enable comments"
+msgstr "yorumlara izin ver"
+
+#: contrib/flatpages/models.py:12
+msgid "template name"
+msgstr "şablon adı"
+
+#: contrib/flatpages/models.py:13
+msgid ""
+"Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
+"will use 'flatpages/default.html'."
+msgstr ""
+"Örnek: 'flatpages/contact_page.html'. Eğer birşey yazılmazsa, sistem "
+"otomatik olarak 'flatpages/default.html' kullanacak."
+
+#: contrib/flatpages/models.py:14
+msgid "registration required"
+msgstr "kayıt gerekli"
+
+#: contrib/flatpages/models.py:14
+msgid "If this is checked, only logged-in users will be able to view the page."
+msgstr "Bu seçili ise, sadece kayıtlı kullanıcılar sayfayı görüntüleyebilir."
+
+#: contrib/flatpages/models.py:18
+msgid "flat page"
+msgstr "düz sayfa"
+
+#: contrib/flatpages/models.py:19
+msgid "flat pages"
+msgstr "düz sayfalar"
+
+#: contrib/sessions/models.py:51
+msgid "session key"
+msgstr "oturum anahtarı"
+
+#: contrib/sessions/models.py:52
+msgid "session data"
+msgstr "oturum bilgisi"
+
+#: contrib/sessions/models.py:53
+msgid "expire date"
+msgstr "bitiÅŸ tarihi"
+
+#: contrib/sessions/models.py:57
+msgid "session"
+msgstr "oturum"
+
+#: contrib/sessions/models.py:58
+msgid "sessions"
+msgstr "oturumlar"
+
+#: contrib/sites/models.py:10
+msgid "domain name"
+msgstr "alan adı"
+
+#: contrib/sites/models.py:11
+msgid "display name"
+msgstr "görülen isim"
+
+#: contrib/sites/models.py:15
+msgid "site"
+msgstr "site"
+
+#: contrib/sites/models.py:16
+msgid "sites"
+msgstr "siteler"
+
+#: contrib/admin/filterspecs.py:40
+#, python-format
+msgid ""
+"<h3>By %s:</h3>\n"
+"<ul>\n"
+msgstr ""
+"<h3>%s nesnesine göre:</h3>\n"
+"<ul>\n"
+
+#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
+#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169
+msgid "All"
+msgstr "Tümü"
+
+#: contrib/admin/filterspecs.py:109
+msgid "Any date"
+msgstr "Herhangi bir tarih"
+
+#: contrib/admin/filterspecs.py:110
+msgid "Today"
+msgstr "Bugün"
+
+#: contrib/admin/filterspecs.py:113
+msgid "Past 7 days"
+msgstr "7 gün içinde"
+
+#: contrib/admin/filterspecs.py:115
+msgid "This month"
+msgstr "Bu ay"
+
+#: contrib/admin/filterspecs.py:117
+msgid "This year"
+msgstr "Bu yıl"
+
+#: contrib/admin/filterspecs.py:143
+msgid "Yes"
+msgstr "Evet"
+
+#: contrib/admin/filterspecs.py:143
+msgid "No"
+msgstr "Hayır"
+
+#: contrib/admin/filterspecs.py:150
+msgid "Unknown"
+msgstr "Bilinmiyor"
+
+#: contrib/admin/models.py:16
+msgid "action time"
+msgstr "işlem zamanı"
+
+#: contrib/admin/models.py:19
+msgid "object id"
+msgstr "nesne no"
+
+#: contrib/admin/models.py:20
+msgid "object repr"
+msgstr "nesne kodu"
+
+#: contrib/admin/models.py:21
+msgid "action flag"
+msgstr "işlem adı"
+
+#: contrib/admin/models.py:22
+msgid "change message"
+msgstr "mesajı değiştir"
+
+#: contrib/admin/models.py:25
+msgid "log entry"
+msgstr "giriÅŸi kaydet"
+
+#: contrib/admin/models.py:26
+msgid "log entries"
+msgstr "giriÅŸleri kaydet"
+
+#: contrib/admin/templatetags/admin_list.py:230
+msgid "All dates"
+msgstr "Tüm tarihler"
+
+#: contrib/admin/views/auth.py:17 contrib/admin/views/main.py:257
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was added successfully."
+msgstr "\"%(obj)s\" isimli %(name)s eklendi."
+
+#: contrib/admin/views/auth.py:22 contrib/admin/views/main.py:261
+#: contrib/admin/views/main.py:347
+msgid "You may edit it again below."
+msgstr "Tekrar düzenleyebilirsiniz."
+
+#: contrib/admin/views/auth.py:28
+msgid "Add user"
+msgstr "Kullanıcı ekle"
+
+#: contrib/admin/views/main.py:223
+msgid "Site administration"
+msgstr "Site yönetimi"
+
+#: contrib/admin/views/main.py:271 contrib/admin/views/main.py:356
+#, python-format
+msgid "You may add another %s below."
+msgstr "Yeni bir %s ekleyebilirsiniz."
+
+#: contrib/admin/views/main.py:289
+#, python-format
+msgid "Add %s"
+msgstr "%s ekle"
+
+#: contrib/admin/views/main.py:335
+#, python-format
+msgid "Added %s."
+msgstr "%s eklendi."
+
+#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
+#: contrib/admin/views/main.py:339
+msgid "and"
+msgstr "ve"
+
+#: contrib/admin/views/main.py:337
+#, python-format
+msgid "Changed %s."
+msgstr "%s deÄŸiÅŸtirildi."
+
+#: contrib/admin/views/main.py:339
+#, python-format
+msgid "Deleted %s."
+msgstr "%s silindi."
+
+#: contrib/admin/views/main.py:342
+msgid "No fields changed."
+msgstr "Hiçbir alan değiştirilmedi."
+
+#: contrib/admin/views/main.py:345
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was changed successfully."
+msgstr "\"%(obj)s\" isimli %(name)s deÄŸiÅŸtirildi."
+
+#: contrib/admin/views/main.py:353
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
+msgstr "\"%(obj)s\" isimli %(name)s eklendi. Aşağıda tekrar düzenleyebilirsiniz."
+
+#: contrib/admin/views/main.py:391
+#, python-format
+msgid "Change %s"
+msgstr "%s deÄŸiÅŸtir"
+
+#: contrib/admin/views/main.py:473
+#, python-format
+msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
+msgstr "%(name)s içinde bir ya da daha fazla %(fieldname)s: %(obj)s"
+
+#: contrib/admin/views/main.py:478
+#, python-format
+msgid "One or more %(fieldname)s in %(name)s:"
+msgstr "%(name)s içinde bir ya da daha fazla %(fieldname)s:"
+
+#: contrib/admin/views/main.py:511
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was deleted successfully."
+msgstr "\"%(obj)s\" isimli %(name)s silindi."
+
+#: contrib/admin/views/main.py:514
+msgid "Are you sure?"
+msgstr "Emin misiniz?"
+
+#: contrib/admin/views/main.py:536
+#, python-format
+msgid "Change history: %s"
+msgstr "%s için değişiklik geçmişi:"
+
+#: contrib/admin/views/main.py:570
+#, python-format
+msgid "Select %s"
+msgstr "%s seç"
+
+#: contrib/admin/views/main.py:570
+#, python-format
+msgid "Select %s to change"
+msgstr "Değiştirilecek %s nesnesini seçin"
+
+#: contrib/admin/views/main.py:758
+msgid "Database error"
+msgstr "Veritabanı hatası"
+
+#: contrib/admin/views/decorators.py:24
+#: contrib/admin/templates/admin/login.html:25
+msgid "Log in"
+msgstr "GiriÅŸ yap"
+
+#: contrib/admin/views/decorators.py:62
+msgid ""
+"Please log in again, because your session has expired. Don't worry: Your "
+"submission has been saved."
+msgstr ""
+"Oturumunuzun süresi geçti. Lütfen tekrar giriş yapın. Endişe etmeyin, "
+"gönderiniz kayıt edildi."
+
+#: contrib/admin/views/decorators.py:69
+msgid ""
+"Looks like your browser isn't configured to accept cookies. Please enable "
+"cookies, reload this page, and try again."
+msgstr ""
+"Görünüşe göre tarayıcınız çerezleri kabul etmiyor. Çerez kullanımını aktif "
+"hale getirin ve sayfayı yeniden yükleyin."
+
+#: contrib/admin/views/decorators.py:83
+msgid "Usernames cannot contain the '@' character."
+msgstr "Kullanıcı isminde '@' karakteri bulunamaz."
+
+#: contrib/admin/views/decorators.py:85
+#, python-format
+msgid "Your e-mail address is not your username. Try '%s' instead."
+msgstr "E-posta adresiniz kullanıcı adınız değil. '%s' kullanın."
+
+#: contrib/admin/views/doc.py:46 contrib/admin/views/doc.py:48
+#: contrib/admin/views/doc.py:50
+msgid "tag:"
+msgstr "etiket:"
+
+#: contrib/admin/views/doc.py:77 contrib/admin/views/doc.py:79
+#: contrib/admin/views/doc.py:81
+msgid "filter:"
+msgstr "filtre:"
+
+#: contrib/admin/views/doc.py:135 contrib/admin/views/doc.py:137
+#: contrib/admin/views/doc.py:139
+msgid "view:"
+msgstr "view:"
+
+#: contrib/admin/views/doc.py:164
+#, python-format
+msgid "App %r not found"
+msgstr "%r uygulaması bulunamadı"
+
+#: contrib/admin/views/doc.py:171
+#, python-format
+msgid "Model %r not found in app %r"
+msgstr "%r modeli %r uygulamasında bulunamadı"
+
+#: contrib/admin/views/doc.py:183
+#, python-format
+msgid "the related `%s.%s` object"
+msgstr "ilgili `%s.%s` nesnesi"
+
+#: contrib/admin/views/doc.py:183 contrib/admin/views/doc.py:205
+#: contrib/admin/views/doc.py:219 contrib/admin/views/doc.py:224
+msgid "model:"
+msgstr "model:"
+
+#: contrib/admin/views/doc.py:214
+#, python-format
+msgid "related `%s.%s` objects"
+msgstr "ilgili `%s.%s` nesneleri"
+
+#: contrib/admin/views/doc.py:219
+#, python-format
+msgid "all %s"
+msgstr "tüm %s"
+
+#: contrib/admin/views/doc.py:224
+#, python-format
+msgid "number of %s"
+msgstr "%s sayısı"
+
+#: contrib/admin/views/doc.py:229
+#, python-format
+msgid "Fields on %s objects"
+msgstr "%s nesnesindeki alanlar"
+
+#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:301
+#: contrib/admin/views/doc.py:303 contrib/admin/views/doc.py:309
+#: contrib/admin/views/doc.py:310 contrib/admin/views/doc.py:312
+msgid "Integer"
+msgstr "Tamsayı"
+
+#: contrib/admin/views/doc.py:292
+msgid "Boolean (Either True or False)"
+msgstr "Mantıksal (True ya da False)"
+
+#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:311
+#, python-format
+msgid "String (up to %(maxlength)s)"
+msgstr "Karakter disizi (en fazla %(maxlength)s)"
+
+#: contrib/admin/views/doc.py:294
+msgid "Comma-separated integers"
+msgstr "Virgülle ayrılmış tamsayılar"
+
+#: contrib/admin/views/doc.py:295
+msgid "Date (without time)"
+msgstr "Tarih (saat yok)"
+
+#: contrib/admin/views/doc.py:296
+msgid "Date (with time)"
+msgstr "Tarih (saat var)"
+
+#: contrib/admin/views/doc.py:297
+msgid "E-mail address"
+msgstr "E-posta adresi"
+
+#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:299
+#: contrib/admin/views/doc.py:302
+msgid "File path"
+msgstr "Dosya yolu"
+
+#: contrib/admin/views/doc.py:300
+msgid "Decimal number"
+msgstr "Ondalık sayı:"
+
+#: contrib/admin/views/doc.py:306
+msgid "Boolean (Either True, False or None)"
+msgstr "Mantıksal (True, False, ya da None)"
+
+#: contrib/admin/views/doc.py:307
+msgid "Relation to parent model"
+msgstr "Ana modelle iliÅŸki"
+
+#: contrib/admin/views/doc.py:308
+msgid "Phone number"
+msgstr "Telefon numarası"
+
+#: contrib/admin/views/doc.py:313
+msgid "Text"
+msgstr "Metin"
+
+#: contrib/admin/views/doc.py:314
+msgid "Time"
+msgstr "Saat"
+
+#: contrib/admin/views/doc.py:316
+msgid "U.S. state (two uppercase letters)"
+msgstr "Åžehir Kodu (iki karakter)"
+
+#: contrib/admin/views/doc.py:317
+msgid "XML text"
+msgstr "XML metni"
+
+#: contrib/admin/views/doc.py:343
+#, python-format
+msgid "%s does not appear to be a urlpattern object"
+msgstr "%s geçerli vir adres kalıbı değil"
+
+#: contrib/admin/templates/widget/file.html:2
+msgid "Currently:"
+msgstr "Åžimdiki:"
+
+#: contrib/admin/templates/widget/file.html:3
+msgid "Change:"
+msgstr "DeÄŸiÅŸtir:"
+
+#: contrib/admin/templates/widget/date_time.html:3
+msgid "Date:"
+msgstr "Tarih:"
+
+#: contrib/admin/templates/widget/date_time.html:4
+msgid "Time:"
+msgstr "Saat:"
+
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/base.html:25
+#: contrib/admin/templates/registration/password_change_done.html:3
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+msgid "Documentation"
+msgstr "Dökümantasyon"
+
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/base.html:25
+#: contrib/admin/templates/registration/password_change_done.html:3
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/admin_doc/view_detail.html:4
+#: contrib/admin/templates/admin_doc/bookmarklets.html:4
+#: contrib/admin/templates/admin_doc/template_detail.html:4
+#: contrib/admin/templates/admin_doc/template_tag_index.html:5
+#: contrib/admin/templates/admin_doc/missing_docutils.html:4
+#: contrib/admin/templates/admin_doc/view_index.html:5
+#: contrib/admin/templates/admin_doc/model_detail.html:3
+#: contrib/admin/templates/admin_doc/index.html:4
+#: contrib/admin/templates/admin_doc/model_index.html:5
+#: contrib/admin/templates/admin_doc/template_filter_index.html:5
+msgid "Change password"
+msgstr "Parola deÄŸiÅŸtir"
+
+#: contrib/admin/templates/admin/change_list.html:6
+#: contrib/admin/templates/admin/object_history.html:5
+#: contrib/admin/templates/admin/500.html:4
+#: contrib/admin/templates/admin/invalid_setup.html:4
+#: contrib/admin/templates/admin/change_form.html:13
+#: contrib/admin/templates/admin/delete_confirmation.html:6
+#: contrib/admin/templates/admin/base.html:30
+#: contrib/admin/templates/registration/password_change_done.html:4
+#: contrib/admin/templates/registration/password_reset_form.html:4
+#: contrib/admin/templates/registration/logged_out.html:4
+#: contrib/admin/templates/registration/password_reset_done.html:4
+#: contrib/admin/templates/registration/password_change_form.html:4
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+msgid "Home"
+msgstr "Anasayfa"
+
+#: contrib/admin/templates/admin/change_list.html:11
+#, python-format
+msgid "Add %(name)s"
+msgstr "%(name)s Ekle"
+
+#: contrib/admin/templates/admin/filter.html:2
+#, python-format
+msgid " By %(filter_title)s "
+msgstr " %(filter_title)s nesnesine göre "
+
+#: contrib/admin/templates/admin/object_history.html:5
+#: contrib/admin/templates/admin/change_form.html:20
+msgid "History"
+msgstr "Geçmiş"
+
+#: contrib/admin/templates/admin/object_history.html:18
+msgid "Date/time"
+msgstr "Tarih/saat"
+
+#: contrib/admin/templates/admin/object_history.html:19
+msgid "User"
+msgstr "Kullanıcı"
+
+#: contrib/admin/templates/admin/object_history.html:20
+msgid "Action"
+msgstr "İşlem"
+
+#: contrib/admin/templates/admin/object_history.html:26
+msgid "DATE_WITH_TIME_FULL"
+msgstr "DATE_WITH_TIME_FULL"
+
+#: contrib/admin/templates/admin/object_history.html:36
+msgid ""
+"This object doesn't have a change history. It probably wasn't added via this "
+"admin site."
+msgstr ""
+"Bu nesnenin işlem geçmişi yok. Muhtemelen yönetici sayfası dışında bir "
+"yerden eklendi."
+
+#: contrib/admin/templates/admin/search_form.html:8
+msgid "Go"
+msgstr "Git"
+
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "1 result"
+msgid_plural "%(counter)s results"
+msgstr[0] "1 sonuç"
+msgstr[1] "%(counter)s sonuç"
+
+#: contrib/admin/templates/admin/search_form.html:10
+#, python-format
+msgid "%(full_result_count)s total"
+msgstr "toplam %(full_result_count)s"
+
+#: contrib/admin/templates/admin/pagination.html:10
+msgid "Show all"
+msgstr "Tümünü göster"
+
+#: contrib/admin/templates/admin/base_site.html:4
+msgid "Django site admin"
+msgstr "Django site yöneticisi"
+
+#: contrib/admin/templates/admin/base_site.html:7
+msgid "Django administration"
+msgstr "Django yönetimi"
+
+#: contrib/admin/templates/admin/500.html:4
+msgid "Server error"
+msgstr "Sunucu hatası"
+
+#: contrib/admin/templates/admin/500.html:6
+msgid "Server error (500)"
+msgstr "Sunucu hatası (500)"
+
+#: contrib/admin/templates/admin/500.html:9
+msgid "Server Error <em>(500)</em>"
+msgstr "Sunucu Hatası <em>(500)</em>"
+
+#: contrib/admin/templates/admin/500.html:10
+msgid ""
+"There's been an error. It's been reported to the site administrators via e-"
+"mail and should be fixed shortly. Thanks for your patience."
+msgstr ""
+"Bir hata oluştu. Hata, e-psota ile site yöneticisine bildirildi ve kısa süre "
+"içinde çözülecktir. Sabrınız için teşekkürler."
+
+#: contrib/admin/templates/admin/invalid_setup.html:8
+msgid ""
+"Something's wrong with your database installation. Make sure the appropriate "
+"database tables have been created, and make sure the database is readable by "
+"the appropriate user."
+msgstr ""
+"Veritabanı kurulumu ile ilgili bir problem var. İlgili veritabanı "
+"tablolarının kurulu olduğundan ve veritabanının ilgili kullanıcı tarafından "
+"okunabilir olduÄŸundan emin olun."
+
+#: contrib/admin/templates/admin/index.html:17
+#, python-format
+msgid "Models available in the %(name)s application."
+msgstr "%(name)s uygulamasındaki modeller."
+
+#: contrib/admin/templates/admin/index.html:18
+#, python-format
+msgid "%(name)s"
+msgstr "%(name)s"
+
+#: contrib/admin/templates/admin/index.html:28
+#: contrib/admin/templates/admin/change_form.html:15
+msgid "Add"
+msgstr "Ekle"
+
+#: contrib/admin/templates/admin/index.html:34
+msgid "Change"
+msgstr "DeÄŸiÅŸtir"
+
+#: contrib/admin/templates/admin/index.html:44
+msgid "You don't have permission to edit anything."
+msgstr "İşlem yapmaya yetkiniz yok."
+
+#: contrib/admin/templates/admin/index.html:52
+msgid "Recent Actions"
+msgstr "Geçmiş İşlemler"
+
+#: contrib/admin/templates/admin/index.html:53
+msgid "My Actions"
+msgstr "İşlemlerim"
+
+#: contrib/admin/templates/admin/index.html:57
+msgid "None available"
+msgstr "Hiç yok"
+
+#: contrib/admin/templates/admin/404.html:4
+#: contrib/admin/templates/admin/404.html:8
+msgid "Page not found"
+msgstr "Sayfa bulunamadı"
+
+#: contrib/admin/templates/admin/404.html:10
+msgid "We're sorry, but the requested page could not be found."
+msgstr "Üzgünüm, aradığınız sayfa bulunamadı."
+
+#: contrib/admin/templates/admin/filters.html:4
+msgid "Filter"
+msgstr "Filtrele"
+
+#: contrib/admin/templates/admin/change_form.html:21
+msgid "View on site"
+msgstr "Sitede görüntüle"
+
+#: contrib/admin/templates/admin/change_form.html:30
+msgid "Please correct the error below."
+msgid_plural "Please correct the errors below."
+msgstr[0] "Lütfen aşağıdaki hatayı düzeltin."
+msgstr[1] "Lütfen aşağıdaki hataları düzeltin."
+
+#: contrib/admin/templates/admin/change_form.html:48
+msgid "Ordering"
+msgstr "Sıralama:"
+
+#: contrib/admin/templates/admin/change_form.html:51
+msgid "Order:"
+msgstr "Sıra:"
+
+#: contrib/admin/templates/admin/login.html:22
+msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
+msgstr "<a href=\"/password_reset/\">Åžifrenizi mi unuttunuz?</a>"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:9
+#: contrib/admin/templates/admin/submit_line.html:3
+msgid "Delete"
+msgstr "Sil"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:14
+#, python-format
+msgid ""
+"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
+"related objects, but your account doesn't have permission to delete the "
+"following types of objects:"
+msgstr ""
+"'%(escaped_object)s' isimli %(object_name)s nesnesini silmek, bağlantılı "
+"nesnelerin silinmesini gerektiriyor, ancak aşağıdaki nesneleri silme "
+"yetkiniz yok."
+
+#: contrib/admin/templates/admin/delete_confirmation.html:21
+#, python-format
+msgid ""
+"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
+"All of the following related items will be deleted:"
+msgstr ""
+"\"%(escaped_object)s\" isimli %(object_name)s nesnesini silmek "
+"istediğinizdenemin misiniz? Aşağıdaki bağlantılı öğeler silinecek:"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:26
+msgid "Yes, I'm sure"
+msgstr "Evet, eminim"
+
+#: contrib/admin/templates/admin/base.html:25
+msgid "Welcome,"
+msgstr "HoÅŸgeldin,"
+
+#: contrib/admin/templates/admin/submit_line.html:4
+msgid "Save as new"
+msgstr "Yeni olarak kaydet"
+
+#: contrib/admin/templates/admin/submit_line.html:5
+msgid "Save and add another"
+msgstr "Kaydet ve yeni bir tane ekle"
+
+#: contrib/admin/templates/admin/submit_line.html:6
+msgid "Save and continue editing"
+msgstr "Kaydet ve düzenlemeye devam et"
+
+#: contrib/admin/templates/admin/submit_line.html:7
+msgid "Save"
+msgstr "Kaydet"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:6
+msgid ""
+"First, enter a username and password. Then, you'll be able to edit more user "
+"options."
+msgstr "Önce bir kullanıcı adı ve parola girin. Daha sonra daha fazla bilgi girebilirsiniz."
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:12
+msgid "Username"
+msgstr "Kullanıcı"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:18
+msgid "Password"
+msgstr "Parola"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:23
+msgid "Password (again)"
+msgstr "Parola (tekrar)"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:24
+msgid "Enter the same password as above, for verification."
+msgstr "Onaylamak için, yukarıdaki parolanın aynısını girin."
+
+#: contrib/admin/templates/registration/password_change_done.html:4
+#: contrib/admin/templates/registration/password_change_form.html:4
+#: contrib/admin/templates/registration/password_change_form.html:6
+#: contrib/admin/templates/registration/password_change_form.html:10
+msgid "Password change"
+msgstr "Parola deÄŸiÅŸimi"
+
+#: contrib/admin/templates/registration/password_change_done.html:6
+#: contrib/admin/templates/registration/password_change_done.html:10
+msgid "Password change successful"
+msgstr "Parola değişimi başarılı"
+
+#: contrib/admin/templates/registration/password_change_done.html:12
+msgid "Your password was changed."
+msgstr "Parolanız değiştirildi."
+
+#: contrib/admin/templates/registration/password_reset_form.html:4
+#: contrib/admin/templates/registration/password_reset_form.html:6
+#: contrib/admin/templates/registration/password_reset_form.html:10
+#: contrib/admin/templates/registration/password_reset_done.html:4
+msgid "Password reset"
+msgstr "Parolayı sıfırla"
+
+#: contrib/admin/templates/registration/password_reset_form.html:12
+msgid ""
+"Forgotten your password? Enter your e-mail address below, and we'll reset "
+"your password and e-mail the new one to you."
+msgstr ""
+"Parolanızı mı unuttunuz? E-posta adresinizi aşağıya girin, parolanızı "
+"sıfırlayalım ve e-posta adresinize gönderelim."
+
+#: contrib/admin/templates/registration/password_reset_form.html:16
+msgid "E-mail address:"
+msgstr "E-posta adresi:"
+
+#: contrib/admin/templates/registration/password_reset_form.html:16
+msgid "Reset my password"
+msgstr "Parolamı sıfırla"
+
+#: contrib/admin/templates/registration/logged_out.html:8
+msgid "Thanks for spending some quality time with the Web site today."
+msgstr "Web sitesinde zaman geçirdiğiniz için teşekkür ederiz."
+
+#: contrib/admin/templates/registration/logged_out.html:10
+msgid "Log in again"
+msgstr "Tekrar giriÅŸ yap"
+
+#: contrib/admin/templates/registration/password_reset_done.html:6
+#: contrib/admin/templates/registration/password_reset_done.html:10
+msgid "Password reset successful"
+msgstr "Parola sıfırlandı."
+
+#: contrib/admin/templates/registration/password_reset_done.html:12
+msgid ""
+"We've e-mailed a new password to the e-mail address you submitted. You "
+"should be receiving it shortly."
+msgstr ""
+"Yeni şifreniz, e-posta adresinize gönderildi, kısa süre içinde size "
+"ulaşacaktır."
+
+#: contrib/admin/templates/registration/password_change_form.html:12
+msgid ""
+"Please enter your old password, for security's sake, and then enter your new "
+"password twice so we can verify you typed it in correctly."
+msgstr ""
+"Güvenliğiniz için, lütfen eski parolanızı girin, sonra da yeni şifrenizi iki "
+"kere girin ve böylece doğru yazdığınızdan emin olun."
+
+#: contrib/admin/templates/registration/password_change_form.html:17
+msgid "Old password:"
+msgstr "Eski parola:"
+
+#: contrib/admin/templates/registration/password_change_form.html:19
+msgid "New password:"
+msgstr "Yeni parola:"
+
+#: contrib/admin/templates/registration/password_change_form.html:21
+msgid "Confirm password:"
+msgstr "Parolayı onayla:"
+
+#: contrib/admin/templates/registration/password_change_form.html:23
+msgid "Change my password"
+msgstr "Parolamı değiştir"
+
+#: contrib/admin/templates/registration/password_reset_email.html:2
+msgid "You're receiving this e-mail because you requested a password reset"
+msgstr "Bu e-postayı aldınız çünkü "
+
+#: contrib/admin/templates/registration/password_reset_email.html:3
+#, python-format
+msgid "for your user account at %(site_name)s"
+msgstr ""
+"%(site_name)s adresindeki kullanıcı hesabınız için parola sıfırlama "
+"talebinde bulundunuz."
+
+#: contrib/admin/templates/registration/password_reset_email.html:5
+#, python-format
+msgid "Your new password is: %(new_password)s"
+msgstr "Yeni parolanız: %(new_password)s"
+
+#: contrib/admin/templates/registration/password_reset_email.html:7
+msgid "Feel free to change this password by going to this page:"
+msgstr "Parolanızı değiştirmek için bu adrese gidebilirsiniz:"
+
+#: contrib/admin/templates/registration/password_reset_email.html:11
+msgid "Your username, in case you've forgotten:"
+msgstr "Unutma ihtimaline karşı, kullanıcı adınız:"
+
+#: contrib/admin/templates/registration/password_reset_email.html:13
+msgid "Thanks for using our site!"
+msgstr "Teşekkürler!"
+
+#: contrib/admin/templates/registration/password_reset_email.html:15
+#, python-format
+msgid "The %(site_name)s team"
+msgstr "%(site_name)s Ekibi"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+msgid "Bookmarklets"
+msgstr "Kısayollar"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:5
+msgid "Documentation bookmarklets"
+msgstr "Döküman kısayolları"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:9
+msgid ""
+"\n"
+"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n"
+"toolbar, or right-click the link and add it to your bookmarks. Now you can\n"
+"select the bookmarklet from any page in the site. Note that some of these\n"
+"bookmarklets require you to be viewing the site from a computer designated\n"
+"as \"internal\" (talk to your system administrator if you aren't sure if\n"
+"your computer is \"internal\").</p>\n"
+msgstr ""
+"\n"
+"<p class=\"help\">Kısayolları kullanabilmek için, bağlantıyı tarayıcınızdaki "
+"araç çubuğuna sürükleyin, ya da sağ tıklayıp sık kullanılan adresler "
+"listenize ekleyin. Bazı kısayollar, uygulamayı çalıştıran sunucu ile aynı "
+"adreste bulunan istemciler tarafından kullanılabilir.</p>\n"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:19
+msgid "Documentation for this page"
+msgstr "Bu sayfa için dökümantasyon"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:20
+msgid ""
+"Jumps you from any page to the documentation for the view that generates "
+"that page."
+msgstr "Sizi, bu sayfayı üreten betiğin dökümantasyonuna yönlendirir."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:22
+msgid "Show object ID"
+msgstr "Nesne numarasını göster"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:23
+msgid ""
+"Shows the content-type and unique ID for pages that represent a single "
+"object."
+msgstr "Tek bir nesneyi temsil eden sayfaların içerik türünü ve numarasını gösterir."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:25
+msgid "Edit this object (current window)"
+msgstr "Nesneyi düzenle (aynı pencerede)"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:26
+msgid "Jumps to the admin page for pages that represent a single object."
+msgstr "Tek bir nesneyi temsil eden sayfaların yönetim sayfasını gösterir."
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:28
+msgid "Edit this object (new window)"
+msgstr "Nesneyi düzenle (yeni pencerede)"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:29
+msgid "As above, but opens the admin page in a new window."
+msgstr "Yukarıdaki gibi, ancak yönetim sayfasını yeni bir pencerede açar."
+
+#: template/defaultfilters.py:401
+msgid "yes,no,maybe"
+msgstr "evet,hayır,olabilir"
+
diff --git a/django/conf/locale/tr/LC_MESSAGES/djangojs.mo b/django/conf/locale/tr/LC_MESSAGES/djangojs.mo
new file mode 100644
index 0000000000..1119203925
--- /dev/null
+++ b/django/conf/locale/tr/LC_MESSAGES/djangojs.mo
Binary files differ
diff --git a/django/conf/locale/tr/LC_MESSAGES/djangojs.po b/django/conf/locale/tr/LC_MESSAGES/djangojs.po
new file mode 100644
index 0000000000..35928b9c03
--- /dev/null
+++ b/django/conf/locale/tr/LC_MESSAGES/djangojs.po
@@ -0,0 +1,109 @@
+# Django 0.95
+# Copyright (C) 2006 Django
+# This file is distributed under the same license as the Django package.
+# Bahadır Kandemir <bahadir@pardus.org.tr>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Django 0.95\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-09-30 01:31+0300\n"
+"PO-Revision-Date: 2006-09-30 01:31+0300\n"
+"Last-Translator: Bahadır Kandemir <bahadir@pardus.org.tr>\n"
+"Language-Team: Bahadır Kandemir <bahadir@pardus.org.tr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: contrib/admin/media/js/SelectFilter2.js:33
+#, perl-format
+msgid "Available %s"
+msgstr "Mevcut %s"
+
+#: contrib/admin/media/js/SelectFilter2.js:41
+msgid "Choose all"
+msgstr "Hepsini seç"
+
+#: contrib/admin/media/js/SelectFilter2.js:46
+msgid "Add"
+msgstr "Ekle"
+
+#: contrib/admin/media/js/SelectFilter2.js:48
+msgid "Remove"
+msgstr "Kaldır"
+
+#: contrib/admin/media/js/SelectFilter2.js:53
+#, perl-format
+msgid "Chosen %s"
+msgstr "Seçilen %s"
+
+#: contrib/admin/media/js/SelectFilter2.js:54
+msgid "Select your choice(s) and click "
+msgstr "Seçiminizi yapın ve tıklayın "
+
+#: contrib/admin/media/js/SelectFilter2.js:59
+msgid "Clear all"
+msgstr "Hepsini temizle"
+
+#: contrib/admin/media/js/dateparse.js:26
+#: contrib/admin/media/js/calendar.js:24
+msgid ""
+"January February March April May June July August September October November "
+"December"
+msgstr "Ocak Şubat Mart Nisan Mayıs Haziran Temmuz Ağustos Eylül Ekim Kasım "
+"Aralık"
+
+#: contrib/admin/media/js/dateparse.js:27
+msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
+msgstr "Pazar Pazartesi Salı Çarşamba Perşembe Cuma Cumartesi"
+
+#: contrib/admin/media/js/calendar.js:25
+msgid "S M T W T F S"
+msgstr "P P S Ç P C C"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
+msgid "Now"
+msgstr "Åžimdi"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
+msgid "Clock"
+msgstr "Saat"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
+msgid "Choose a time"
+msgstr "Saat seçin"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
+msgid "Midnight"
+msgstr "Geceyarısı"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
+msgid "6 a.m."
+msgstr "Sabah 6"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
+msgid "Noon"
+msgstr "Öğle"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
+msgid "Cancel"
+msgstr "İptal"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
+msgid "Today"
+msgstr "Bugün"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
+msgid "Calendar"
+msgstr "Takvim"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
+msgid "Yesterday"
+msgstr "Dün"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
+msgid "Tomorrow"
+msgstr "Yarın"
diff --git a/django/conf/locale/zh_CN/LC_MESSAGES/django.mo b/django/conf/locale/zh_CN/LC_MESSAGES/django.mo
index 9fc04b9395..0d6bf90c0e 100644
--- a/django/conf/locale/zh_CN/LC_MESSAGES/django.mo
+++ b/django/conf/locale/zh_CN/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/zh_CN/LC_MESSAGES/django.po b/django/conf/locale/zh_CN/LC_MESSAGES/django.po
index 7718514299..2552b677bd 100644
--- a/django/conf/locale/zh_CN/LC_MESSAGES/django.po
+++ b/django/conf/locale/zh_CN/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: django v1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:10+0200\n"
-"PO-Revision-Date: 2006-05-17 13:47+0800\n"
+"PO-Revision-Date: 2006-09-01 22:05+0800\n"
"Last-Translator: limodou <limodou@gmail.com>\n"
"Language-Team: Simplified Chinese <limodou@gmail.com>\n"
"MIME-Version: 1.0\n"
@@ -1167,7 +1167,7 @@ msgstr "个人信æ¯"
#: contrib/auth/models.py:77
msgid "Permissions"
-msgstr "许å¯"
+msgstr "æƒé™"
#: contrib/auth/models.py:78
msgid "Important dates"
diff --git a/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo b/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo
index 983a8a7154..ec7580a862 100644
--- a/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo
+++ b/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo
Binary files differ
diff --git a/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.po b/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.po
index 1e9e7dbeb7..610e61d17a 100644
--- a/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.po
+++ b/django/conf/locale/zh_CN/LC_MESSAGES/djangojs.po
@@ -3,22 +3,21 @@
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
-#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
+"Project-Id-Version: Django 0.95\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-03-21 18:43+0800\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <max@exoweb.net>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"PO-Revision-Date: 2006-09-25 08:35+0800\n"
+"Last-Translator: limodou <limodou@gmail.com>\n"
+"Language-Team: limodou <limodou@gmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
msgid "Available %s"
-msgstr "å¯è¡Œ %s"
+msgstr "å¯ç”¨ %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
@@ -30,34 +29,32 @@ msgstr "增加"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
-msgstr "移出"
+msgstr "删除"
#: contrib/admin/media/js/SelectFilter2.js:53
msgid "Chosen %s"
-msgstr "选择 %s"
+msgstr "选中的 %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
-msgstr "挑选你的选择并且点击 "
+msgstr "选择并点击 "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
-msgstr "清除所有"
+msgstr "清除全部"
#: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24
-msgid ""
-"January February March April May June July August September October November "
-"December"
+msgid "January February March April May June July August September October November December"
msgstr "一月 二月 三月 四月 五月 六月 六月 七月 八月 乿œˆ åæœˆ å一月 å二月"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
-msgstr "星期天 星期一 星期二 星期三 星期四 星期五 星期六"
+msgstr "星期日 星期一 星期二 星期三 星期四 星期五 星期六"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
-msgstr "æ—¥ 月 ç« æ°´ 木 金 土"
+msgstr "日 一 二 三 四 五 六"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
@@ -105,3 +102,4 @@ msgstr "昨天"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "明天"
+
diff --git a/django/conf/project_template/settings.py b/django/conf/project_template/settings.py
index 14da715db5..d6f34a28db 100644
--- a/django/conf/project_template/settings.py
+++ b/django/conf/project_template/settings.py
@@ -27,6 +27,10 @@ LANGUAGE_CODE = 'en-us'
SITE_ID = 1
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = ''
@@ -60,8 +64,9 @@ MIDDLEWARE_CLASSES = (
ROOT_URLCONF = '{{ project_name }}.urls'
TEMPLATE_DIRS = (
- # Put strings here, like "/home/html/django_templates".
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
)
INSTALLED_APPS = (
diff --git a/django/conf/urls/defaults.py b/django/conf/urls/defaults.py
index 07611c5147..17fe603d96 100644
--- a/django/conf/urls/defaults.py
+++ b/django/conf/urls/defaults.py
@@ -10,8 +10,10 @@ include = lambda urlconf_module: [urlconf_module]
def patterns(prefix, *tuples):
pattern_list = []
for t in tuples:
- if type(t[1]) == list:
- pattern_list.append(RegexURLResolver(t[0], t[1][0]))
+ regex, view_or_include = t[:2]
+ default_kwargs = t[2:]
+ if type(view_or_include) == list:
+ pattern_list.append(RegexURLResolver(regex, view_or_include[0], *default_kwargs))
else:
- pattern_list.append(RegexURLPattern(t[0], prefix and (prefix + '.' + t[1]) or t[1], *t[2:]))
+ pattern_list.append(RegexURLPattern(regex, prefix and (prefix + '.' + view_or_include) or view_or_include, *default_kwargs))
return pattern_list
diff --git a/django/contrib/admin/filterspecs.py b/django/contrib/admin/filterspecs.py
index 25376be12a..8c2b82147e 100644
--- a/django/contrib/admin/filterspecs.py
+++ b/django/contrib/admin/filterspecs.py
@@ -123,7 +123,7 @@ class DateFieldFilterSpec(FilterSpec):
def choices(self, cl):
for title, param_dict in self.links:
yield {'selected': self.date_params == param_dict,
- 'query_string': cl.get_query_string(param_dict, self.field_generic),
+ 'query_string': cl.get_query_string(param_dict, [self.field_generic]),
'display': title}
FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)
diff --git a/django/contrib/admin/media/css/changelists.css b/django/contrib/admin/media/css/changelists.css
index fbcbe56f06..4834be4685 100644
--- a/django/contrib/admin/media/css/changelists.css
+++ b/django/contrib/admin/media/css/changelists.css
@@ -42,9 +42,9 @@
/* PAGINATOR */
.paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; }
-.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
+.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
.paginator a.showall { padding:0 !important; border:none !important; }
.paginator a.showall:hover { color:#036 !important; background:transparent !important; }
-.paginator .end { border-width:2px !important; margin-right:6px; }
+.paginator .end { border-width:2px !important; margin-right:6px; }
.paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; }
.paginator a:hover { color:white; background:#5b80b2; border-color:#036; }
diff --git a/django/contrib/admin/media/css/forms.css b/django/contrib/admin/media/css/forms.css
index b66f268fec..468e06a8a2 100644
--- a/django/contrib/admin/media/css/forms.css
+++ b/django/contrib/admin/media/css/forms.css
@@ -7,10 +7,10 @@
form .form-row p { padding-left:0; font-size:11px; }
/* FORM LABELS */
-form h4 { margin:0 !important; padding:0 !important; border:none !important; }
+form h4 { margin:0 !important; padding:0 !important; border:none !important; }
label { font-weight:normal !important; color:#666; font-size:12px; }
label.inline { margin-left:20px; }
-.required label, label.required { font-weight:bold !important; color:#333 !important; }
+.required label, label.required { font-weight:bold !important; color:#333 !important; }
/* RADIO BUTTONS */
form ul.radiolist li { list-style-type:none; }
diff --git a/django/contrib/admin/media/css/global.css b/django/contrib/admin/media/css/global.css
index a87931681c..d50601bde7 100644
--- a/django/contrib/admin/media/css/global.css
+++ b/django/contrib/admin/media/css/global.css
@@ -1,4 +1,4 @@
-body { margin:0; padding:0; font-size:12px; font-family:"Lucida Grande","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; }
+body { margin:0; padding:0; font-size:12px; font-family:"Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; }
/* LINKS */
a:link, a:visited { color: #5b80b2; text-decoration:none; }
@@ -31,7 +31,7 @@ fieldset { margin:0; padding:0; }
blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; }
code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; background:inherit; color:#666; font-size:11px; }
pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
-code strong { color:#930; }
+code strong { color:#930; }
hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
/* TEXT STYLES & MODIFIERS */
@@ -81,7 +81,7 @@ table.orderable tbody tr td:first-child { padding-left:14px; background-image:ur
table.orderable-initalized .order-cell, body>tr>td.order-cell { display:none; }
/* FORM DEFAULTS */
-input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
+input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
textarea { vertical-align:top !important; }
input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
@@ -92,7 +92,7 @@ input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2
input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; }
/* MODULES */
-.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
+.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
.module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
.module blockquote { margin-left:12px; }
.module ul, .module ol { margin-left:1.5em; }
diff --git a/django/contrib/admin/media/css/layout.css b/django/contrib/admin/media/css/layout.css
index befe4fc1ca..17c52861ee 100644
--- a/django/contrib/admin/media/css/layout.css
+++ b/django/contrib/admin/media/css/layout.css
@@ -4,7 +4,7 @@
#header { width:100%; }
#content-main { float:left; width:100%; }
#content-related { float:right; width:18em; position:relative; margin-right:-19em; }
-#footer { clear:both; padding:10px; }
+#footer { clear:both; padding:10px; }
/* COLUMN TYPES */
.colMS { margin-right:20em !important; }
@@ -16,14 +16,14 @@
.dashboard #content { width:500px; }
/* HEADER */
-#header { background:#417690; color:#ffc; overflow:hidden; }
+#header { background:#417690; color:#ffc; overflow:hidden; }
#header a:link, #header a:visited { color:white; }
#header a:hover { text-decoration:underline; }
#branding h1 { padding:0 10px; font-size:18px; margin:8px 0; font-weight:normal; color:#f4f379; }
#branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; }
-#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
+#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
/* SIDEBAR */
#content-related h3 { font-size:12px; color:#666; margin-bottom:3px; }
#content-related h4 { font-size:11px; }
-#content-related .module h2 { background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; } \ No newline at end of file
+#content-related .module h2 { background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; } \ No newline at end of file
diff --git a/django/contrib/admin/media/css/rtl.css b/django/contrib/admin/media/css/rtl.css
index c29391cabf..1974e7c2ec 100644
--- a/django/contrib/admin/media/css/rtl.css
+++ b/django/contrib/admin/media/css/rtl.css
@@ -16,7 +16,7 @@ th { text-align: right; }
/* layout styles */
-#user-tools { right:auto; left:0; text-align:left; }
+#user-tools { right:auto; left:0; text-align:left; }
div.breadcrumbs { text-align:right; }
#content-main { float:right;}
#content-related { float:left; margin-left:-19em; margin-right:auto;}
diff --git a/django/contrib/admin/media/js/admin/CollapsedFieldsets.js b/django/contrib/admin/media/js/admin/CollapsedFieldsets.js
index 97f0a68d04..c8426db228 100644
--- a/django/contrib/admin/media/js/admin/CollapsedFieldsets.js
+++ b/django/contrib/admin/media/js/admin/CollapsedFieldsets.js
@@ -3,83 +3,83 @@
// link when the fieldset is visible.
function findForm(node) {
- // returns the node of the form containing the given node
- if (node.tagName.toLowerCase() != 'form') {
- return findForm(node.parentNode);
- }
- return node;
+ // returns the node of the form containing the given node
+ if (node.tagName.toLowerCase() != 'form') {
+ return findForm(node.parentNode);
+ }
+ return node;
}
var CollapsedFieldsets = {
- collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with.
- collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
- collapsed_class: 'collapsed',
- init: function() {
- var fieldsets = document.getElementsByTagName('fieldset');
- var collapsed_seen = false;
- for (var i = 0, fs; fs = fieldsets[i]; i++) {
- // Collapse this fieldset if it has the correct class, and if it
- // doesn't have any errors. (Collapsing shouldn't apply in the case
- // of error messages.)
- if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
- collapsed_seen = true;
- // Give it an additional class, used by CSS to hide it.
- fs.className += ' ' + CollapsedFieldsets.collapsed_class;
- // (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
- var collapse_link = document.createElement('a');
- collapse_link.className = 'collapse-toggle';
- collapse_link.id = 'fieldsetcollapser' + i;
- collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
- collapse_link.href = '#';
- collapse_link.innerHTML = gettext('Show');
- var h2 = fs.getElementsByTagName('h2')[0];
- h2.appendChild(document.createTextNode(' ('));
- h2.appendChild(collapse_link);
- h2.appendChild(document.createTextNode(')'));
- }
- }
- if (collapsed_seen) {
- // Expand all collapsed fieldsets when form is submitted.
- addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
- }
- },
- fieldset_has_errors: function(fs) {
- // Returns true if any fields in the fieldset have validation errors.
- var divs = fs.getElementsByTagName('div');
- for (var i=0; i<divs.length; i++) {
- if (divs[i].className.match(/\berror\b/)) {
- return true;
- }
- }
- return false;
- },
- show: function(fieldset_index) {
- var fs = document.getElementsByTagName('fieldset')[fieldset_index];
- // Remove the class name that causes the "display: none".
- fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
- // Toggle the "Show" link to a "Hide" link
- var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
- collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
- collapse_link.innerHTML = gettext('Hide');
- },
- hide: function(fieldset_index) {
- var fs = document.getElementsByTagName('fieldset')[fieldset_index];
- // Add the class name that causes the "display: none".
- fs.className += ' ' + CollapsedFieldsets.collapsed_class;
- // Toggle the "Hide" link to a "Show" link
- var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
+ collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with.
+ collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
+ collapsed_class: 'collapsed',
+ init: function() {
+ var fieldsets = document.getElementsByTagName('fieldset');
+ var collapsed_seen = false;
+ for (var i = 0, fs; fs = fieldsets[i]; i++) {
+ // Collapse this fieldset if it has the correct class, and if it
+ // doesn't have any errors. (Collapsing shouldn't apply in the case
+ // of error messages.)
+ if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
+ collapsed_seen = true;
+ // Give it an additional class, used by CSS to hide it.
+ fs.className += ' ' + CollapsedFieldsets.collapsed_class;
+ // (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
+ var collapse_link = document.createElement('a');
+ collapse_link.className = 'collapse-toggle';
+ collapse_link.id = 'fieldsetcollapser' + i;
+ collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
+ collapse_link.href = '#';
+ collapse_link.innerHTML = gettext('Show');
+ var h2 = fs.getElementsByTagName('h2')[0];
+ h2.appendChild(document.createTextNode(' ('));
+ h2.appendChild(collapse_link);
+ h2.appendChild(document.createTextNode(')'));
+ }
+ }
+ if (collapsed_seen) {
+ // Expand all collapsed fieldsets when form is submitted.
+ addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
+ }
+ },
+ fieldset_has_errors: function(fs) {
+ // Returns true if any fields in the fieldset have validation errors.
+ var divs = fs.getElementsByTagName('div');
+ for (var i=0; i<divs.length; i++) {
+ if (divs[i].className.match(/\berror\b/)) {
+ return true;
+ }
+ }
+ return false;
+ },
+ show: function(fieldset_index) {
+ var fs = document.getElementsByTagName('fieldset')[fieldset_index];
+ // Remove the class name that causes the "display: none".
+ fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
+ // Toggle the "Show" link to a "Hide" link
+ var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
+ collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
+ collapse_link.innerHTML = gettext('Hide');
+ },
+ hide: function(fieldset_index) {
+ var fs = document.getElementsByTagName('fieldset')[fieldset_index];
+ // Add the class name that causes the "display: none".
+ fs.className += ' ' + CollapsedFieldsets.collapsed_class;
+ // Toggle the "Hide" link to a "Show" link
+ var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;');
- collapse_link.innerHTML = gettext('Show');
- },
+ collapse_link.innerHTML = gettext('Show');
+ },
- uncollapse_all: function() {
- var fieldsets = document.getElementsByTagName('fieldset');
- for (var i=0; i<fieldsets.length; i++) {
- if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
- CollapsedFieldsets.show(i);
- }
- }
- }
+ uncollapse_all: function() {
+ var fieldsets = document.getElementsByTagName('fieldset');
+ for (var i=0; i<fieldsets.length; i++) {
+ if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
+ CollapsedFieldsets.show(i);
+ }
+ }
+ }
}
addEvent(window, 'load', CollapsedFieldsets.init);
diff --git a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js
index 35199baf84..77c536b865 100644
--- a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js
+++ b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js
@@ -8,7 +8,9 @@ var DateTimeShortcuts = {
clockInputs: [],
calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
calendarDivName2: 'calendarin', // name of <div> that contains calendar
+ calendarLinkName: 'calendarlink',// name of the link that is used to toggle
clockDivName: 'clockbox', // name of clock <div> that gets toggled
+ clockLinkName: 'clocklink', // name of the link that is used to toggle
admin_media_prefix: '',
init: function() {
// Deduce admin_media_prefix by looking at the <script>s in the
@@ -46,6 +48,7 @@ var DateTimeShortcuts = {
now_link.appendChild(document.createTextNode(gettext('Now')));
var clock_link = document.createElement('a');
clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
+ clock_link.id = DateTimeShortcuts.clockLinkName + num;
quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_clock.gif', 'alt', gettext('Clock'));
shortcuts_span.appendChild(document.createTextNode('\240'));
shortcuts_span.appendChild(now_link);
@@ -69,17 +72,6 @@ var DateTimeShortcuts = {
var clock_box = document.createElement('div');
clock_box.style.display = 'none';
clock_box.style.position = 'absolute';
- if (getStyle(document.body,'direction')!='rtl') {
- clock_box.style.left = findPosX(clock_link) + 17 + 'px';
- }
- else {
- // since style's width is in em, it'd be tough to calculate
- // px value of it. let's use an estimated px for now
- // TODO: IE returns wrong value for findPosX when in rtl mode
- // (it returns as it was left aligned), needs to be fixed.
- clock_box.style.left = findPosX(clock_link) - 110 + 'px';
- }
- clock_box.style.top = findPosY(clock_link) - 30 + 'px';
clock_box.className = 'clockbox module';
clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
document.body.appendChild(clock_box);
@@ -98,7 +90,25 @@ var DateTimeShortcuts = {
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
},
openClock: function(num) {
- document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'block';
+ var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
+ var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
+
+ // Recalculate the clockbox position
+ // is it left-to-right or right-to-left layout ?
+ if (getStyle(document.body,'direction')!='rtl') {
+ clock_box.style.left = findPosX(clock_link) + 17 + 'px';
+ }
+ else {
+ // since style's width is in em, it'd be tough to calculate
+ // px value of it. let's use an estimated px for now
+ // TODO: IE returns wrong value for findPosX when in rtl mode
+ // (it returns as it was left aligned), needs to be fixed.
+ clock_box.style.left = findPosX(clock_link) - 110 + 'px';
+ }
+ clock_box.style.top = findPosY(clock_link) - 30 + 'px';
+
+ // Show the clock box
+ clock_box.style.display = 'block';
addEvent(window, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
},
dismissClock: function(num) {
@@ -123,6 +133,7 @@ var DateTimeShortcuts = {
today_link.appendChild(document.createTextNode(gettext('Today')));
var cal_link = document.createElement('a');
cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
+ cal_link.id = DateTimeShortcuts.calendarLinkName + num;
quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar'));
shortcuts_span.appendChild(document.createTextNode('\240'));
shortcuts_span.appendChild(today_link);
@@ -149,18 +160,6 @@ var DateTimeShortcuts = {
var cal_box = document.createElement('div');
cal_box.style.display = 'none';
cal_box.style.position = 'absolute';
- // is it left-to-right or right-to-left layout ?
- if (getStyle(document.body,'direction')!='rtl') {
- cal_box.style.left = findPosX(cal_link) + 17 + 'px';
- }
- else {
- // since style's width is in em, it'd be tough to calculate
- // px value of it. let's use an estimated px for now
- // TODO: IE returns wrong value for findPosX when in rtl mode
- // (it returns as it was left aligned), needs to be fixed.
- cal_box.style.left = findPosX(cal_link) - 180 + 'px';
- }
- cal_box.style.top = findPosY(cal_link) - 75 + 'px';
cal_box.className = 'calendarbox module';
cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
document.body.appendChild(cal_box);
@@ -172,7 +171,6 @@ var DateTimeShortcuts = {
cal_nav_prev.className = 'calendarnav-previous';
var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
cal_nav_next.className = 'calendarnav-next';
- cal_box.appendChild(cal_nav);
// main box
var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
@@ -195,7 +193,24 @@ var DateTimeShortcuts = {
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
},
openCalendar: function(num) {
- document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'block';
+ var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
+ var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
+
+ // Recalculate the clockbox position
+ // is it left-to-right or right-to-left layout ?
+ if (getStyle(document.body,'direction')!='rtl') {
+ cal_box.style.left = findPosX(cal_link) + 17 + 'px';
+ }
+ else {
+ // since style's width is in em, it'd be tough to calculate
+ // px value of it. let's use an estimated px for now
+ // TODO: IE returns wrong value for findPosX when in rtl mode
+ // (it returns as it was left aligned), needs to be fixed.
+ cal_box.style.left = findPosX(cal_link) - 180 + 'px';
+ }
+ cal_box.style.top = findPosY(cal_link) - 75 + 'px';
+
+ cal_box.style.display = 'block';
addEvent(window, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
},
dismissCalendar: function(num) {
diff --git a/django/contrib/admin/media/js/admin/RelatedObjectLookups.js b/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
index cf57fc4dfb..db4ed1a9d1 100644
--- a/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
+++ b/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
@@ -11,7 +11,7 @@ function showRelatedObjectLookupPopup(triggeringLink) {
} else {
href = triggeringLink.href + '?pop=1';
}
- var win = window.open(href, name, 'height=500,width=740,resizable=yes,scrollbars=yes');
+ var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
}
diff --git a/django/contrib/admin/templates/admin/auth/user/add_form.html b/django/contrib/admin/templates/admin/auth/user/add_form.html
new file mode 100644
index 0000000000..139fa6a75e
--- /dev/null
+++ b/django/contrib/admin/templates/admin/auth/user/add_form.html
@@ -0,0 +1,28 @@
+{% extends "admin/change_form.html" %}
+{% load i18n %}
+
+{% block after_field_sets %}
+
+<p>{% trans "First, enter a username and password. Then, you'll be able to edit more user options." %}</p>
+
+<fieldset class="module aligned">
+
+<div class="form-row">
+ {{ form.username.html_error_list }}
+ <label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }}
+ <p class="help">{{ username_help_text }}</p>
+</div>
+
+<div class="form-row">
+ {{ form.password1.html_error_list }}
+ <label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
+</div>
+
+<div class="form-row">
+ {{ form.password2.html_error_list }}
+ <label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
+ <p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
+</div>
+
+</fieldset>
+{% endblock %}
diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html
index 67fe27529c..b63604b268 100644
--- a/django/contrib/admin/templates/admin/base.html
+++ b/django/contrib/admin/templates/admin/base.html
@@ -6,6 +6,7 @@
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %}
{% block extrastyle %}{% endblock %}
{% block extrahead %}{% endblock %}
+{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
</head>
{% load i18n %}
@@ -20,13 +21,13 @@
<div id="branding">
{% block branding %}{% endblock %}
</div>
- {% if not user.is_anonymous %}{% if user.is_staff %}
+ {% if user.is_authenticated and user.is_staff %}
<div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name|escape }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div>
- {% endif %}{% endif %}
+ {% endif %}
{% block nav-global %}{% endblock %}
</div>
<!-- END Header -->
- {% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} &rsaquo; {{ title }}{% endif %}</div>{% endblock %}
+ {% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} &rsaquo; {{ title|escape }}{% endif %}</div>{% endblock %}
{% endif %}
{% if messages %}
@@ -36,7 +37,7 @@
<!-- Content -->
<div id="content" class="{% block coltype %}colM{% endblock %}">
{% block pretitle %}{% endblock %}
- {% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
+ {% block content_title %}{% if title %}<h1>{{ title|escape }}</h1>{% endif %}{% endblock %}
{% block content %}{{ content }}{% endblock %}
{% block sidebar %}{% endblock %}
<br class="clear" />
diff --git a/django/contrib/admin/templates/admin/base_site.html b/django/contrib/admin/templates/admin/base_site.html
index b867bd29bd..2bc7310873 100644
--- a/django/contrib/admin/templates/admin/base_site.html
+++ b/django/contrib/admin/templates/admin/base_site.html
@@ -1,7 +1,7 @@
{% extends "admin/base.html" %}
{% load i18n %}
-{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}
+{% block title %}{{ title|escape }} | {% trans 'Django site admin' %}{% endblock %}
{% block branding %}
<h1 id="site-name">{% trans 'Django administration' %}</h1>
diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html
index fa04969f01..b1fdc5ebdb 100644
--- a/django/contrib/admin/templates/admin/change_form.html
+++ b/django/contrib/admin/templates/admin/change_form.html
@@ -11,8 +11,8 @@
{% block breadcrumbs %}{% if not is_popup %}
<div class="breadcrumbs">
<a href="../../../">{% trans "Home" %}</a> &rsaquo;
- <a href="../">{{ opts.verbose_name_plural|capfirst }}</a> &rsaquo;
- {% if add %}{% trans "Add" %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %}
+ <a href="../">{{ opts.verbose_name_plural|capfirst|escape }}</a> &rsaquo;
+ {% if add %}{% trans "Add" %} {{ opts.verbose_name|escape }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %}
</div>
{% endif %}{% endblock %}
{% block content %}<div id="content-main">
@@ -21,7 +21,7 @@
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
</ul>
{% endif %}{% endif %}
-<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post">{% block form_top %}{% endblock %}
+<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}
<div>
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
{% if opts.admin.save_on_top %}{% submit_row %}{% endif %}
diff --git a/django/contrib/admin/templates/admin/change_list.html b/django/contrib/admin/templates/admin/change_list.html
index 5b54bfb8cc..bd2304bd52 100644
--- a/django/contrib/admin/templates/admin/change_list.html
+++ b/django/contrib/admin/templates/admin/change_list.html
@@ -3,12 +3,12 @@
{% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %}
{% block bodyclass %}change-list{% endblock %}
{% block userlinks %}<a href="../../doc/">{% trans 'Documentation' %}</a> / <a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
-{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> &rsaquo; {{ cl.opts.verbose_name_plural|capfirst }}</div>{% endblock %}{% endif %}
+{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> &rsaquo; {{ cl.opts.verbose_name_plural|capfirst|escape }}</div>{% endblock %}{% endif %}
{% block coltype %}flex{% endblock %}
{% block content %}
<div id="content-main">
{% if has_add_permission %}
-<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
+<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name|escape as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
{% endif %}
<div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
{% block search %}{% search_form cl %}{% endblock %}
diff --git a/django/contrib/admin/templates/admin/date_hierarchy.html b/django/contrib/admin/templates/admin/date_hierarchy.html
index a53d810f93..d2d69616c7 100644
--- a/django/contrib/admin/templates/admin/date_hierarchy.html
+++ b/django/contrib/admin/templates/admin/date_hierarchy.html
@@ -1,10 +1,10 @@
{% if show %}
<div class="xfull">
<ul class="toplinks">
-{% if back %}<li class="date-back"><a href="{{ back.link }}">&lsaquo; {{ back.title }}</a></li>{% endif %}
+{% if back %}<li class="date-back"><a href="{{ back.link }}">&lsaquo; {{ back.title|escape }}</a></li>{% endif %}
{% for choice in choices %}
-<li> {% if choice.link %}<a href="{{ choice.link }}">{% endif %}{{ choice.title }}{% if choice.link %}</a>{% endif %}</li>
+<li> {% if choice.link %}<a href="{{ choice.link }}">{% endif %}{{ choice.title|escape }}{% if choice.link %}</a>{% endif %}</li>
{% endfor %}
</ul><br class="clear" />
</div>
-{% endif %} \ No newline at end of file
+{% endif %}
diff --git a/django/contrib/admin/templates/admin/delete_confirmation.html b/django/contrib/admin/templates/admin/delete_confirmation.html
index f907c18a16..3921ab69e3 100644
--- a/django/contrib/admin/templates/admin/delete_confirmation.html
+++ b/django/contrib/admin/templates/admin/delete_confirmation.html
@@ -4,21 +4,21 @@
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="../../../../">{% trans "Home" %}</a> &rsaquo;
- <a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> &rsaquo;
- <a href="../">{{ object|striptags|truncatewords:"18" }}</a> &rsaquo;
+ <a href="../../">{{ opts.verbose_name_plural|capfirst|escape }}</a> &rsaquo;
+ <a href="../">{{ object|escape|truncatewords:"18" }}</a> &rsaquo;
{% trans 'Delete' %}
</div>
{% endblock %}
{% block content %}
{% if perms_lacking %}
- <p>{% blocktrans %}Deleting the {{ object_name }} '{{ object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}</p>
+ <p>{% blocktrans with object|escape as escaped_object %}Deleting the {{ object_name }} '{{ escaped_object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}</p>
<ul>
{% for obj in perms_lacking %}
- <li>{{ obj }}</li>
+ <li>{{ obj|escape }}</li>
{% endfor %}
</ul>
{% else %}
- <p>{% blocktrans %}Are you sure you want to delete the {{ object_name }} "{{ object }}"? All of the following related items will be deleted:{% endblocktrans %}</p>
+ <p>{% blocktrans with object|escape as escaped_object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktrans %}</p>
<ul>{{ deleted_objects|unordered_list }}</ul>
<form action="" method="post">
<div>
diff --git a/django/contrib/admin/templates/admin/edit_inline_stacked.html b/django/contrib/admin/templates/admin/edit_inline_stacked.html
index 45aa0a4f58..48ecc698d9 100644
--- a/django/contrib/admin/templates/admin/edit_inline_stacked.html
+++ b/django/contrib/admin/templates/admin/edit_inline_stacked.html
@@ -1,7 +1,7 @@
{% load admin_modify %}
<fieldset class="module aligned">
{% for fcw in bound_related_object.form_field_collection_wrappers %}
- <h2>{{ bound_related_object.relation.opts.verbose_name|capfirst }}&nbsp;#{{ forloop.counter }}</h2>
+ <h2>{{ bound_related_object.relation.opts.verbose_name|capfirst|escape }}&nbsp;#{{ forloop.counter }}</h2>
{% if bound_related_object.show_url %}{% if fcw.obj.original %}
<p><a href="/r/{{ fcw.obj.original.content_type_id }}/{{ fcw.obj.original.id }}/">View on site</a></p>
{% endif %}{% endif %}
diff --git a/django/contrib/admin/templates/admin/edit_inline_tabular.html b/django/contrib/admin/templates/admin/edit_inline_tabular.html
index e9535df02c..3d059c8b3d 100644
--- a/django/contrib/admin/templates/admin/edit_inline_tabular.html
+++ b/django/contrib/admin/templates/admin/edit_inline_tabular.html
@@ -1,12 +1,13 @@
{% load admin_modify %}
<fieldset class="module">
- <h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst }}</h2><table>
+ <h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst|escape }}</h2><table>
<thead><tr>
{% for fw in bound_related_object.field_wrapper_list %}
{% if fw.needs_header %}
- <th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst }}</th>
+ <th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th>
{% endif %}
{% endfor %}
+ </tr></thead>
{% for fcw in bound_related_object.form_field_collection_wrappers %}
{% if change %}{% if original_row_needed %}
{% if fcw.obj.original %}
diff --git a/django/contrib/admin/templates/admin/filter.html b/django/contrib/admin/templates/admin/filter.html
index 5b0e78b6fc..8b5b521437 100644
--- a/django/contrib/admin/templates/admin/filter.html
+++ b/django/contrib/admin/templates/admin/filter.html
@@ -1,5 +1,5 @@
{% load i18n %}
-<h3>{% blocktrans %} By {{ title }} {% endblocktrans %}</h3>
+<h3>{% blocktrans with title|escape as filter_title %} By {{ filter_title }} {% endblocktrans %}</h3>
<ul>
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>
diff --git a/django/contrib/admin/templates/admin/index.html b/django/contrib/admin/templates/admin/index.html
index f7b121723a..aa63c14fce 100644
--- a/django/contrib/admin/templates/admin/index.html
+++ b/django/contrib/admin/templates/admin/index.html
@@ -19,9 +19,9 @@
{% for model in app.models %}
<tr>
{% if model.perms.change %}
- <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
+ <th scope="row"><a href="{{ model.admin_url }}">{{ model.name|escape }}</a></th>
{% else %}
- <th scope="row">{{ model.name }}</th>
+ <th scope="row">{{ model.name|escape }}</th>
{% endif %}
{% if model.perms.add %}
@@ -58,7 +58,7 @@
{% else %}
<ul class="actionlist">
{% for entry in admin_log %}
- <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.content_type.name|capfirst }}</span></li>
+ <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.content_type.name|capfirst|escape }}</span></li>
{% endfor %}
</ul>
{% endif %}
diff --git a/django/contrib/admin/templates/admin/invalid_setup.html b/django/contrib/admin/templates/admin/invalid_setup.html
index 1fa0d32358..1d7d61f0d2 100644
--- a/django/contrib/admin/templates/admin/invalid_setup.html
+++ b/django/contrib/admin/templates/admin/invalid_setup.html
@@ -1,7 +1,7 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
-{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> &rsaquo; {{ title }}</div>{% endblock %}
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> &rsaquo; {{ title|escape }}</div>{% endblock %}
{% block content %}
diff --git a/django/contrib/admin/templates/admin/login.html b/django/contrib/admin/templates/admin/login.html
index 5f338f703e..0773132cec 100644
--- a/django/contrib/admin/templates/admin/login.html
+++ b/django/contrib/admin/templates/admin/login.html
@@ -13,17 +13,17 @@
{% endif %}
<div id="content-main">
<form action="{{ app_path }}" method="post" id="login-form">
- <div class="form-row">
- <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
- </div>
- <div class="form-row">
- <label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
- <input type="hidden" name="this_is_the_login_form" value="1" />
- <input type="hidden" name="post_data" value="{{ post_data }}" /> {% comment %}<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>{% endcomment %}
- </div>
- <div class="submit-row">
- <label>&nbsp;</label><input type="submit" value="{% trans 'Log in' %}" />
- </div>
+ <div class="form-row">
+ <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
+ </div>
+ <div class="form-row">
+ <label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
+ <input type="hidden" name="this_is_the_login_form" value="1" />
+ <input type="hidden" name="post_data" value="{{ post_data }}" /> {#<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>#}
+ </div>
+ <div class="submit-row">
+ <label>&nbsp;</label><input type="submit" value="{% trans 'Log in' %}" />
+ </div>
</form>
<script type="text/javascript">
diff --git a/django/contrib/admin/templates/admin/object_history.html b/django/contrib/admin/templates/admin/object_history.html
index fc568305ca..14a77b8a31 100644
--- a/django/contrib/admin/templates/admin/object_history.html
+++ b/django/contrib/admin/templates/admin/object_history.html
@@ -2,7 +2,7 @@
{% load i18n %}
{% block userlinks %}<a href="../../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
{% block breadcrumbs %}
-<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> &rsaquo; <a href="../../">{{ module_name }}</a> &rsaquo; <a href="../">{{ object|truncatewords:"18" }}</a> &rsaquo; {% trans 'History' %}</div>
+<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> &rsaquo; <a href="../../">{{ module_name|escape }}</a> &rsaquo; <a href="../">{{ object|escape|truncatewords:"18" }}</a> &rsaquo; {% trans 'History' %}</div>
{% endblock %}
{% block content %}
diff --git a/django/contrib/admin/templates/admin/pagination.html b/django/contrib/admin/templates/admin/pagination.html
index 7694e4c5b0..e1c09b2932 100644
--- a/django/contrib/admin/templates/admin/pagination.html
+++ b/django/contrib/admin/templates/admin/pagination.html
@@ -6,6 +6,6 @@
{% paginator_number cl i %}
{% endfor %}
{% endif %}
-{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %}
+{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name|escape }}{% else %}{{ cl.opts.verbose_name_plural|escape }}{% endifequal %}
{% if show_all_url %}&nbsp;&nbsp;<a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
</p>
diff --git a/django/contrib/admin/templates/admin_doc/index.html b/django/contrib/admin/templates/admin_doc/index.html
index 331774d2b3..74f9f20916 100644
--- a/django/contrib/admin/templates/admin_doc/index.html
+++ b/django/contrib/admin/templates/admin_doc/index.html
@@ -9,17 +9,17 @@
<h1>Documentation</h1>
<div id="content-main">
- <h3><a href="tags/">Tags</a></h3>
- <p>List of all the template tags and their functions.</p>
+ <h3><a href="tags/">Tags</a></h3>
+ <p>List of all the template tags and their functions.</p>
- <h3><a href="filters/">Filters</a></h3>
- <p>Filters are actions which can be applied to variables in a template to alter the output.</p>
+ <h3><a href="filters/">Filters</a></h3>
+ <p>Filters are actions which can be applied to variables in a template to alter the output.</p>
- <h3><a href="models/">Models</a></h3>
- <p>Models are descriptions of all the objects in the system and their associated fields. Each model has a list of fields which can be accessed as template variables.</p>
+ <h3><a href="models/">Models</a></h3>
+ <p>Models are descriptions of all the objects in the system and their associated fields. Each model has a list of fields which can be accessed as template variables.</p>
- <h3><a href="views/">Views</a></h3>
- <p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
+ <h3><a href="views/">Views</a></h3>
+ <p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
<h3><a href="bookmarklets/">Bookmarklets</a></h3>
<p>Tools for your browser to quickly access admin functionality.</p>
diff --git a/django/contrib/admin/templates/admin_doc/missing_docutils.html b/django/contrib/admin/templates/admin_doc/missing_docutils.html
index d0b571f957..cdeab0cdd8 100644
--- a/django/contrib/admin/templates/admin_doc/missing_docutils.html
+++ b/django/contrib/admin/templates/admin_doc/missing_docutils.html
@@ -9,9 +9,9 @@
<h1>Documentation</h1>
<div id="content-main">
- <h3>The admin documentation system requires Python's <a href="http://docutils.sf.net/">docutils</a> library.</h3>
+ <h3>The admin documentation system requires Python's <a href="http://docutils.sf.net/">docutils</a> library.</h3>
- <p>Please ask your administrators to install <a href="http://docutils.sf.net/">docutils</a>.</p>
+ <p>Please ask your administrators to install <a href="http://docutils.sf.net/">docutils</a>.</p>
</div>
{% endblock %}
diff --git a/django/contrib/admin/templates/admin_doc/model_detail.html b/django/contrib/admin/templates/admin_doc/model_detail.html
index 9ac56864fa..70133e26dd 100644
--- a/django/contrib/admin/templates/admin_doc/model_detail.html
+++ b/django/contrib/admin/templates/admin_doc/model_detail.html
@@ -9,13 +9,13 @@
</style>
{% endblock %}
-{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> &rsaquo; <a href="../../">Documentation</a> &rsaquo; <a href="../">Models</a> &rsaquo; {{ name }}</div>{% endblock %}
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> &rsaquo; <a href="../../">Documentation</a> &rsaquo; <a href="../">Models</a> &rsaquo; {{ name|escape }}</div>{% endblock %}
-{% block title %}Model: {{ name }}{% endblock %}
+{% block title %}Model: {{ name|escape }}{% endblock %}
{% block content %}
<div id="content-main">
-<h1>{{ summary }}</h1>
+<h1>{{ summary|escape }}</h1>
{% if description %}
<p>{% filter escape|linebreaksbr %}{% trans description %}{% endfilter %}</p>
diff --git a/django/contrib/admin/templates/admin_doc/template_detail.html b/django/contrib/admin/templates/admin_doc/template_detail.html
index df67f1856b..280ea912d0 100644
--- a/django/contrib/admin/templates/admin_doc/template_detail.html
+++ b/django/contrib/admin/templates/admin_doc/template_detail.html
@@ -1,19 +1,19 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
-{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> &rsaquo; <a href="../../">Documentation</a> &rsaquo; Templates &rsaquo; {{ name }}</div>{% endblock %}
+{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> &rsaquo; <a href="../../">Documentation</a> &rsaquo; Templates &rsaquo; {{ name|escape }}</div>{% endblock %}
{% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
-{% block title %}Template: {{ name }}{% endblock %}
+{% block title %}Template: {{ name|escape }}{% endblock %}
{% block content %}
-<h1>Template: "{{ name }}"</h1>
+<h1>Template: "{{ name|escape }}"</h1>
{% regroup templates|dictsort:"site_id" by site as templates_by_site %}
{% for group in templates_by_site %}
- <h2>Search path for template "{{ name }}" on {{ group.grouper }}:</h2>
+ <h2>Search path for template "{{ name|escape }}" on {{ group.grouper }}:</h2>
<ol>
{% for template in group.list|dictsort:"order" %}
- <li><code>{{ template.file }}</code>{% if not template.exists %} <em>(does not exist)</em>{% endif %}</li>
+ <li><code>{{ template.file|escape }}</code>{% if not template.exists %} <em>(does not exist)</em>{% endif %}</li>
{% endfor %}
</ol>
{% endfor %}
diff --git a/django/contrib/admin/templates/widget/file.html b/django/contrib/admin/templates/widget/file.html
index e4a0756211..e584abf956 100644
--- a/django/contrib/admin/templates/widget/file.html
+++ b/django/contrib/admin/templates/widget/file.html
@@ -1,4 +1,4 @@
{% load admin_modify i18n %}{% if bound_field.original_value %}
-{% trans "Currently:" %} <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value }} </a><br />
+{% trans "Currently:" %} <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value|escape }} </a><br />
{% trans "Change:" %}{% output_all bound_field.form_fields %}
{% else %} {% output_all bound_field.form_fields %} {% endif %}
diff --git a/django/contrib/admin/templates/widget/foreign.html b/django/contrib/admin/templates/widget/foreign.html
index 6b43d044bd..301f5214db 100644
--- a/django/contrib/admin/templates/widget/foreign.html
+++ b/django/contrib/admin/templates/widget/foreign.html
@@ -15,6 +15,6 @@
{{ bound_field.original_value }}
{% endif %}
{% if bound_field.raw_id_admin %}
- {% if bound_field.existing_display %}&nbsp;<strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}
+ {% if bound_field.existing_display %}&nbsp;<strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %}
{% endif %}
{% endif %}
diff --git a/django/contrib/admin/templates/widget/one_to_one.html b/django/contrib/admin/templates/widget/one_to_one.html
index a79a12314f..efd0117bf2 100644
--- a/django/contrib/admin/templates/widget/one_to_one.html
+++ b/django/contrib/admin/templates/widget/one_to_one.html
@@ -1,2 +1,2 @@
{% if add %}{% include "widget/foreign.html" %}{% endif %}
-{% if change %}{% if bound_field.existing_display %}&nbsp;<strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}{% endif %}
+{% if change %}{% if bound_field.existing_display %}&nbsp;<strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %}{% endif %}
diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
index 3537f46755..832b3562cd 100644
--- a/django/contrib/admin/templatetags/admin_list.py
+++ b/django/contrib/admin/templatetags/admin_list.py
@@ -1,8 +1,6 @@
-from django import template
from django.conf import settings
-from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, ALL_VAR
+from django.contrib.admin.views.main import ALL_VAR, EMPTY_CHANGELIST_VALUE
from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR
-from django.contrib.admin.views.main import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.utils import dateformat
@@ -119,7 +117,7 @@ def items_for_result(cl, result):
if callable(attr):
attr = attr()
result_repr = str(attr)
- except AttributeError, ObjectDoesNotExist:
+ except (AttributeError, ObjectDoesNotExist):
result_repr = EMPTY_CHANGELIST_VALUE
else:
# Strip HTML tags in the resulting text, except if the
@@ -167,11 +165,12 @@ def items_for_result(cl, result):
result_repr = '&nbsp;'
# If list_display_links not defined, add the link tag to the first field
if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links:
+ table_tag = {True:'th', False:'td'}[first]
first = False
url = cl.url_for_result(result)
result_id = str(getattr(result, pk)) # str() is needed in case of 23L (long ints)
- yield ('<th%s><a href="%s"%s>%s</a></th>' % \
- (row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr))
+ yield ('<%s%s><a href="%s"%s>%s</a></%s>' % \
+ (table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr, table_tag))
else:
yield ('<td%s>%s</td>' % (row_class, result_repr))
diff --git a/django/contrib/admin/templatetags/admin_modify.py b/django/contrib/admin/templatetags/admin_modify.py
index 2d34452f52..d09fa28b10 100644
--- a/django/contrib/admin/templatetags/admin_modify.py
+++ b/django/contrib/admin/templatetags/admin_modify.py
@@ -1,9 +1,7 @@
from django import template
from django.contrib.admin.views.main import AdminBoundField
from django.template import loader
-from django.utils.html import escape
from django.utils.text import capfirst
-from django.utils.functional import curry
from django.db import models
from django.db.models.fields import Field
from django.db.models.related import BoundRelatedObject
@@ -162,8 +160,10 @@ class EditInlineNode(template.Node):
context.push()
if relation.field.rel.edit_inline == models.TABULAR:
bound_related_object_class = TabularBoundRelatedObject
- else:
+ elif relation.field.rel.edit_inline == models.STACKED:
bound_related_object_class = StackedBoundRelatedObject
+ else:
+ bound_related_object_class = relation.field.rel.edit_inline
original = context.get('original', None)
bound_related_object = relation.bind(context['form'], original, bound_related_object_class)
context['bound_related_object'] = bound_related_object
@@ -198,7 +198,7 @@ def filter_interface_script_maybe(bound_field):
if f.rel and isinstance(f.rel, models.ManyToManyRel) and f.rel.filter_interface:
return '<script type="text/javascript">addEvent(window, "load", function(e) {' \
' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % (
- f.name, f.verbose_name, f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX)
+ f.name, f.verbose_name.replace('"', '\\"'), f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX)
else:
return ''
filter_interface_script_maybe = register.simple_tag(filter_interface_script_maybe)
diff --git a/django/contrib/admin/urls.py b/django/contrib/admin/urls.py
index bd894d8de1..aaf9841e45 100644
--- a/django/contrib/admin/urls.py
+++ b/django/contrib/admin/urls.py
@@ -21,13 +21,15 @@ urlpatterns = patterns('',
('^doc/tags/$', 'django.contrib.admin.views.doc.template_tag_index'),
('^doc/filters/$', 'django.contrib.admin.views.doc.template_filter_index'),
('^doc/views/$', 'django.contrib.admin.views.doc.view_index'),
- ('^doc/views/jump/$', 'django.contrib.admin.views.doc.jump_to_view'),
('^doc/views/(?P<view>[^/]+)/$', 'django.contrib.admin.views.doc.view_detail'),
('^doc/models/$', 'django.contrib.admin.views.doc.model_index'),
('^doc/models/(?P<app_label>[^\.]+)\.(?P<model_name>[^/]+)/$', 'django.contrib.admin.views.doc.model_detail'),
# ('^doc/templates/$', 'django.views.admin.doc.template_index'),
('^doc/templates/(?P<template>.*)/$', 'django.contrib.admin.views.doc.template_detail'),
+ # "Add user" -- a special-case view
+ ('^auth/user/add/$', 'django.contrib.admin.views.auth.user_add_stage'),
+
# Add/change/delete/history
('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'),
('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
diff --git a/django/contrib/admin/utils.py b/django/contrib/admin/utils.py
index 0242b2f32e..9adf09b6a5 100644
--- a/django/contrib/admin/utils.py
+++ b/django/contrib/admin/utils.py
@@ -3,7 +3,6 @@
import re
from email.Parser import HeaderParser
from email.Errors import HeaderParseError
-from urlparse import urljoin
try:
import docutils.core
import docutils.nodes
diff --git a/django/contrib/admin/views/auth.py b/django/contrib/admin/views/auth.py
new file mode 100644
index 0000000000..03876bb4ac
--- /dev/null
+++ b/django/contrib/admin/views/auth.py
@@ -0,0 +1,44 @@
+from django.contrib.admin.views.decorators import staff_member_required
+from django.contrib.auth.forms import UserCreationForm
+from django.contrib.auth.models import User
+from django.core.exceptions import PermissionDenied
+from django import forms, template
+from django.shortcuts import render_to_response
+from django.http import HttpResponseRedirect
+
+def user_add_stage(request):
+ if not request.user.has_perm('auth.change_user'):
+ raise PermissionDenied
+ manipulator = UserCreationForm()
+ if request.method == 'POST':
+ new_data = request.POST.copy()
+ errors = manipulator.get_validation_errors(new_data)
+ if not errors:
+ new_user = manipulator.save(new_data)
+ msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user}
+ if request.POST.has_key("_addanother"):
+ request.user.message_set.create(message=msg)
+ return HttpResponseRedirect(request.path)
+ else:
+ request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
+ return HttpResponseRedirect('../%s/' % new_user.id)
+ else:
+ errors = new_data = {}
+ form = forms.FormWrapper(manipulator, new_data, errors)
+ return render_to_response('admin/auth/user/add_form.html', {
+ 'title': _('Add user'),
+ 'form': form,
+ 'is_popup': request.REQUEST.has_key('_popup'),
+ 'add': True,
+ 'change': False,
+ 'has_delete_permission': False,
+ 'has_change_permission': True,
+ 'has_file_field': False,
+ 'has_absolute_url': False,
+ 'auto_populated_fields': (),
+ 'bound_field_sets': (),
+ 'first_form_field_id': 'id_username',
+ 'opts': User._meta,
+ 'username_help_text': User._meta.get_field('username').help_text,
+ }, context_instance=template.RequestContext(request))
+user_add_stage = staff_member_required(user_add_stage)
diff --git a/django/contrib/admin/views/decorators.py b/django/contrib/admin/views/decorators.py
index 250c585220..9dfe651fe6 100644
--- a/django/contrib/admin/views/decorators.py
+++ b/django/contrib/admin/views/decorators.py
@@ -46,7 +46,7 @@ def staff_member_required(view_func):
member, displaying the login page if necessary.
"""
def _checklogin(request, *args, **kwargs):
- if not request.user.is_anonymous() and request.user.is_staff:
+ if request.user.is_authenticated() and request.user.is_staff:
# The user is valid. Continue to the admin page.
if request.POST.has_key('post_data'):
# User must have re-authenticated through a different window
@@ -87,7 +87,7 @@ def staff_member_required(view_func):
# The user data is correct; log in the user in and continue.
else:
- if user.is_staff:
+ if user.is_active and user.is_staff:
login(request, user)
# TODO: set last_login with an event.
user.last_login = datetime.datetime.now()
diff --git a/django/contrib/admin/views/doc.py b/django/contrib/admin/views/doc.py
index 5aa143e1fd..435d76f276 100644
--- a/django/contrib/admin/views/doc.py
+++ b/django/contrib/admin/views/doc.py
@@ -28,7 +28,7 @@ def bookmarklets(request):
# Hack! This couples this view to the URL it lives at.
admin_root = request.path[:-len('doc/bookmarklets/')]
return render_to_response('admin_doc/bookmarklets.html', {
- 'admin_url': "%s://%s%s" % (os.environ.get('HTTPS') == 'on' and 'https' or 'http', get_host(request), admin_root),
+ 'admin_url': "%s://%s%s" % (request.is_secure() and 'https' or 'http', get_host(request), admin_root),
}, context_instance=RequestContext(request))
bookmarklets = staff_member_required(bookmarklets)
@@ -43,11 +43,11 @@ def template_tag_index(request):
for tag_name, tag_func in library.tags.items():
title, body, metadata = utils.parse_docstring(tag_func.__doc__)
if title:
- title = utils.parse_rst(title, 'tag', 'tag:' + tag_name)
+ title = utils.parse_rst(title, 'tag', _('tag:') + tag_name)
if body:
- body = utils.parse_rst(body, 'tag', 'tag:' + tag_name)
+ body = utils.parse_rst(body, 'tag', _('tag:') + tag_name)
for key in metadata:
- metadata[key] = utils.parse_rst(metadata[key], 'tag', 'tag:' + tag_name)
+ metadata[key] = utils.parse_rst(metadata[key], 'tag', _('tag:') + tag_name)
if library in template.builtins:
tag_library = None
else:
@@ -74,11 +74,11 @@ def template_filter_index(request):
for filter_name, filter_func in library.filters.items():
title, body, metadata = utils.parse_docstring(filter_func.__doc__)
if title:
- title = utils.parse_rst(title, 'filter', 'filter:' + filter_name)
+ title = utils.parse_rst(title, 'filter', _('filter:') + filter_name)
if body:
- body = utils.parse_rst(body, 'filter', 'filter:' + filter_name)
+ body = utils.parse_rst(body, 'filter', _('filter:') + filter_name)
for key in metadata:
- metadata[key] = utils.parse_rst(metadata[key], 'filter', 'filter:' + filter_name)
+ metadata[key] = utils.parse_rst(metadata[key], 'filter', _('filter:') + filter_name)
if library in template.builtins:
tag_library = None
else:
@@ -132,11 +132,11 @@ def view_detail(request, view):
raise Http404
title, body, metadata = utils.parse_docstring(view_func.__doc__)
if title:
- title = utils.parse_rst(title, 'view', 'view:' + view)
+ title = utils.parse_rst(title, 'view', _('view:') + view)
if body:
- body = utils.parse_rst(body, 'view', 'view:' + view)
+ body = utils.parse_rst(body, 'view', _('view:') + view)
for key in metadata:
- metadata[key] = utils.parse_rst(metadata[key], 'model', 'view:' + view)
+ metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view)
return render_to_response('admin_doc/view_detail.html', {
'name': view,
'summary': title,
@@ -161,14 +161,14 @@ def model_detail(request, app_label, model_name):
try:
app_mod = models.get_app(app_label)
except ImproperlyConfigured:
- raise Http404, "App %r not found" % app_label
+ raise Http404, _("App %r not found") % app_label
model = None
for m in models.get_models(app_mod):
if m._meta.object_name.lower() == model_name:
model = m
break
if model is None:
- raise Http404, "Model %r not found in app %r" % (model_name, app_label)
+ raise Http404, _("Model %r not found in app %r") % (model_name, app_label)
opts = model._meta
@@ -180,7 +180,7 @@ def model_detail(request, app_label, model_name):
if isinstance(field, models.ForeignKey):
data_type = related_object_name = field.rel.to.__name__
app_label = field.rel.to._meta.app_label
- verbose = utils.parse_rst(("the related `%s.%s` object" % (app_label, data_type)), 'model', 'model:' + data_type)
+ verbose = utils.parse_rst((_("the related `%s.%s` object") % (app_label, data_type)), 'model', _('model:') + data_type)
else:
data_type = get_readable_field_data_type(field)
verbose = field.verbose_name
@@ -202,7 +202,7 @@ def model_detail(request, app_label, model_name):
continue
verbose = func.__doc__
if verbose:
- verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', 'model:' + opts.module_name)
+ verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.module_name)
fields.append({
'name': func_name,
'data_type': get_return_data_type(func_name),
@@ -211,22 +211,22 @@ def model_detail(request, app_label, model_name):
# Gather related objects
for rel in opts.get_all_related_objects():
- verbose = "related `%s.%s` objects" % (rel.opts.app_label, rel.opts.object_name)
+ verbose = _("related `%s.%s` objects") % (rel.opts.app_label, rel.opts.object_name)
accessor = rel.get_accessor_name()
fields.append({
'name' : "%s.all" % accessor,
'data_type' : 'List',
- 'verbose' : utils.parse_rst("all " + verbose , 'model', 'model:' + opts.module_name),
+ 'verbose' : utils.parse_rst(_("all %s") % verbose , 'model', _('model:') + opts.module_name),
})
fields.append({
'name' : "%s.count" % accessor,
'data_type' : 'Integer',
- 'verbose' : utils.parse_rst("number of " + verbose , 'model', 'model:' + opts.module_name),
+ 'verbose' : utils.parse_rst(_("number of %s") % verbose , 'model', _('model:') + opts.module_name),
})
return render_to_response('admin_doc/model_detail.html', {
'name': '%s.%s' % (opts.app_label, opts.object_name),
- 'summary': "Fields on %s objects" % opts.object_name,
+ 'summary': _("Fields on %s objects") % opts.object_name,
'description': model.__doc__,
'fields': fields,
}, context_instance=RequestContext(request))
@@ -328,15 +328,19 @@ def extract_views_from_urlpatterns(urlpatterns, base=''):
"""
views = []
for p in urlpatterns:
- if hasattr(p, 'get_callback'):
+ if hasattr(p, '_get_callback'):
try:
- views.append((p.get_callback(), base + p.regex.pattern))
+ views.append((p._get_callback(), base + p.regex.pattern))
except ViewDoesNotExist:
continue
elif hasattr(p, '_get_url_patterns'):
- views.extend(extract_views_from_urlpatterns(p.url_patterns, base + p.regex.pattern))
+ try:
+ patterns = p.url_patterns
+ except ImportError:
+ continue
+ views.extend(extract_views_from_urlpatterns(patterns, base + p.regex.pattern))
else:
- raise TypeError, "%s does not appear to be a urlpattern object" % p
+ raise TypeError, _("%s does not appear to be a urlpattern object") % p
return views
named_group_matcher = re.compile(r'\(\?P(<\w+>).+?\)')
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index a7ee08f1c0..324841a669 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -10,9 +10,6 @@ from django.shortcuts import get_object_or_404, render_to_response
from django.db import models
from django.db.models.query import handle_legacy_orderlist, QuerySet
from django.http import Http404, HttpResponse, HttpResponseRedirect
-from django.template import loader
-from django.utils import dateformat
-from django.utils.dates import MONTHS
from django.utils.html import escape
from django.utils.text import capfirst, get_text_list
import operator
@@ -266,6 +263,8 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
post_url_continue += "?_popup=1"
return HttpResponseRedirect(post_url_continue % pk_value)
if request.POST.has_key("_popup"):
+ if type(pk_value) is str: # Quote if string, so JavaScript doesn't think it's a variable.
+ pk_value = '"%s"' % pk_value.replace('"', '\\"')
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
(pk_value, str(new_object).replace('"', '\\"')))
elif request.POST.has_key("_addanother"):
@@ -455,7 +454,7 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
if related.opts.admin and has_related_objs:
p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission())
if not user.has_perm(p):
- perms_needed.add(rel_opts_name)
+ perms_needed.add(related.opts.verbose_name)
for related in opts.get_all_related_many_to_many_objects():
if related.opts in opts_seen:
continue
@@ -714,10 +713,22 @@ class ChangeList(object):
qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field)
# Apply keyword searches.
+ def construct_search(field_name):
+ if field_name.startswith('^'):
+ return "%s__istartswith" % field_name[1:]
+ elif field_name.startswith('='):
+ return "%s__iexact" % field_name[1:]
+ elif field_name.startswith('@'):
+ return "%s__search" % field_name[1:]
+ else:
+ return "%s__icontains" % field_name
+
if self.lookup_opts.admin.search_fields and self.query:
for bit in self.query.split():
- or_queries = [models.Q(**{'%s__icontains' % field_name: bit}) for field_name in self.lookup_opts.admin.search_fields]
+ or_queries = [models.Q(**{construct_search(field_name): bit}) for field_name in self.lookup_opts.admin.search_fields]
other_qs = QuerySet(self.model)
+ if qs._select_related:
+ other_qs = other_qs.select_related()
other_qs = other_qs.filter(reduce(operator.or_, or_queries))
qs = qs & other_qs
diff --git a/django/contrib/admin/views/template.py b/django/contrib/admin/views/template.py
index f73b9e4218..1684870842 100644
--- a/django/contrib/admin/views/template.py
+++ b/django/contrib/admin/views/template.py
@@ -22,7 +22,7 @@ def template_validator(request):
new_data = request.POST.copy()
errors = manipulator.get_validation_errors(new_data)
if not errors:
- request.user.add_message('The template is valid.')
+ request.user.message_set.create(message='The template is valid.')
return render_to_response('admin/template_validator.html', {
'title': 'Template validator',
'form': forms.FormWrapper(manipulator, new_data, errors),
@@ -32,7 +32,7 @@ template_validator = staff_member_required(template_validator)
class TemplateValidator(forms.Manipulator):
def __init__(self, settings_modules):
self.settings_modules = settings_modules
- site_list = Site.objects.get_in_bulk(settings_modules.keys()).values()
+ site_list = Site.objects.in_bulk(settings_modules.keys()).values()
self.fields = (
forms.SelectField('site', is_required=True, choices=[(s.id, s.name) for s in site_list]),
forms.LargeTextField('template', is_required=True, rows=25, validator_list=[self.isValidTemplate]),
diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py
index 2150893022..a0097a01ed 100644
--- a/django/contrib/auth/__init__.py
+++ b/django/contrib/auth/__init__.py
@@ -38,7 +38,7 @@ def authenticate(**credentials):
if user is None:
continue
# Annotate the user object with the path of the backend.
- user.backend = str(backend.__class__)
+ user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
return user
def login(request, user):
@@ -56,8 +56,14 @@ def logout(request):
"""
Remove the authenticated user's ID from the request.
"""
- del request.session[SESSION_KEY]
- del request.session[BACKEND_SESSION_KEY]
+ try:
+ del request.session[SESSION_KEY]
+ except KeyError:
+ pass
+ try:
+ del request.session[BACKEND_SESSION_KEY]
+ except KeyError:
+ pass
def get_user(request):
from django.contrib.auth.models import AnonymousUser
diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
index 3b46b65b0a..4b8efcca46 100644
--- a/django/contrib/auth/backends.py
+++ b/django/contrib/auth/backends.py
@@ -1,4 +1,4 @@
-from django.contrib.auth.models import User, check_password
+from django.contrib.auth.models import User
class ModelBackend:
"""
diff --git a/django/contrib/auth/create_superuser.py b/django/contrib/auth/create_superuser.py
index f42d30539e..2e93c35b93 100644
--- a/django/contrib/auth/create_superuser.py
+++ b/django/contrib/auth/create_superuser.py
@@ -46,6 +46,7 @@ def createsuperuser(username=None, email=None, password=None):
if not username.isalnum():
sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n")
username = None
+ continue
try:
User.objects.get(username=username)
except User.DoesNotExist:
diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py
index bc8ec39115..37e948f8fe 100644
--- a/django/contrib/auth/decorators.py
+++ b/django/contrib/auth/decorators.py
@@ -13,14 +13,24 @@ def user_passes_test(test_func, login_url=LOGIN_URL):
if test_func(request.user):
return view_func(request, *args, **kwargs)
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
+ _checklogin.__doc__ = view_func.__doc__
+ _checklogin.__dict__ = view_func.__dict__
return _checklogin
return _dec
-login_required = user_passes_test(lambda u: not u.is_anonymous())
+login_required = user_passes_test(lambda u: u.is_authenticated())
login_required.__doc__ = (
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
)
+
+def permission_required(perm, login_url=LOGIN_URL):
+ """
+ Decorator for views that checks whether a user has a particular permission
+ enabled, redirecting to the log-in page if necessary.
+ """
+ return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
+
diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py
index ef81268e2a..24c69cb73e 100644
--- a/django/contrib/auth/forms.py
+++ b/django/contrib/auth/forms.py
@@ -5,6 +5,28 @@ from django.template import Context, loader
from django.core import validators
from django import forms
+class UserCreationForm(forms.Manipulator):
+ "A form that creates a user, with no privileges, from the given username and password."
+ def __init__(self):
+ self.fields = (
+ forms.TextField(field_name='username', length=30, maxlength=30, is_required=True,
+ validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
+ forms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
+ forms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
+ validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
+ )
+
+ def isValidUsername(self, field_data, all_data):
+ try:
+ User.objects.get(username=field_data)
+ except User.DoesNotExist:
+ return
+ raise validators.ValidationError, _('A user with that username already exists.')
+
+ def save(self, new_data):
+ "Creates the user."
+ return User.objects.create_user(new_data['username'], '', new_data['password1'])
+
class AuthenticationForm(forms.Manipulator):
"""
Base class for authenticating users. Extend this to get a form that accepts
@@ -59,9 +81,9 @@ class PasswordResetForm(forms.Manipulator):
try:
self.user_cache = User.objects.get(email__iexact=new_data)
except User.DoesNotExist:
- raise validators.ValidationError, "That e-mail address doesn't have an associated user acount. Are you sure you've registered?"
+ raise validators.ValidationError, _("That e-mail address doesn't have an associated user account. Are you sure you've registered?")
- def save(self, domain_override=None):
+ def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
"Calculates a new password randomly and sends it to the user"
from django.core.mail import send_mail
new_pass = User.objects.make_random_password()
@@ -73,7 +95,7 @@ class PasswordResetForm(forms.Manipulator):
domain = current_site.domain
else:
site_name = domain = domain_override
- t = loader.get_template('registration/password_reset_email.html')
+ t = loader.get_template(email_template_name)
c = {
'new_password': new_pass,
'email': self.user_cache.email,
@@ -91,14 +113,14 @@ class PasswordChangeForm(forms.Manipulator):
forms.PasswordField(field_name="old_password", length=30, maxlength=30, is_required=True,
validator_list=[self.isValidOldPassword]),
forms.PasswordField(field_name="new_password1", length=30, maxlength=30, is_required=True,
- validator_list=[validators.AlwaysMatchesOtherField('new_password2', "The two 'new password' fields didn't match.")]),
+ validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]),
forms.PasswordField(field_name="new_password2", length=30, maxlength=30, is_required=True),
)
def isValidOldPassword(self, new_data, all_data):
"Validates that the old_password field is correct."
if not self.user.check_password(new_data):
- raise validators.ValidationError, "Your old password was entered incorrectly. Please enter it again."
+ raise validators.ValidationError, _("Your old password was entered incorrectly. Please enter it again.")
def save(self, new_data):
"Saves the new password."
diff --git a/django/contrib/auth/handlers/modpython.py b/django/contrib/auth/handlers/modpython.py
index e6719794a1..c7d921313d 100644
--- a/django/contrib/auth/handlers/modpython.py
+++ b/django/contrib/auth/handlers/modpython.py
@@ -22,6 +22,8 @@ def authenhandler(req, **kwargs):
os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
from django.contrib.auth.models import User
+ from django import db
+ db.reset_queries()
# check that the username is valid
kwargs = {'username': req.user, 'is_active': True}
@@ -30,18 +32,21 @@ def authenhandler(req, **kwargs):
if superuser_only:
kwargs['is_superuser'] = True
try:
- user = User.objects.get(**kwargs)
- except User.DoesNotExist:
- return apache.HTTP_UNAUTHORIZED
-
- # check the password and any permission given
- if user.check_password(req.get_basic_auth_pw()):
- if permission_name:
- if user.has_perm(permission_name):
- return apache.OK
+ try:
+ user = User.objects.get(**kwargs)
+ except User.DoesNotExist:
+ return apache.HTTP_UNAUTHORIZED
+
+ # check the password and any permission given
+ if user.check_password(req.get_basic_auth_pw()):
+ if permission_name:
+ if user.has_perm(permission_name):
+ return apache.OK
+ else:
+ return apache.HTTP_UNAUTHORIZED
else:
- return apache.HTTP_UNAUTHORIZED
+ return apache.OK
else:
- return apache.OK
- else:
- return apache.HTTP_UNAUTHORIZED
+ return apache.HTTP_UNAUTHORIZED
+ finally:
+ db.connection.close()
diff --git a/django/contrib/auth/management.py b/django/contrib/auth/management.py
index 1a07417f1d..3f52681747 100644
--- a/django/contrib/auth/management.py
+++ b/django/contrib/auth/management.py
@@ -16,7 +16,7 @@ def _get_all_permissions(opts):
perms.append((_get_permission_codename(action, opts), 'Can %s %s' % (action, opts.verbose_name)))
return perms + list(opts.permissions)
-def create_permissions(app, created_models):
+def create_permissions(app, created_models, verbosity):
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import Permission
app_models = get_models(app)
@@ -27,13 +27,13 @@ def create_permissions(app, created_models):
for codename, name in _get_all_permissions(klass._meta):
p, created = Permission.objects.get_or_create(codename=codename, content_type__pk=ctype.id,
defaults={'name': name, 'content_type': ctype})
- if created:
+ if created and verbosity >= 2:
print "Adding permission '%s'" % p
-def create_superuser(app, created_models):
+def create_superuser(app, created_models, verbosity, **kwargs):
from django.contrib.auth.models import User
from django.contrib.auth.create_superuser import createsuperuser as do_create
- if User in created_models:
+ if User in created_models and kwargs.get('interactive', True):
msg = "\nYou just installed Django's auth system, which means you don't have " \
"any superusers defined.\nWould you like to create one now? (yes/no): "
confirm = raw_input(msg)
diff --git a/django/contrib/auth/middleware.py b/django/contrib/auth/middleware.py
index a6a60780a7..42dc15a366 100644
--- a/django/contrib/auth/middleware.py
+++ b/django/contrib/auth/middleware.py
@@ -1,12 +1,9 @@
class LazyUser(object):
- def __init__(self):
- self._user = None
-
def __get__(self, request, obj_type=None):
- if self._user is None:
+ if not hasattr(request, '_cached_user'):
from django.contrib.auth import get_user
- self._user = get_user(request)
- return self._user
+ request._cached_user = get_user(request)
+ return request._cached_user
class AuthenticationMiddleware(object):
def process_request(self, request):
diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
index cca3c62252..58cc07efa9 100644
--- a/django/contrib/auth/models.py
+++ b/django/contrib/auth/models.py
@@ -1,4 +1,5 @@
from django.core import validators
+from django.core.exceptions import ImproperlyConfigured
from django.db import backend, connection, models
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext_lazy as _
@@ -32,7 +33,7 @@ class Permission(models.Model):
Permissions are set globally per type of object, not per specific object instance. It is possible to say "Mary may change news stories," but it's not currently possible to say "Mary may change news stories, but only the ones she created herself" or "Mary may only change news stories that have a certain status or publication date."
- Three basic permissions -- add, create and delete -- are automatically created for each Django model.
+ Three basic permissions -- add, change and delete -- are automatically created for each Django model.
"""
name = models.CharField(_('name'), maxlength=50)
content_type = models.ForeignKey(ContentType)
@@ -91,9 +92,9 @@ class User(models.Model):
last_name = models.CharField(_('last name'), maxlength=30, blank=True)
email = models.EmailField(_('e-mail address'), blank=True)
password = models.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]'"))
- is_staff = models.BooleanField(_('staff status'), help_text=_("Designates whether the user can log into this admin site."))
+ is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts."))
- is_superuser = models.BooleanField(_('superuser status'), help_text=_("Designates that this user has all permissions without explicitly assigning them."))
+ is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
last_login = models.DateTimeField(_('last login'), default=models.LazyDate())
date_joined = models.DateTimeField(_('date joined'), default=models.LazyDate())
groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
@@ -126,6 +127,11 @@ class User(models.Model):
"Always returns False. This is a way of comparing User objects to anonymous users."
return False
+ def is_authenticated(self):
+ """Always return True. This is a way to tell if the user has been authenticated in templates.
+ """
+ return True
+
def get_full_name(self):
"Returns the first_name plus the last_name, with a space in between."
full_name = '%s %s' % (self.first_name, self.last_name)
@@ -210,6 +216,8 @@ class User(models.Model):
def has_module_perms(self, app_label):
"Returns True if the user has any permissions in the given app label."
+ if not self.is_active:
+ return False
if self.is_superuser:
return True
return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label]))
@@ -262,6 +270,15 @@ class AnonymousUser(object):
def __str__(self):
return 'AnonymousUser'
+ def __eq__(self, other):
+ return isinstance(other, self.__class__)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return 1 # instances always return the same hash value
+
def save(self):
raise NotImplementedError
@@ -293,3 +310,6 @@ class AnonymousUser(object):
def is_anonymous(self):
return True
+
+ def is_authenticated(self):
+ return False
diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py
index 97ecd6a3fd..6882755787 100644
--- a/django/contrib/auth/views.py
+++ b/django/contrib/auth/views.py
@@ -4,7 +4,7 @@ from django import forms
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.sites.models import Site
-from django.http import HttpResponse, HttpResponseRedirect
+from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
@@ -34,9 +34,8 @@ def login(request, template_name='registration/login.html'):
def logout(request, next_page=None, template_name='registration/logged_out.html'):
"Logs out the user and displays 'You are logged out' message."
from django.contrib.auth import logout
- try:
- logout(request)
- except KeyError:
+ logout(request)
+ if next_page is None:
return render_to_response(template_name, {'title': _('Logged out')}, context_instance=RequestContext(request))
else:
# Redirect to this page until the session has been cleared.
@@ -50,7 +49,8 @@ def redirect_to_login(next, login_url=LOGIN_URL):
"Redirects the user to the login page, passing the given 'next' page"
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next))
-def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html'):
+def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
+ email_template_name='registration/password_reset_email.html'):
new_data, errors = {}, {}
form = PasswordResetForm()
if request.POST:
@@ -58,9 +58,9 @@ def password_reset(request, is_admin_site=False, template_name='registration/pas
errors = form.get_validation_errors(new_data)
if not errors:
if is_admin_site:
- form.save(request.META['HTTP_HOST'])
+ form.save(domain_override=request.META['HTTP_HOST'])
else:
- form.save()
+ form.save(email_template_name=email_template_name)
return HttpResponseRedirect('%sdone/' % request.path)
return render_to_response(template_name, {'form': forms.FormWrapper(form, new_data, errors)},
context_instance=RequestContext(request))
diff --git a/django/contrib/comments/feeds.py b/django/contrib/comments/feeds.py
index cad8c881a1..34cf3d9cef 100644
--- a/django/contrib/comments/feeds.py
+++ b/django/contrib/comments/feeds.py
@@ -1,7 +1,6 @@
from django.conf import settings
from django.contrib.comments.models import Comment, FreeComment
from django.contrib.syndication.feeds import Feed
-from django.core.exceptions import ObjectDoesNotExist
from django.contrib.sites.models import Site
class LatestFreeCommentsFeed(Feed):
@@ -37,6 +36,6 @@ class LatestCommentsFeed(LatestFreeCommentsFeed):
qs = qs.filter(is_removed=False)
if settings.COMMENTS_BANNED_USERS_GROUP:
where = ['user_id NOT IN (SELECT user_id FROM auth_users_group WHERE group_id = %s)']
- params = [COMMENTS_BANNED_USERS_GROUP]
+ params = [settings.COMMENTS_BANNED_USERS_GROUP]
qs = qs.extra(where=where, params=params)
return qs
diff --git a/django/contrib/comments/models.py b/django/contrib/comments/models.py
index 23b0dfbde6..a8aff1cfb3 100644
--- a/django/contrib/comments/models.py
+++ b/django/contrib/comments/models.py
@@ -51,7 +51,7 @@ class CommentManager(models.Manager):
extra_kwargs.setdefault('select', {})
extra_kwargs['select']['_karma_total_good'] = 'SELECT COUNT(*) FROM comments_karmascore, comments_comment WHERE comments_karmascore.comment_id=comments_comment.id AND score=1'
extra_kwargs['select']['_karma_total_bad'] = 'SELECT COUNT(*) FROM comments_karmascore, comments_comment WHERE comments_karmascore.comment_id=comments_comment.id AND score=-1'
- return self.filter(**kwargs).extra(**extra_kwargs)
+ return self.filter(**kwargs).extra(**extra_kwargs)
def user_is_moderator(self, user):
if user.is_superuser:
diff --git a/django/contrib/comments/templates/comments/form.html b/django/contrib/comments/templates/comments/form.html
index 4a6b5fc320..c5aa7686a3 100644
--- a/django/contrib/comments/templates/comments/form.html
+++ b/django/contrib/comments/templates/comments/form.html
@@ -2,10 +2,10 @@
{% if display_form %}
<form {% if photos_optional or photos_required %}enctype="multipart/form-data" {% endif %}action="/comments/post/" method="post">
-{% if user.is_anonymous %}
-<p><label for="id_username">{% trans "Username:" %}</label> <input type="text" name="username" id="id_username" /><br />{% trans "Password:" %} <input type="password" name="password" id="id_password" /> (<a href="/accounts/password_reset/">{% trans "Forgotten your password?" %}</a>)</p>
-{% else %}
+{% if user.is_authenticated %}
<p>{% trans "Username:" %} <strong>{{ user.username }}</strong> (<a href="/accounts/logout/">{% trans "Log out" %}</a>)</p>
+{% else %}
+<p><label for="id_username">{% trans "Username:" %}</label> <input type="text" name="username" id="id_username" /><br />{% trans "Password:" %} <input type="password" name="password" id="id_password" /> (<a href="/accounts/password_reset/">{% trans "Forgotten your password?" %}</a>)</p>
{% endif %}
{% if ratings_optional or ratings_required %}
diff --git a/django/contrib/comments/templatetags/comments.py b/django/contrib/comments/templatetags/comments.py
index a3893fdf61..c3a2fd40d8 100644
--- a/django/contrib/comments/templatetags/comments.py
+++ b/django/contrib/comments/templatetags/comments.py
@@ -114,7 +114,7 @@ class CommentListNode(template.Node):
comment_list = get_list_function(**kwargs).order_by(self.ordering + 'submit_date').select_related()
if not self.free:
- if context.has_key('user') and not context['user'].is_anonymous():
+ if context.has_key('user') and context['user'].is_authenticated():
user_id = context['user'].id
context['user_can_moderate_comments'] = Comment.objects.user_is_moderator(context['user'])
else:
diff --git a/django/contrib/comments/views/comments.py b/django/contrib/comments/views/comments.py
index c32a82f4d8..3640da90fe 100644
--- a/django/contrib/comments/views/comments.py
+++ b/django/contrib/comments/views/comments.py
@@ -5,7 +5,7 @@ from django.http import Http404
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import render_to_response
from django.template import RequestContext
-from django.contrib.comments.models import Comment, FreeComment, PHOTOS_REQUIRED, PHOTOS_OPTIONAL, RATINGS_REQUIRED, RATINGS_OPTIONAL, IS_PUBLIC
+from django.contrib.comments.models import Comment, FreeComment, RATINGS_REQUIRED, RATINGS_OPTIONAL, IS_PUBLIC
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.forms import AuthenticationForm
from django.http import HttpResponseRedirect
@@ -63,7 +63,7 @@ class PublicCommentManipulator(AuthenticationForm):
validator_list=get_validator_list(8),
),
])
- if not user.is_anonymous():
+ if user.is_authenticated():
self["username"].is_required = False
self["username"].validator_list = []
self["password"].is_required = False
@@ -109,7 +109,7 @@ class PublicCommentManipulator(AuthenticationForm):
# send the comment to the managers.
if self.user_cache.comment_set.count() <= settings.COMMENTS_FIRST_FEW:
message = ngettext('This comment was posted by a user who has posted fewer than %(count)s comment:\n\n%(text)s',
- 'This comment was posted by a user who has posted fewer than %(count)s comments:\n\n%(text)s') % \
+ 'This comment was posted by a user who has posted fewer than %(count)s comments:\n\n%(text)s', settings.COMMENTS_FIRST_FEW) % \
{'count': settings.COMMENTS_FIRST_FEW, 'text': c.get_as_text()}
mail_managers("Comment posted by rookie user", message)
if settings.COMMENTS_SKETCHY_USERS_GROUP and settings.COMMENTS_SKETCHY_USERS_GROUP in [g.id for g in self.user_cache.get_group_list()]:
@@ -217,7 +217,7 @@ def post_comment(request):
errors = manipulator.get_validation_errors(new_data)
# If user gave correct username/password and wasn't already logged in, log them in
# so they don't have to enter a username/password again.
- if manipulator.get_user() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']):
+ if manipulator.get_user() and not manipulator.get_user().is_authenticated() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']):
from django.contrib.auth import login
login(request, manipulator.get_user())
if errors or request.POST.has_key('preview'):
diff --git a/django/contrib/comments/views/karma.py b/django/contrib/comments/views/karma.py
index becb02e128..8c18523feb 100644
--- a/django/contrib/comments/views/karma.py
+++ b/django/contrib/comments/views/karma.py
@@ -15,7 +15,7 @@ def vote(request, comment_id, vote):
rating = {'up': 1, 'down': -1}.get(vote, False)
if not rating:
raise Http404, "Invalid vote"
- if request.user.is_anonymous():
+ if not request.user.is_authenticated():
raise Http404, _("Anonymous users cannot vote")
try:
comment = Comment.objects.get(pk=comment_id)
diff --git a/django/contrib/contenttypes/management.py b/django/contrib/contenttypes/management.py
index a9174584bc..de3a685477 100644
--- a/django/contrib/contenttypes/management.py
+++ b/django/contrib/contenttypes/management.py
@@ -5,7 +5,7 @@ Creates content types for all installed models.
from django.dispatch import dispatcher
from django.db.models import get_models, signals
-def create_contenttypes(app, created_models):
+def create_contenttypes(app, created_models, verbosity):
from django.contrib.contenttypes.models import ContentType
app_models = get_models(app)
if not app_models:
@@ -19,6 +19,7 @@ def create_contenttypes(app, created_models):
ct = ContentType(name=str(opts.verbose_name),
app_label=opts.app_label, model=opts.object_name.lower())
ct.save()
- print "Adding content type '%s | %s'" % (ct.app_label, ct.model)
+ if verbosity >= 2:
+ print "Adding content type '%s | %s'" % (ct.app_label, ct.model)
dispatcher.connect(create_contenttypes, signal=signals.post_syncdb)
diff --git a/django/contrib/flatpages/README.TXT b/django/contrib/flatpages/README.TXT
index e46aa1f9bf..d3071377f5 100644
--- a/django/contrib/flatpages/README.TXT
+++ b/django/contrib/flatpages/README.TXT
@@ -2,7 +2,7 @@ This is an optional add-on app, flatpages.
For full documentation, see either of these:
- * The file django/docs/flatpages.txt in the Django distribution
+ * The file docs/flatpages.txt in the Django distribution
* http://www.djangoproject.com/documentation/flatpages/ on the Web
-Both have identical content. \ No newline at end of file
+Both have identical content.
diff --git a/django/contrib/flatpages/views.py b/django/contrib/flatpages/views.py
index 1441f6f3a3..f386a52101 100644
--- a/django/contrib/flatpages/views.py
+++ b/django/contrib/flatpages/views.py
@@ -3,6 +3,7 @@ from django.template import loader, RequestContext
from django.shortcuts import get_object_or_404
from django.http import HttpResponse
from django.conf import settings
+from django.core.xheaders import populate_xheaders
DEFAULT_TEMPLATE = 'flatpages/default.html'
@@ -22,7 +23,7 @@ def flatpage(request, url):
f = get_object_or_404(FlatPage, url__exact=url, sites__id__exact=settings.SITE_ID)
# If registration is required for accessing this page, and the user isn't
# logged in, redirect to the login page.
- if f.registration_required and request.user.is_anonymous():
+ if f.registration_required and not request.user.is_authenticated():
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(request.path)
if f.template_name:
@@ -32,4 +33,6 @@ def flatpage(request, url):
c = RequestContext(request, {
'flatpage': f,
})
- return HttpResponse(t.render(c))
+ response = HttpResponse(t.render(c))
+ populate_xheaders(request, response, FlatPage, f.id)
+ return response
diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py
index dde4f1a6c0..2337ad8a61 100644
--- a/django/contrib/sessions/middleware.py
+++ b/django/contrib/sessions/middleware.py
@@ -88,5 +88,6 @@ class SessionMiddleware(object):
new_session = Session.objects.save(session_key, request.session._session,
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,
- max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN)
+ max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
+ secure=settings.SESSION_COOKIE_SECURE or None)
return response
diff --git a/django/contrib/sessions/models.py b/django/contrib/sessions/models.py
index 8e2d011e3f..f684cd381e 100644
--- a/django/contrib/sessions/models.py
+++ b/django/contrib/sessions/models.py
@@ -32,11 +32,21 @@ class SessionManager(models.Manager):
return s
class Session(models.Model):
- """Django provides full support for anonymous sessions. The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis. It stores data on the server side and abstracts the sending and receiving of cookies. Cookies contain a session ID -- not the data itself.
+ """
+ Django provides full support for anonymous sessions. The session
+ framework lets you store and retrieve arbitrary data on a
+ per-site-visitor basis. It stores data on the server side and
+ abstracts the sending and receiving of cookies. Cookies contain a
+ session ID -- not the data itself.
- The Django sessions framework is entirely cookie-based. It does not fall back to putting session IDs in URLs. This is an intentional design decision. Not only does that behavior make URLs ugly, it makes your site vulnerable to session-ID theft via the "Referer" header.
+ The Django sessions framework is entirely cookie-based. It does
+ not fall back to putting session IDs in URLs. This is an intentional
+ design decision. Not only does that behavior make URLs ugly, it makes
+ your site vulnerable to session-ID theft via the "Referer" header.
- For complete documentation on using Sessions in your code, consult the sessions documentation that is shipped with Django (also available on the Django website).
+ For complete documentation on using Sessions in your code, consult
+ the sessions documentation that is shipped with Django (also available
+ on the Django website).
"""
session_key = models.CharField(_('session key'), maxlength=40, primary_key=True)
session_data = models.TextField(_('session data'))
diff --git a/django/contrib/sitemaps/__init__.py b/django/contrib/sitemaps/__init__.py
new file mode 100644
index 0000000000..2c76e13c22
--- /dev/null
+++ b/django/contrib/sitemaps/__init__.py
@@ -0,0 +1,90 @@
+from django.core import urlresolvers
+import urllib
+
+PING_URL = "http://www.google.com/webmasters/sitemaps/ping"
+
+class SitemapNotFound(Exception):
+ pass
+
+def ping_google(sitemap_url=None, ping_url=PING_URL):
+ """
+ Alerts Google that the sitemap for the current site has been updated.
+ If sitemap_url is provided, it should be an absolute path to the sitemap
+ for this site -- e.g., '/sitemap.xml'. If sitemap_url is not provided, this
+ function will attempt to deduce it by using urlresolvers.reverse().
+ """
+ if sitemap_url is None:
+ try:
+ # First, try to get the "index" sitemap URL.
+ sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.index')
+ except urlresolvers.NoReverseMatch:
+ try:
+ # Next, try for the "global" sitemap URL.
+ sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.sitemap')
+ except urlresolvers.NoReverseMatch:
+ pass
+
+ if sitemap_url is None:
+ raise SitemapNotFound("You didn't provide a sitemap_url, and the sitemap URL couldn't be auto-detected.")
+
+ from django.contrib.sites.models import Site
+ current_site = Site.objects.get_current()
+ url = "%s%s" % (current_site.domain, sitemap)
+ params = urllib.urlencode({'sitemap':url})
+ urllib.urlopen("%s?%s" % (ping_url, params))
+
+class Sitemap:
+ def __get(self, name, obj, default=None):
+ try:
+ attr = getattr(self, name)
+ except AttributeError:
+ return default
+ if callable(attr):
+ return attr(obj)
+ return attr
+
+ def items(self):
+ return []
+
+ def location(self, obj):
+ return obj.get_absolute_url()
+
+ def get_urls(self):
+ from django.contrib.sites.models import Site
+ current_site = Site.objects.get_current()
+ urls = []
+ for item in self.items():
+ loc = "http://%s%s" % (current_site.domain, self.__get('location', item))
+ url_info = {
+ 'location': loc,
+ 'lastmod': self.__get('lastmod', item, None),
+ 'changefreq': self.__get('changefreq', item, None),
+ 'priority': self.__get('priority', item, None)
+ }
+ urls.append(url_info)
+ return urls
+
+class FlatPageSitemap(Sitemap):
+ def items(self):
+ from django.contrib.sites.models import Site
+ current_site = Site.objects.get_current()
+ return current_site.flatpage_set.all()
+
+class GenericSitemap(Sitemap):
+ priority = None
+ changefreq = None
+
+ def __init__(self, info_dict, priority=None, changefreq=None):
+ self.queryset = info_dict['queryset']
+ self.date_field = info_dict.get('date_field', None)
+ self.priority = priority
+ self.changefreq = changefreq
+
+ def items(self):
+ # Make sure to return a clone; we don't want premature evaluation.
+ return self.queryset.filter()
+
+ def lastmod(self, item):
+ if self.date_field is not None:
+ return getattr(item, self.date_field)
+ return None
diff --git a/django/contrib/sitemaps/templates/sitemap.xml b/django/contrib/sitemaps/templates/sitemap.xml
new file mode 100644
index 0000000000..ad24c045d4
--- /dev/null
+++ b/django/contrib/sitemaps/templates/sitemap.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
+{% spaceless %}
+{% for url in urlset %}
+ <url>
+ <loc>{{ url.location|escape }}</loc>
+ {% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
+ {% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
+ {% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
+ </url>
+{% endfor %}
+{% endspaceless %}
+</urlset>
diff --git a/django/contrib/sitemaps/templates/sitemap_index.xml b/django/contrib/sitemaps/templates/sitemap_index.xml
new file mode 100644
index 0000000000..c89b192ecc
--- /dev/null
+++ b/django/contrib/sitemaps/templates/sitemap_index.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84">
+{% for location in sitemaps %}<sitemap><loc>{{ location|escape }}</loc></sitemap>{% endfor %}
+</sitemapindex>
diff --git a/django/contrib/sitemaps/views.py b/django/contrib/sitemaps/views.py
new file mode 100644
index 0000000000..576e3d0bb8
--- /dev/null
+++ b/django/contrib/sitemaps/views.py
@@ -0,0 +1,30 @@
+from django.http import HttpResponse, Http404
+from django.template import loader
+from django.contrib.sites.models import Site
+from django.core import urlresolvers
+
+def index(request, sitemaps):
+ current_site = Site.objects.get_current()
+ sites = []
+ protocol = request.is_secure() and 'https' or 'http'
+ for section in sitemaps.keys():
+ sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.sitemap', kwargs={'section': section})
+ sites.append('%s://%s%s' % (protocol, current_site.domain, sitemap_url))
+ xml = loader.render_to_string('sitemap_index.xml', {'sitemaps': sites})
+ return HttpResponse(xml, mimetype='application/xml')
+
+def sitemap(request, sitemaps, section=None):
+ maps, urls = [], []
+ if section is not None:
+ if not sitemaps.has_key(section):
+ raise Http404("No sitemap available for section: %r" % section)
+ maps.append(sitemaps[section])
+ else:
+ maps = sitemaps.values()
+ for site in maps:
+ if callable(site):
+ urls.extend(site().get_urls())
+ else:
+ urls.extend(site.get_urls())
+ xml = loader.render_to_string('sitemap.xml', {'urlset': urls})
+ return HttpResponse(xml, mimetype='application/xml')
diff --git a/django/contrib/sites/management.py b/django/contrib/sites/management.py
index 0e1a50227a..6831cab96d 100644
--- a/django/contrib/sites/management.py
+++ b/django/contrib/sites/management.py
@@ -7,9 +7,10 @@ from django.db.models import signals
from django.contrib.sites.models import Site
from django.contrib.sites import models as site_app
-def create_default_site(app, created_models):
+def create_default_site(app, created_models, verbosity):
if Site in created_models:
- print "Creating example.com Site object"
+ if verbosity >= 2:
+ print "Creating example.com Site object"
s = Site(domain="example.com", name="example.com")
s.save()
diff --git a/django/contrib/syndication/feeds.py b/django/contrib/syndication/feeds.py
index e648c6c746..119615a0b9 100644
--- a/django/contrib/syndication/feeds.py
+++ b/django/contrib/syndication/feeds.py
@@ -73,7 +73,7 @@ class Feed(object):
link = link,
description = self.__get_dynamic_attr('description', obj),
language = settings.LANGUAGE_CODE.decode(),
- feed_url = add_domain(current_site, self.feed_url),
+ feed_url = add_domain(current_site, self.__get_dynamic_attr('feed_url', obj)),
author_name = self.__get_dynamic_attr('author_name', obj),
author_link = self.__get_dynamic_attr('author_link', obj),
author_email = self.__get_dynamic_attr('author_email', obj),
diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py
index 1b54addded..4a0d44a44e 100644
--- a/django/core/cache/backends/db.py
+++ b/django/core/cache/backends/db.py
@@ -1,7 +1,7 @@
"Database cache backend."
from django.core.cache.backends.base import BaseCache
-from django.db import connection, transaction
+from django.db import connection, transaction, DatabaseError
import base64, time
from datetime import datetime
try:
diff --git a/django/core/cache/backends/locmem.py b/django/core/cache/backends/locmem.py
index 5bd6da5857..0e21b80ed8 100644
--- a/django/core/cache/backends/locmem.py
+++ b/django/core/cache/backends/locmem.py
@@ -3,10 +3,6 @@
from django.core.cache.backends.simple import CacheClass as SimpleCacheClass
from django.utils.synch import RWLock
import copy, time
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
class CacheClass(SimpleCacheClass):
def __init__(self, host, params):
diff --git a/django/core/cache/backends/memcached.py b/django/core/cache/backends/memcached.py
index 86ae096d2c..180f95da73 100644
--- a/django/core/cache/backends/memcached.py
+++ b/django/core/cache/backends/memcached.py
@@ -20,7 +20,7 @@ class CacheClass(BaseCache):
return val
def set(self, key, value, timeout=0):
- self._cache.set(key, value, timeout)
+ self._cache.set(key, value, timeout or self.default_timeout)
def delete(self, key):
self._cache.delete(key)
diff --git a/django/core/context_processors.py b/django/core/context_processors.py
index 2ae9a6d972..f4b288dfc4 100644
--- a/django/core/context_processors.py
+++ b/django/core/context_processors.py
@@ -51,15 +51,19 @@ def request(request):
class PermLookupDict(object):
def __init__(self, user, module_name):
self.user, self.module_name = user, module_name
+
def __repr__(self):
- return str(self.user.get_permission_list())
+ return str(self.user.get_all_permissions())
+
def __getitem__(self, perm_name):
return self.user.has_perm("%s.%s" % (self.module_name, perm_name))
+
def __nonzero__(self):
return self.user.has_module_perms(self.module_name)
class PermWrapper(object):
def __init__(self, user):
self.user = user
+
def __getitem__(self, module_name):
return PermLookupDict(self.user, module_name)
diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py
index c25ff2b14e..213c528952 100644
--- a/django/core/handlers/base.py
+++ b/django/core/handlers/base.py
@@ -48,7 +48,7 @@ class BaseHandler(object):
if hasattr(mw_instance, 'process_exception'):
self._exception_middleware.insert(0, mw_instance.process_exception)
- def get_response(self, path, request):
+ def get_response(self, request):
"Returns an HttpResponse object for the given HttpRequest"
from django.core import exceptions, urlresolvers
from django.core.mail import mail_admins
@@ -62,7 +62,7 @@ class BaseHandler(object):
resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF)
try:
- callback, callback_args, callback_kwargs = resolver.resolve(path)
+ callback, callback_args, callback_kwargs = resolver.resolve(request.path)
# Apply view middleware
for middleware_method in self._view_middleware:
@@ -89,7 +89,8 @@ class BaseHandler(object):
return response
except http.Http404, e:
if settings.DEBUG:
- return self.get_technical_error_response(request, is404=True, exception=e)
+ from django.views import debug
+ return debug.technical_404_response(request, e)
else:
callback, param_dict = resolver.resolve404()
return callback(request, **param_dict)
@@ -99,40 +100,23 @@ class BaseHandler(object):
pass # See http://code.djangoproject.com/ticket/1023
except: # Handle everything else, including SuspiciousOperation, etc.
if settings.DEBUG:
- return self.get_technical_error_response(request)
+ from django.views import debug
+ return debug.technical_500_response(request, *sys.exc_info())
else:
# Get the exception info now, in case another exception is thrown later.
exc_info = sys.exc_info()
receivers = dispatcher.send(signal=signals.got_request_exception)
# When DEBUG is False, send an error message to the admins.
- subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', ''))
+ subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
try:
request_repr = repr(request)
except:
request_repr = "Request repr() unavailable"
message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr)
mail_admins(subject, message, fail_silently=True)
- return self.get_friendly_error_response(request, resolver)
-
- def get_friendly_error_response(self, request, resolver):
- """
- Returns an HttpResponse that displays a PUBLIC error message for a
- fundamental error.
- """
- from django.core import urlresolvers
- callback, param_dict = resolver.resolve500()
- return callback(request, **param_dict)
-
- def get_technical_error_response(self, request, is404=False, exception=None):
- """
- Returns an HttpResponse that displays a TECHNICAL error message for a
- fundamental error.
- """
- from django.views import debug
- if is404:
- return debug.technical_404_response(request, exception)
- else:
- return debug.technical_500_response(request, *sys.exc_info())
+ # Return an HttpResponse that displays a friendly error message.
+ callback, param_dict = resolver.resolve500()
+ return callback(request, **param_dict)
def _get_traceback(self, exc_info=None):
"Helper function to return the traceback as a string"
diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py
index 5a20ce9f67..5fc41a048b 100644
--- a/django/core/handlers/modpython.py
+++ b/django/core/handlers/modpython.py
@@ -16,13 +16,34 @@ class ModPythonRequest(http.HttpRequest):
self.path = req.uri
def __repr__(self):
+ # Since this is called as part of error handling, we need to be very
+ # robust against potentially malformed input.
+ try:
+ get = pformat(self.GET)
+ except:
+ get = '<could not parse>'
+ try:
+ post = pformat(self.POST)
+ except:
+ post = '<could not parse>'
+ try:
+ cookies = pformat(self.COOKIES)
+ except:
+ cookies = '<could not parse>'
+ try:
+ meta = pformat(self.META)
+ except:
+ meta = '<could not parse>'
return '<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
- (self.path, pformat(self.GET), pformat(self.POST), pformat(self.COOKIES),
- pformat(self.META))
+ (self.path, get, post, cookies, meta)
def get_full_path(self):
return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '')
+ def is_secure(self):
+ # Note: modpython 3.2.10+ has req.is_https(), but we need to support previous versions
+ return self._req.subprocess_env.has_key('HTTPS') and self._req.subprocess_env['HTTPS'] == 'on'
+
def _load_post_and_files(self):
"Populates self._post and self._files"
if self._req.headers_in.has_key('content-type') and self._req.headers_in['content-type'].startswith('multipart'):
@@ -119,10 +140,6 @@ class ModPythonHandler(BaseHandler):
# that use settings now can work
from django.conf import settings
- if settings.ENABLE_PSYCO:
- import psyco
- psyco.profile()
-
# if we need to set up middleware, now that settings works we can do it now.
if self._request_middleware is None:
self.load_middleware()
@@ -130,7 +147,7 @@ class ModPythonHandler(BaseHandler):
dispatcher.send(signal=signals.request_started)
try:
request = ModPythonRequest(req)
- response = self.get_response(req.uri, request)
+ response = self.get_response(request)
# Apply response middleware
for middleware_method in self._response_middleware:
@@ -140,21 +157,20 @@ class ModPythonHandler(BaseHandler):
dispatcher.send(signal=signals.request_finished)
# Convert our custom HttpResponse object back into the mod_python req.
- populate_apache_request(response, req)
- return 0 # mod_python.apache.OK
+ req.content_type = response['Content-Type']
+ for key, value in response.headers.items():
+ if key != 'Content-Type':
+ req.headers_out[key] = value
+ for c in response.cookies.values():
+ req.headers_out.add('Set-Cookie', c.output(header=''))
+ req.status = response.status_code
+ try:
+ for chunk in response:
+ req.write(chunk)
+ finally:
+ response.close()
-def populate_apache_request(http_response, mod_python_req):
- "Populates the mod_python request object with an HttpResponse"
- from django.conf import settings
- mod_python_req.content_type = http_response['Content-Type']
- for key, value in http_response.headers.items():
- if key != 'Content-Type':
- mod_python_req.headers_out[key] = value
- for c in http_response.cookies.values():
- mod_python_req.headers_out.add('Set-Cookie', c.output(header=''))
- mod_python_req.status = http_response.status_code
- for chunk in http_response.iterator:
- mod_python_req.write(chunk)
+ return 0 # mod_python.apache.OK
def handler(req):
# mod_python hooks into this function.
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
index 00a9a2ca53..2998bd31f6 100644
--- a/django/core/handlers/wsgi.py
+++ b/django/core/handlers/wsgi.py
@@ -4,6 +4,11 @@ from django.dispatch import dispatcher
from django.utils import datastructures
from django import http
from pprint import pformat
+from shutil import copyfileobj
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
STATUS_CODE_TEXT = {
@@ -50,6 +55,21 @@ STATUS_CODE_TEXT = {
505: 'HTTP VERSION NOT SUPPORTED',
}
+def safe_copyfileobj(fsrc, fdst, length=16*1024, size=0):
+ """
+ A version of shutil.copyfileobj that will not read more than 'size' bytes.
+ This makes it safe from clients sending more than CONTENT_LENGTH bytes of
+ data in the body.
+ """
+ if not size:
+ return copyfileobj(fsrc, fdst, length)
+ while size > 0:
+ buf = fsrc.read(min(length, size))
+ if not buf:
+ break
+ fdst.write(buf)
+ size -= len(buf)
+
class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
self.environ = environ
@@ -58,14 +78,33 @@ class WSGIRequest(http.HttpRequest):
self.method = environ['REQUEST_METHOD'].upper()
def __repr__(self):
- from pprint import pformat
- return '<DjangoRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
- (pformat(self.GET), pformat(self.POST), pformat(self.COOKIES),
- pformat(self.META))
+ # Since this is called as part of error handling, we need to be very
+ # robust against potentially malformed input.
+ try:
+ get = pformat(self.GET)
+ except:
+ get = '<could not parse>'
+ try:
+ post = pformat(self.POST)
+ except:
+ post = '<could not parse>'
+ try:
+ cookies = pformat(self.COOKIES)
+ except:
+ cookies = '<could not parse>'
+ try:
+ meta = pformat(self.META)
+ except:
+ meta = '<could not parse>'
+ return '<WSGIRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
+ (get, post, cookies, meta)
def get_full_path(self):
return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '')
+ def is_secure(self):
+ return self.environ.has_key('HTTPS') and self.environ['HTTPS'] == 'on'
+
def _load_post_and_files(self):
# Populates self._post and self._files
if self.method == 'POST':
@@ -117,7 +156,11 @@ class WSGIRequest(http.HttpRequest):
try:
return self._raw_post_data
except AttributeError:
- self._raw_post_data = self.environ['wsgi.input'].read(int(self.environ["CONTENT_LENGTH"]))
+ buf = StringIO()
+ content_length = int(self.environ['CONTENT_LENGTH'])
+ safe_copyfileobj(self.environ['wsgi.input'], buf, size=content_length)
+ self._raw_post_data = buf.getvalue()
+ buf.close()
return self._raw_post_data
GET = property(_get_get, _set_get)
@@ -131,10 +174,6 @@ class WSGIHandler(BaseHandler):
def __call__(self, environ, start_response):
from django.conf import settings
- if settings.ENABLE_PSYCO:
- import psyco
- psyco.profile()
-
# Set up middleware if needed. We couldn't do this earlier, because
# settings weren't available.
if self._request_middleware is None:
@@ -143,7 +182,7 @@ class WSGIHandler(BaseHandler):
dispatcher.send(signal=signals.request_started)
try:
request = WSGIRequest(environ)
- response = self.get_response(request.path, request)
+ response = self.get_response(request)
# Apply response middleware
for middleware_method in self._response_middleware:
@@ -161,4 +200,4 @@ class WSGIHandler(BaseHandler):
for c in response.cookies.values():
response_headers.append(('Set-Cookie', c.output(header='')))
start_response(status, response_headers)
- return response.iterator
+ return response
diff --git a/django/core/management.py b/django/core/management.py
index aa1a8dcf7d..437a80d5af 100644
--- a/django/core/management.py
+++ b/django/core/management.py
@@ -103,7 +103,6 @@ def get_sql_create(app):
known_models = set([model for model in _get_installed_models(_get_table_list()) if model not in app_models])
pending_references = {}
-
for model in app_models:
output, references = _get_sql_model_create(model, known_models)
final_output.extend(output)
@@ -147,7 +146,7 @@ def _get_sql_model_create(model, known_models=set()):
table_output = []
pending_references = {}
for f in opts.fields:
- if isinstance(f, models.ForeignKey):
+ if isinstance(f, (models.ForeignKey, models.OneToOneField)):
rel_field = f.rel.get_related_field()
data_type = get_rel_data_type(rel_field)
else:
@@ -347,7 +346,7 @@ def get_sql_initial_data_for_model(model):
os.path.join(app_dir, "%s.sql" % opts.object_name.lower())]
for sql_file in sql_files:
if os.path.exists(sql_file):
- fp = open(sql_file)
+ fp = open(sql_file, 'U')
for statement in statements.split(fp.read()):
if statement.strip():
output.append(statement + ";")
@@ -398,21 +397,11 @@ get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting Postg
get_sql_sequence_reset.args = APP_ARGS
def get_sql_indexes(app):
- "Returns a list of the CREATE INDEX SQL statements for the given app."
- from django.db import backend, models
+ "Returns a list of the CREATE INDEX SQL statements for all models in the given app."
+ from django.db import models
output = []
-
for model in models.get_models(app):
- for f in model._meta.fields:
- if f.db_index:
- unique = f.unique and 'UNIQUE ' or ''
- output.append(
- style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \
- style.SQL_TABLE('%s_%s' % (model._meta.db_table, f.column)) + ' ' + \
- style.SQL_KEYWORD('ON') + ' ' + \
- style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \
- "(%s);" % style.SQL_FIELD(backend.quote_name(f.column))
- )
+ output.extend(get_sql_indexes_for_model(model))
return output
get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)."
get_sql_indexes.args = APP_ARGS
@@ -639,13 +628,30 @@ def get_sql_evolution_check_for_dead_fields(klass, new_table_name):
output.append( '-- end warning' )
return output
+def get_sql_indexes_for_model(model):
+ "Returns the CREATE INDEX SQL statements for a single model"
+ from django.db import backend
+ output = []
+
+ for f in model._meta.fields:
+ if f.db_index:
+ unique = f.unique and 'UNIQUE ' or ''
+ output.append(
+ style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \
+ style.SQL_TABLE('%s_%s' % (model._meta.db_table, f.column)) + ' ' + \
+ style.SQL_KEYWORD('ON') + ' ' + \
+ style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \
+ "(%s);" % style.SQL_FIELD(backend.quote_name(f.column))
+ )
+ return output
+
def get_sql_all(app):
"Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module."
return get_sql_create(app) + get_sql_initial_data(app) + get_sql_indexes(app)
get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)."
get_sql_all.args = APP_ARGS
-def syncdb():
+def syncdb(verbosity=1, interactive=True):
"Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
from django.db import connection, transaction, models, get_creation_module
from django.db.models import signals
@@ -679,21 +685,22 @@ def syncdb():
pending_references = {}
for app in models.get_apps():
+ app_name = app.__name__.split('.')[-2]
model_list = models.get_models(app)
for model in model_list:
# Create the model's database table, if it doesn't already exist.
+ if verbosity >= 2:
+ print "Processing %s.%s model" % (app_name, model._meta.object_name)
if model._meta.db_table in table_list or model._meta.aka in table_list or len(set(model._meta.aka) & set(table_list))>0:
continue
sql, references = _get_sql_model_create(model, seen_models)
seen_models.add(model)
created_models.add(model)
for refto, refs in references.items():
- try:
- pending_references[refto].extend(refs)
- except KeyError:
- pending_references[refto] = refs
+ pending_references.setdefault(refto, []).extend(refs)
sql.extend(_get_sql_for_pending_references(model, pending_references))
- print "Creating table %s" % model._meta.db_table
+ if verbosity >= 1:
+ print "Creating table %s" % model._meta.db_table
for statement in sql:
cursor.execute(statement)
table_list.append(model._meta.db_table)
@@ -702,7 +709,8 @@ def syncdb():
if model in created_models:
sql = _get_many_to_many_sql_for_model(model)
if sql:
- print "Creating many-to-many tables for %s model" % model.__name__
+ if verbosity >= 2:
+ print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name)
for statement in sql:
cursor.execute(statement)
@@ -715,8 +723,12 @@ def syncdb():
# Send the post_syncdb signal, so individual apps can do whatever they need
# to do at this point.
for app in models.get_apps():
+ app_name = app.__name__.split('.')[-2]
+ if verbosity >= 2:
+ print "Running post-sync handlers for application", app_name
dispatcher.send(signal=signals.post_syncdb, sender=app,
- app=app, created_models=created_models)
+ app=app, created_models=created_models,
+ verbosity=verbosity, interactive=interactive)
# Install initial data for the app (but only if this is a model we've
# just created)
@@ -724,13 +736,33 @@ def syncdb():
if model in created_models:
initial_sql = get_sql_initial_data_for_model(model)
if initial_sql:
- print "Installing initial data for %s model" % model._meta.object_name
+ if verbosity >= 1:
+ print "Installing initial data for %s.%s model" % (app_name, model._meta.object_name)
try:
for sql in initial_sql:
cursor.execute(sql)
except Exception, e:
- sys.stderr.write("Failed to install initial SQL data for %s model: %s" % \
- (model._meta.object_name, e))
+ sys.stderr.write("Failed to install initial SQL data for %s.%s model: %s" % \
+ (app_name, model._meta.object_name, e))
+ transaction.rollback_unless_managed()
+ else:
+ transaction.commit_unless_managed()
+
+ # Install SQL indicies for all newly created models
+ for app in models.get_apps():
+ app_name = app.__name__.split('.')[-2]
+ for model in models.get_models(app):
+ if model in created_models:
+ index_sql = get_sql_indexes_for_model(model)
+ if index_sql:
+ if verbosity >= 1:
+ print "Installing index for %s.%s model" % (app_name, model._meta.object_name)
+ try:
+ for sql in index_sql:
+ cursor.execute(sql)
+ except Exception, e:
+ sys.stderr.write("Failed to install index for %s.%s model: %s" % \
+ (app_name, model._meta.object_name, e))
transaction.rollback_unless_managed()
else:
transaction.commit_unless_managed()
@@ -774,7 +806,7 @@ def diffsettings():
# Inspired by Postfix's "postconf -n".
from django.conf import settings, global_settings
- user_settings = _module_to_dict(settings)
+ user_settings = _module_to_dict(settings._target)
default_settings = _module_to_dict(global_settings)
output = []
@@ -818,9 +850,10 @@ The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database."
install.args = APP_ARGS
-def reset(app):
+def reset(app, interactive=True):
"Executes the equivalent of 'get_sql_reset' in the current database."
from django.db import connection, transaction
+ from django.conf import settings
app_name = app.__name__.split('.')[-2]
disable_termcolors()
@@ -829,21 +862,26 @@ def reset(app):
_check_for_validation_errors(app)
sql_list = get_sql_reset(app)
- confirm = raw_input("""
+ if interactive:
+ confirm = raw_input("""
You have requested a database reset.
-This will IRREVERSIBLY DESTROY any data in your database.
+This will IRREVERSIBLY DESTROY any data for
+the "%s" application in the database "%s".
Are you sure you want to do this?
-Type 'yes' to continue, or 'no' to cancel: """)
+Type 'yes' to continue, or 'no' to cancel: """ % (app_name, settings.DATABASE_NAME))
+ else:
+ confirm = 'yes'
+
if confirm == 'yes':
try:
cursor = connection.cursor()
for sql in sql_list:
cursor.execute(sql)
except Exception, e:
- sys.stderr.write(style.ERROR("""Error: %s couldn't be installed. Possible reasons:
+ sys.stderr.write(style.ERROR("""Error: %s couldn't be reset. Possible reasons:
* The database isn't running or isn't configured correctly.
- * At least one of the database tables already exists.
+ * At least one of the database tables doesn't exist.
* The SQL was invalid.
Hint: Look at the output of 'django-admin.py sqlreset %s'. That's the SQL this command wasn't able to run.
The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
@@ -1042,7 +1080,8 @@ def get_validation_errors(outfile, app=None):
validates all models of all installed apps. Writes errors, if any, to outfile.
Returns number of errors.
"""
- from django.db import models
+ from django.conf import settings
+ from django.db import models, connection
from django.db.models.loading import get_app_errors
from django.db.models.fields.related import RelatedObject
@@ -1084,6 +1123,12 @@ def get_validation_errors(outfile, app=None):
if f.db_index not in (None, True, False):
e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name)
+ # Check that maxlength <= 255 if using older MySQL versions.
+ if settings.DATABASE_ENGINE == 'mysql':
+ db_version = connection.get_server_version()
+ if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.maxlength > 255:
+ e.add(opts, '"%s": %s cannot have a "maxlength" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]])))
+
# Check to see if the related field will clash with any
# existing fields, m2m fields, m2m related objects or related objects
if f.rel:
@@ -1125,27 +1170,32 @@ def get_validation_errors(outfile, app=None):
rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
rel_query_name = f.related_query_name()
- for r in rel_opts.fields:
- if r.name == rel_name:
- e.add(opts, "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
- if r.name == rel_query_name:
- e.add(opts, "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
- for r in rel_opts.many_to_many:
- if r.name == rel_name:
- e.add(opts, "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
- if r.name == rel_query_name:
- e.add(opts, "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
- for r in rel_opts.get_all_related_many_to_many_objects():
- if r.field is not f:
+ # If rel_name is none, there is no reverse accessor.
+ # (This only occurs for symmetrical m2m relations to self).
+ # If this is the case, there are no clashes to check for this field, as
+ # there are no reverse descriptors for this field.
+ if rel_name is not None:
+ for r in rel_opts.fields:
+ if r.name == rel_name:
+ e.add(opts, "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
+ if r.name == rel_query_name:
+ e.add(opts, "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
+ for r in rel_opts.many_to_many:
+ if r.name == rel_name:
+ e.add(opts, "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
+ if r.name == rel_query_name:
+ e.add(opts, "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
+ for r in rel_opts.get_all_related_many_to_many_objects():
+ if r.field is not f:
+ if r.get_accessor_name() == rel_name:
+ e.add(opts, "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
+ if r.get_accessor_name() == rel_query_name:
+ e.add(opts, "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
+ for r in rel_opts.get_all_related_objects():
if r.get_accessor_name() == rel_name:
- e.add(opts, "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
+ e.add(opts, "Accessor for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
if r.get_accessor_name() == rel_query_name:
- e.add(opts, "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
- for r in rel_opts.get_all_related_objects():
- if r.get_accessor_name() == rel_name:
- e.add(opts, "Accessor for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
- if r.get_accessor_name() == rel_query_name:
- e.add(opts, "Reverse query name for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
+ e.add(opts, "Reverse query name for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
# Check admin attribute.
if opts.admin is not None:
@@ -1175,7 +1225,8 @@ def get_validation_errors(outfile, app=None):
try:
f = opts.get_field(fn)
except models.FieldDoesNotExist:
- e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
+ if not hasattr(cls, fn):
+ e.add(opts, '"admin.list_display_links" refers to %r, which isn\'t an attribute, method or property.' % fn)
if fn not in opts.admin.list_display:
e.add(opts, '"admin.list_display_links" refers to %r, which is not defined in "admin.list_display".' % fn)
# list_filter
@@ -1233,10 +1284,12 @@ def get_validation_errors(outfile, app=None):
return len(e.errors)
-def validate(outfile=sys.stdout):
+def validate(outfile=sys.stdout, silent_success=False):
"Validates all installed models."
try:
num_errors = get_validation_errors(outfile)
+ if silent_success and num_errors == 0:
+ return
outfile.write('%s error%s found.\n' % (num_errors, num_errors != 1 and 's' or ''))
except ImproperlyConfigured:
outfile.write("Skipping validation because things aren't configured properly.")
@@ -1259,7 +1312,7 @@ def _check_for_validation_errors(app=None):
sys.stderr.write(s.read())
sys.exit(1)
-def runserver(addr, port, use_reloader=True):
+def runserver(addr, port, use_reloader=True, admin_media_dir=''):
"Starts a lightweight Web server for development."
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
from django.core.handlers.wsgi import WSGIHandler
@@ -1277,7 +1330,10 @@ def runserver(addr, port, use_reloader=True):
print "Development server is running at http://%s:%s/" % (addr, port)
print "Quit the server with %s." % quit_command
try:
- run(addr, int(port), AdminMediaHandler(WSGIHandler()))
+ import django
+ path = admin_media_dir or django.__path__[0] + '/contrib/admin/media'
+ handler = AdminMediaHandler(WSGIHandler(), path)
+ run(addr, int(port), handler)
except WSGIServerException, e:
# Use helpful error messages instead of ugly tracebacks.
ERRORS = {
@@ -1298,7 +1354,7 @@ def runserver(addr, port, use_reloader=True):
autoreload.main(inner_run)
else:
inner_run()
-runserver.args = '[--noreload] [optional port number, or ipaddr:port]'
+runserver.args = '[--noreload] [--adminmedia=ADMIN_MEDIA_PATH] [optional port number, or ipaddr:port]'
def createcachetable(tablename):
"Creates the table needed to use the SQL cache backend"
@@ -1380,6 +1436,29 @@ def runfcgi(args):
runfastcgi(args)
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
+def test(app_labels, verbosity=1):
+ "Runs the test suite for the specified applications"
+ from django.conf import settings
+ from django.db.models import get_app, get_apps
+
+ if len(app_labels) == 0:
+ app_list = get_apps()
+ else:
+ app_list = [get_app(app_label) for app_label in app_labels]
+
+ test_path = settings.TEST_RUNNER.split('.')
+ # Allow for Python 2.5 relative paths
+ if len(test_path) > 1:
+ test_module_name = '.'.join(test_path[:-1])
+ else:
+ test_module_name = '.'
+ test_module = __import__(test_module_name, [],[],test_path[-1])
+ test_runner = getattr(test_module, test_path[-1])
+
+ test_runner(app_list, verbosity)
+test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified'
+test.args = '[--verbosity] ' + APP_ARGS
+
# Utilities for command-line script
DEFAULT_ACTION_MAPPING = {
@@ -1405,6 +1484,7 @@ DEFAULT_ACTION_MAPPING = {
'startproject': startproject,
'syncdb': syncdb,
'validate': validate,
+ 'test':test,
}
NO_SQL_TRANSACTION = (
@@ -1455,8 +1535,15 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
parser.add_option('--plain', action='store_true', dest='plain',
help='Tells Django to use plain Python, not IPython, for "shell" command.')
+ parser.add_option('--noinput', action='store_false', dest='interactive', default=True,
+ help='Tells Django to NOT prompt the user for input of any kind.')
parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
help='Tells Django to NOT use the auto-reloader when running the development server.')
+ parser.add_option('--verbosity', action='store', dest='verbosity', default='1',
+ type='choice', choices=['0', '1', '2'],
+ help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
+ parser.add_option('--adminmedia', dest='admin_media_path', default='', help='Specifies the directory from which to serve admin media for runserver.'),
+
options, args = parser.parse_args(argv[1:])
# Take care of options.
@@ -1483,8 +1570,10 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
if action == 'shell':
action_mapping[action](options.plain is True)
- elif action in ('syncdb', 'validate', 'diffsettings', 'dbshell'):
+ elif action in ('validate', 'diffsettings', 'dbshell'):
action_mapping[action]()
+ elif action == 'syncdb':
+ action_mapping[action](int(options.verbosity), options.interactive)
elif action == 'inspectdb':
try:
for line in action_mapping[action]():
@@ -1497,6 +1586,11 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
action_mapping[action](args[1])
except IndexError:
parser.print_usage_and_exit()
+ elif action == 'test':
+ try:
+ action_mapping[action](args[1:], int(options.verbosity))
+ except IndexError:
+ parser.print_usage_and_exit()
elif action in ('startapp', 'startproject'):
try:
name = args[1]
@@ -1512,11 +1606,12 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
addr, port = args[1].split(':')
except ValueError:
addr, port = '', args[1]
- action_mapping[action](addr, port, options.use_reloader)
+ action_mapping[action](addr, port, options.use_reloader, options.admin_media_path)
elif action == 'runfcgi':
action_mapping[action](args[1:])
else:
from django.db import models
+ validate(silent_success=True)
try:
mod_list = [models.get_app(app_label) for app_label in args[1:]]
except ImportError, e:
@@ -1527,7 +1622,10 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
if action not in NO_SQL_TRANSACTION:
print style.SQL_KEYWORD("BEGIN;")
for mod in mod_list:
- output = action_mapping[action](mod)
+ if action == 'reset':
+ output = action_mapping[action](mod, options.interactive)
+ else:
+ output = action_mapping[action](mod)
if output:
print '\n'.join(output)
if action not in NO_SQL_TRANSACTION:
diff --git a/django/core/paginator.py b/django/core/paginator.py
index 195ad1009e..026fe0a675 100644
--- a/django/core/paginator.py
+++ b/django/core/paginator.py
@@ -1,4 +1,3 @@
-from copy import copy
from math import ceil
class InvalidPage(Exception):
diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py
index e939c0c6e7..fb293c7c13 100644
--- a/django/core/serializers/base.py
+++ b/django/core/serializers/base.py
@@ -11,7 +11,7 @@ from django.db import models
class SerializationError(Exception):
"""Something bad happened during serialization."""
pass
-
+
class DeserializationError(Exception):
"""Something bad happened during deserialization."""
pass
@@ -20,15 +20,15 @@ class Serializer(object):
"""
Abstract serializer base class.
"""
-
+
def serialize(self, queryset, **options):
"""
Serialize a queryset.
"""
self.options = options
-
+
self.stream = options.get("stream", StringIO())
-
+
self.start_serialization()
for obj in queryset:
self.start_object(obj)
@@ -44,61 +44,65 @@ class Serializer(object):
self.end_object(obj)
self.end_serialization()
return self.getvalue()
-
+
def get_string_value(self, obj, field):
"""
Convert a field's value to a string.
"""
if isinstance(field, models.DateTimeField):
- value = getattr(obj, field.name).strftime("%Y-%m-%d %H:%M:%S")
+ value = getattr(obj, field.name)
+ if value is None:
+ value = ''
+ else:
+ value = value.strftime("%Y-%m-%d %H:%M:%S")
elif isinstance(field, models.FileField):
value = getattr(obj, "get_%s_url" % field.name, lambda: None)()
else:
value = field.flatten_data(follow=None, obj=obj).get(field.name, "")
return str(value)
-
+
def start_serialization(self):
"""
Called when serializing of the queryset starts.
"""
raise NotImplementedError
-
+
def end_serialization(self):
"""
Called when serializing of the queryset ends.
"""
pass
-
+
def start_object(self, obj):
"""
Called when serializing of an object starts.
"""
raise NotImplementedError
-
+
def end_object(self, obj):
"""
Called when serializing of an object ends.
"""
pass
-
+
def handle_field(self, obj, field):
"""
Called to handle each individual (non-relational) field on an object.
"""
raise NotImplementedError
-
+
def handle_fk_field(self, obj, field):
"""
Called to handle a ForeignKey field.
"""
raise NotImplementedError
-
+
def handle_m2m_field(self, obj, field):
"""
Called to handle a ManyToManyField.
"""
raise NotImplementedError
-
+
def getvalue(self):
"""
Return the fully serialized queryset.
@@ -109,7 +113,7 @@ class Deserializer(object):
"""
Abstract base deserializer class.
"""
-
+
def __init__(self, stream_or_string, **options):
"""
Init this serializer given a stream or a string
@@ -123,39 +127,39 @@ class Deserializer(object):
# deserialization starts (otherwise subclass calls to get_model()
# and friends might fail...)
models.get_apps()
-
+
def __iter__(self):
return self
-
+
def next(self):
"""Iteration iterface -- return the next item in the stream"""
raise NotImplementedError
-
+
class DeserializedObject(object):
"""
A deserialzed model.
-
+
Basically a container for holding the pre-saved deserialized data along
with the many-to-many data saved with the object.
-
+
Call ``save()`` to save the object (with the many-to-many data) to the
database; call ``save(save_m2m=False)`` to save just the object fields
(and not touch the many-to-many stuff.)
"""
-
+
def __init__(self, obj, m2m_data=None):
self.object = obj
self.m2m_data = m2m_data
-
+
def __repr__(self):
return "<DeserializedObject: %s>" % str(self.object)
-
+
def save(self, save_m2m=True):
self.object.save()
if self.m2m_data and save_m2m:
for accessor_name, object_list in self.m2m_data.items():
setattr(self.object, accessor_name, object_list)
-
- # prevent a second (possibly accidental) call to save() from saving
+
+ # prevent a second (possibly accidental) call to save() from saving
# the m2m data twice.
self.m2m_data = None
diff --git a/django/core/serializers/json.py b/django/core/serializers/json.py
index dd6513db57..15770f160e 100644
--- a/django/core/serializers/json.py
+++ b/django/core/serializers/json.py
@@ -16,7 +16,7 @@ class Serializer(PythonSerializer):
Convert a queryset to JSON.
"""
def end_serialization(self):
- simplejson.dump(self.objects, self.stream, cls=DateTimeAwareJSONEncoder)
+ simplejson.dump(self.objects, self.stream, cls=DateTimeAwareJSONEncoder, **self.options)
def getvalue(self):
return self.stream.getvalue()
@@ -41,11 +41,11 @@ class DateTimeAwareJSONEncoder(simplejson.JSONEncoder):
TIME_FORMAT = "%H:%M:%S"
def default(self, o):
- if isinstance(o, datetime.date):
+ if isinstance(o, datetime.datetime):
+ return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
+ elif isinstance(o, datetime.date):
return o.strftime(self.DATE_FORMAT)
elif isinstance(o, datetime.time):
return o.strftime(self.TIME_FORMAT)
- elif isinstance(o, datetime.datetime):
- return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
else:
- return super(self, DateTimeAwareJSONEncoder).default(o) \ No newline at end of file
+ return super(DateTimeAwareJSONEncoder, self).default(o)
diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py
index 7989e1d469..4181bc7f2b 100644
--- a/django/core/serializers/python.py
+++ b/django/core/serializers/python.py
@@ -79,7 +79,7 @@ def Deserializer(object_list, **options):
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
try:
data[field.name] = field.rel.to._default_manager.get(pk=field_value)
- except RelatedModel.DoesNotExist:
+ except field.rel.to.DoesNotExist:
data[field.name] = None
# Handle all other fields
diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py
index 259a931594..a16b8b675a 100644
--- a/django/core/servers/basehttp.py
+++ b/django/core/servers/basehttp.py
@@ -8,7 +8,7 @@ been reviewed for security issues. Don't use it for production use.
"""
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
-from types import ListType, StringType, TupleType
+from types import ListType, StringType
import os, re, sys, time, urllib
__version__ = "0.1"
@@ -547,10 +547,6 @@ class WSGIRequestHandler(BaseHTTPRequestHandler):
env['PATH_INFO'] = urllib.unquote(path)
env['QUERY_STRING'] = query
-
- host = self.address_string()
- if host != self.client_address[0]:
- env['REMOTE_HOST'] = host
env['REMOTE_ADDR'] = self.client_address[0]
if self.headers.typeheader is None:
@@ -598,11 +594,14 @@ class AdminMediaHandler(object):
Use this ONLY LOCALLY, for development! This hasn't been tested for
security and is not super efficient.
"""
- def __init__(self, application):
+ def __init__(self, application, media_dir=None):
from django.conf import settings
- import django
self.application = application
- self.media_dir = django.__path__[0] + '/contrib/admin/media'
+ if not media_dir:
+ import django
+ self.media_dir = django.__path__[0] + '/contrib/admin/media'
+ else:
+ self.media_dir = media_dir
self.media_url = settings.ADMIN_MEDIA_PREFIX
def __call__(self, environ, start_response):
diff --git a/django/core/servers/fastcgi.py b/django/core/servers/fastcgi.py
index dedc1f8ba1..c6507fe173 100644
--- a/django/core/servers/fastcgi.py
+++ b/django/core/servers/fastcgi.py
@@ -74,8 +74,9 @@ def fastcgi_help(message=None):
print message
return False
-def runfastcgi(argset):
+def runfastcgi(argset=[], **kwargs):
options = FASTCGI_OPTIONS.copy()
+ options.update(kwargs)
for x in argset:
if "=" in x:
k, v = x.split('=', 1)
diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
index a1661a2ecd..45705cb223 100644
--- a/django/core/urlresolvers.py
+++ b/django/core/urlresolvers.py
@@ -15,7 +15,8 @@ class Resolver404(Http404):
pass
class NoReverseMatch(Exception):
- pass
+ # Don't make this raise an error when used in a template.
+ silent_variable_failure = True
def get_mod_func(callback):
# Converts 'django.views.news.stories.story_detail' to
@@ -86,10 +87,15 @@ class MatchChecker(object):
class RegexURLPattern(object):
def __init__(self, regex, callback, default_args=None):
# regex is a string representing a regular expression.
- # callback is something like 'foo.views.news.stories.story_detail',
- # which represents the path to a module and a view function name.
+ # callback is either a string like 'foo.views.news.stories.story_detail'
+ # which represents the path to a module and a view function name, or a
+ # callable object (view).
self.regex = re.compile(regex)
- self.callback = callback
+ if callable(callback):
+ self._callback = callback
+ else:
+ self._callback = None
+ self._callback_str = callback
self.default_args = default_args or {}
def resolve(self, path):
@@ -106,23 +112,28 @@ class RegexURLPattern(object):
# In both cases, pass any extra_kwargs as **kwargs.
kwargs.update(self.default_args)
- try: # Lazily load self.func.
- return self.func, args, kwargs
- except AttributeError:
- self.func = self.get_callback()
- return self.func, args, kwargs
+ return self.callback, args, kwargs
- def get_callback(self):
- mod_name, func_name = get_mod_func(self.callback)
+ def _get_callback(self):
+ if self._callback is not None:
+ return self._callback
+ mod_name, func_name = get_mod_func(self._callback_str)
try:
- return getattr(__import__(mod_name, '', '', ['']), func_name)
+ self._callback = getattr(__import__(mod_name, '', '', ['']), func_name)
except ImportError, e:
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
except AttributeError, e:
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
+ return self._callback
+ callback = property(_get_callback)
def reverse(self, viewname, *args, **kwargs):
- if viewname != self.callback:
+ mod_name, func_name = get_mod_func(viewname)
+ try:
+ lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
+ except (ImportError, AttributeError):
+ raise NoReverseMatch
+ if lookup_view != self.callback:
raise NoReverseMatch
return self.reverse_helper(*args, **kwargs)
@@ -130,12 +141,13 @@ class RegexURLPattern(object):
return reverse_helper(self.regex, *args, **kwargs)
class RegexURLResolver(object):
- def __init__(self, regex, urlconf_name):
+ def __init__(self, regex, urlconf_name, default_kwargs=None):
# regex is a string representing a regular expression.
# urlconf_name is a string representing the module containing urlconfs.
self.regex = re.compile(regex)
self.urlconf_name = urlconf_name
self.callback = None
+ self.default_kwargs = default_kwargs or {}
def resolve(self, path):
tried = []
@@ -149,7 +161,8 @@ class RegexURLResolver(object):
tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']])
else:
if sub_match:
- return sub_match[0], sub_match[1], dict(match.groupdict(), **sub_match[2])
+ sub_match_dict = dict(self.default_kwargs, **sub_match[2])
+ return sub_match[0], sub_match[1], dict(match.groupdict(), **sub_match_dict)
tried.append(pattern.regex.pattern)
raise Resolver404, {'tried': tried, 'path': new_path}
@@ -183,21 +196,43 @@ class RegexURLResolver(object):
def resolve500(self):
return self._resolve_special('500')
- def reverse(self, viewname, *args, **kwargs):
+ def reverse(self, lookup_view, *args, **kwargs):
+ if not callable(lookup_view):
+ mod_name, func_name = get_mod_func(lookup_view)
+ try:
+ lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
+ except (ImportError, AttributeError):
+ raise NoReverseMatch
for pattern in self.urlconf_module.urlpatterns:
if isinstance(pattern, RegexURLResolver):
try:
- return pattern.reverse_helper(viewname, *args, **kwargs)
+ return pattern.reverse_helper(lookup_view, *args, **kwargs)
except NoReverseMatch:
continue
- elif pattern.callback == viewname:
+ elif pattern.callback == lookup_view:
try:
return pattern.reverse_helper(*args, **kwargs)
except NoReverseMatch:
continue
raise NoReverseMatch
- def reverse_helper(self, viewname, *args, **kwargs):
- sub_match = self.reverse(viewname, *args, **kwargs)
+ def reverse_helper(self, lookup_view, *args, **kwargs):
+ sub_match = self.reverse(lookup_view, *args, **kwargs)
result = reverse_helper(self.regex, *args, **kwargs)
return result + sub_match
+
+def resolve(path, urlconf=None):
+ if urlconf is None:
+ from django.conf import settings
+ urlconf = settings.ROOT_URLCONF
+ resolver = RegexURLResolver(r'^/', urlconf)
+ return resolver.resolve(path)
+
+def reverse(viewname, urlconf=None, args=None, kwargs=None):
+ args = args or []
+ kwargs = kwargs or {}
+ if urlconf is None:
+ from django.conf import settings
+ urlconf = settings.ROOT_URLCONF
+ resolver = RegexURLResolver(r'^/', urlconf)
+ return '/' + resolver.reverse(viewname, *args, **kwargs)
diff --git a/django/core/validators.py b/django/core/validators.py
index 81bea23e36..4c3f59143e 100644
--- a/django/core/validators.py
+++ b/django/core/validators.py
@@ -13,7 +13,7 @@ from django.utils.translation import gettext, gettext_lazy, ngettext
from django.utils.functional import Promise, lazy
import re
-_datere = r'(19|2\d)\d{2}-((?:0?[1-9])|(?:1[0-2]))-((?:0?[1-9])|(?:[12][0-9])|(?:3[0-1]))'
+_datere = r'\d{4}-\d{1,2}-\d{1,2}'
_timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?'
alnum_re = re.compile(r'^\w+$')
alnumurl_re = re.compile(r'^[-\w/]+$')
@@ -68,7 +68,7 @@ def isAlphaNumericURL(field_data, all_data):
def isSlug(field_data, all_data):
if not slug_re.search(field_data):
- raise ValidationError, "This value must contain only letters, numbers, underscores or hyphens."
+ raise ValidationError, gettext("This value must contain only letters, numbers, underscores or hyphens.")
def isLowerCase(field_data, all_data):
if field_data.lower() != field_data:
@@ -122,9 +122,29 @@ def isOnlyLetters(field_data, all_data):
if not field_data.isalpha():
raise ValidationError, gettext("Only alphabetical characters are allowed here.")
+def _isValidDate(date_string):
+ """
+ A helper function used by isValidANSIDate and isValidANSIDatetime to
+ check if the date is valid. The date string is assumed to already be in
+ YYYY-MM-DD format.
+ """
+ from datetime import date
+ # Could use time.strptime here and catch errors, but datetime.date below
+ # produces much friendlier error messages.
+ year, month, day = map(int, date_string.split('-'))
+ # This check is needed because strftime is used when saving the date
+ # value to the database, and strftime requires that the year be >=1900.
+ if year < 1900:
+ raise ValidationError, gettext('Year must be 1900 or later.')
+ try:
+ date(year, month, day)
+ except ValueError, e:
+ raise ValidationError, gettext('Invalid date: %s.' % e)
+
def isValidANSIDate(field_data, all_data):
if not ansi_date_re.search(field_data):
raise ValidationError, gettext('Enter a valid date in YYYY-MM-DD format.')
+ _isValidDate(field_data)
def isValidANSITime(field_data, all_data):
if not ansi_time_re.search(field_data):
@@ -133,6 +153,7 @@ def isValidANSITime(field_data, all_data):
def isValidANSIDatetime(field_data, all_data):
if not ansi_datetime_re.search(field_data):
raise ValidationError, gettext('Enter a valid date/time in YYYY-MM-DD HH:MM format.')
+ _isValidDate(field_data.split()[0])
def isValidEmail(field_data, all_data):
if not email_re.search(field_data):
@@ -227,9 +248,8 @@ def hasNoProfanities(field_data, all_data):
catch 'motherfucker' as well. Raises a ValidationError such as:
Watch your mouth! The words "f--k" and "s--t" are not allowed here.
"""
- bad_words = ['asshat', 'asshead', 'asshole', 'cunt', 'fuck', 'gook', 'nigger', 'shit'] # all in lower case
field_data = field_data.lower() # normalize
- words_seen = [w for w in bad_words if field_data.find(w) > -1]
+ words_seen = [w for w in settings.PROFANITIES_LIST if w in field_data]
if words_seen:
from django.utils.text import get_text_list
plural = len(words_seen) > 1
@@ -352,10 +372,12 @@ class IsValidFloat(object):
float(data)
except ValueError:
raise ValidationError, gettext("Please enter a valid decimal number.")
- if len(data) > (self.max_digits + 1):
+ # Negative floats require more space to input.
+ max_allowed_length = data.startswith('-') and (self.max_digits + 2) or (self.max_digits + 1)
+ if len(data) > max_allowed_length:
raise ValidationError, ngettext("Please enter a valid decimal number with at most %s total digit.",
"Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
- if (not '.' in data and len(data) > (self.max_digits - self.decimal_places)) or ('.' in data and len(data) > (self.max_digits - (self.decimal_places - len(data.split('.')[1])) + 1)):
+ if (not '.' in data and len(data) > (max_allowed_length - self.decimal_places - 1)) or ('.' in data and len(data) > (max_allowed_length - (self.decimal_places - len(data.split('.')[1])))):
raise ValidationError, ngettext( "Please enter a valid decimal number with a whole part of at most %s digit.",
"Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places)
if '.' in data and len(data.split('.')[1]) > self.decimal_places:
diff --git a/django/core/xheaders.py b/django/core/xheaders.py
index e173bcbca8..69f6115839 100644
--- a/django/core/xheaders.py
+++ b/django/core/xheaders.py
@@ -13,9 +13,10 @@ def populate_xheaders(request, response, model, object_id):
"""
Adds the "X-Object-Type" and "X-Object-Id" headers to the given
HttpResponse according to the given model and object_id -- but only if the
- given HttpRequest object has an IP address within the INTERNAL_IPS setting.
+ given HttpRequest object has an IP address within the INTERNAL_IPS setting
+ or if the request is from a logged in staff member.
"""
from django.conf import settings
- if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
+ if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or (request.user.is_authenticated() and request.user.is_staff):
response['X-Object-Type'] = "%s.%s" % (model._meta.app_label, model._meta.object_name.lower())
response['X-Object-Id'] = str(object_id)
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index 50b76cc3a0..924c032b4c 100644
--- a/django/db/backends/mysql/base.py
+++ b/django/db/backends/mysql/base.py
@@ -13,6 +13,7 @@ except ImportError, e:
from MySQLdb.converters import conversions
from MySQLdb.constants import FIELD_TYPE
import types
+import re
DatabaseError = Database.DatabaseError
@@ -24,6 +25,12 @@ django_conversions.update({
FIELD_TYPE.TIME: util.typecast_time,
})
+# This should match the numerical portion of the version numbers (we can treat
+# versions like 5.0.24 and 5.0.24a as the same). Based on the list of version
+# at http://dev.mysql.com/doc/refman/4.1/en/news.html and
+# http://dev.mysql.com/doc/refman/5.0/en/news.html .
+server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
+
# This is an extra debug layer over MySQL queries, to display warnings.
# It's only used when DEBUG=True.
class MysqlDebugWrapper:
@@ -61,6 +68,7 @@ class DatabaseWrapper(local):
def __init__(self):
self.connection = None
self.queries = []
+ self.server_version = None
def _valid_connection(self):
if self.connection is not None:
@@ -110,6 +118,16 @@ class DatabaseWrapper(local):
self.connection.close()
self.connection = None
+ def get_server_version(self):
+ if not self.server_version:
+ if not self._valid_connection():
+ self.cursor()
+ m = server_version_re.match(self.connection.get_server_info())
+ if not m:
+ raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())
+ self.server_version = tuple([int(x) for x in m.groups()])
+ return self.server_version
+
supports_constraints = True
def quote_name(name):
diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py
index 202fced1dc..7caf5fa060 100644
--- a/django/db/backends/mysql/introspection.py
+++ b/django/db/backends/mysql/introspection.py
@@ -36,13 +36,14 @@ def get_relations(cursor, table_name):
SELECT column_name, referenced_table_name, referenced_column_name
FROM information_schema.key_column_usage
WHERE table_name = %s
+ AND table_schema = DATABASE()
AND referenced_table_name IS NOT NULL
AND referenced_column_name IS NOT NULL""", [table_name])
constraints.extend(cursor.fetchall())
except (ProgrammingError, OperationalError):
# Fall back to "SHOW CREATE TABLE", for previous MySQL versions.
# Go through all constraints and save the equal matches.
- cursor.execute("SHOW CREATE TABLE %s" % table_name)
+ cursor.execute("SHOW CREATE TABLE %s" % quote_name(table_name))
for row in cursor.fetchall():
pos = 0
while True:
diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py
index 188c4bb678..dfe2df11dc 100644
--- a/django/db/backends/oracle/base.py
+++ b/django/db/backends/oracle/base.py
@@ -10,7 +10,6 @@ try:
except ImportError, e:
from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured, "Error loading cx_Oracle module: %s" % e
-import types
DatabaseError = Database.Error
diff --git a/django/db/backends/oracle/introspection.py b/django/db/backends/oracle/introspection.py
index 656741e440..ecc8f372a8 100644
--- a/django/db/backends/oracle/introspection.py
+++ b/django/db/backends/oracle/introspection.py
@@ -1,5 +1,3 @@
-from django.db import transaction
-from django.db.backends.oracle.base import quote_name
import re
foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py
index 55cba81b70..4c835d89fc 100644
--- a/django/db/backends/postgresql_psycopg2/base.py
+++ b/django/db/backends/postgresql_psycopg2/base.py
@@ -43,6 +43,7 @@ class DatabaseWrapper(local):
self.connection = Database.connect(conn_string)
self.connection.set_isolation_level(1) # make transactions transparent to all cursors
cursor = self.connection.cursor()
+ cursor.tzinfo_factory = None
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
if settings.DEBUG:
return util.CursorDebugWrapper(cursor, self)
@@ -67,23 +68,9 @@ def quote_name(name):
return name # Quoting once is enough.
return '"%s"' % name
-def dictfetchone(cursor):
- "Returns a row from the cursor as a dict"
- # TODO: cursor.dictfetchone() doesn't exist in psycopg2,
- # but no Django code uses this. Safe to remove?
- return cursor.dictfetchone()
-
-def dictfetchmany(cursor, number):
- "Returns a certain number of rows from a cursor as a dict"
- # TODO: cursor.dictfetchmany() doesn't exist in psycopg2,
- # but no Django code uses this. Safe to remove?
- return cursor.dictfetchmany(number)
-
-def dictfetchall(cursor):
- "Returns all rows from a cursor as a dict"
- # TODO: cursor.dictfetchall() doesn't exist in psycopg2,
- # but no Django code uses this. Safe to remove?
- return cursor.dictfetchall()
+dictfetchone = util.dictfetchone
+dictfetchmany = util.dictfetchmany
+dictfetchall = util.dictfetchall
def get_last_insert_id(cursor, table_name, pk_name):
cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (table_name, pk_name))
diff --git a/django/db/backends/postgresql_psycopg2/introspection.py b/django/db/backends/postgresql_psycopg2/introspection.py
index b991493d39..a546da8c45 100644
--- a/django/db/backends/postgresql_psycopg2/introspection.py
+++ b/django/db/backends/postgresql_psycopg2/introspection.py
@@ -1,4 +1,3 @@
-from django.db import transaction
from django.db.backends.postgresql_psycopg2.base import quote_name
def get_table_list(cursor):
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
index 5c884ff121..01e4b3aebf 100644
--- a/django/db/backends/sqlite3/base.py
+++ b/django/db/backends/sqlite3/base.py
@@ -4,10 +4,18 @@ SQLite3 backend for django. Requires pysqlite2 (http://pysqlite.org/).
from django.db.backends import util
try:
- from pysqlite2 import dbapi2 as Database
+ try:
+ from sqlite3 import dbapi2 as Database
+ except ImportError:
+ from pysqlite2 import dbapi2 as Database
except ImportError, e:
+ import sys
from django.core.exceptions import ImproperlyConfigured
- raise ImproperlyConfigured, "Error loading pysqlite2 module: %s" % e
+ if sys.version_info < (2, 5, 0):
+ module = 'pysqlite2'
+ else:
+ module = 'sqlite3'
+ raise ImproperlyConfigured, "Error loading %s module: %s" % (module, e)
DatabaseError = Database.DatabaseError
@@ -62,7 +70,10 @@ class DatabaseWrapper(local):
self.connection.rollback()
def close(self):
- if self.connection is not None:
+ from django.conf import settings
+ # If database is in memory, closing the connection destroys the database.
+ # To prevent accidental data loss, ignore close requests on an in-memory db.
+ if self.connection is not None and settings.DATABASE_NAME != ":memory:":
self.connection.close()
self.connection = None
diff --git a/django/db/backends/util.py b/django/db/backends/util.py
index 74d33f42ca..3ec1b41485 100644
--- a/django/db/backends/util.py
+++ b/django/db/backends/util.py
@@ -98,7 +98,7 @@ def rev_typecast_boolean(obj, d):
def _dict_helper(desc, row):
"Returns a dictionary for the given cursor.description and result row."
- return dict([(desc[col[0]][0], col[1]) for col in enumerate(row)])
+ return dict(zip([col[0] for col in desc], row))
def dictfetchone(cursor):
"Returns a row from the cursor as a dict"
@@ -110,9 +110,11 @@ def dictfetchone(cursor):
def dictfetchmany(cursor, number):
"Returns a certain number of rows from a cursor as a dict"
desc = cursor.description
- return [_dict_helper(desc, row) for row in cursor.fetchmany(number)]
+ for row in cursor.fetchmany(number):
+ yield _dict_helper(desc, row)
def dictfetchall(cursor):
"Returns all rows from a cursor as a dict"
desc = cursor.description
- return [_dict_helper(desc, row) for row in cursor.fetchall()]
+ for row in cursor.fetchall():
+ yield _dict_helper(desc, row)
diff --git a/django/db/models/__init__.py b/django/db/models/__init__.py
index 82b1238723..0308dd047a 100644
--- a/django/db/models/__init__.py
+++ b/django/db/models/__init__.py
@@ -16,6 +16,18 @@ from django.utils.text import capfirst
# Admin stages.
ADD, CHANGE, BOTH = 1, 2, 3
+# Decorator. Takes a function that returns a tuple in this format:
+# (viewname, viewargs, viewkwargs)
+# Returns a function that calls urlresolvers.reverse() on that data, to return
+# the URL for those parameters.
+def permalink(func):
+ from django.core.urlresolvers import reverse
+ def inner(*args, **kwargs):
+ bits = func(*args, **kwargs)
+ viewname = bits[0]
+ return reverse(bits[0], None, *bits[1:3])
+ return inner
+
class LazyDate(object):
"""
Use in limit_choices_to to compare the field to dates calculated at run time
@@ -35,7 +47,7 @@ class LazyDate(object):
return "<LazyDate: %s>" % self.delta
def __get_value__(self):
- return datetime.datetime.now() + self.delta
+ return (datetime.datetime.now() + self.delta).date()
def __getattr__(self, attr):
return getattr(self.__get_value__(), attr)
diff --git a/django/db/models/base.py b/django/db/models/base.py
index c89033c491..bdae7eccc2 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -4,8 +4,7 @@ from django.core import validators
from django.core.exceptions import ObjectDoesNotExist
from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist
from django.db.models.fields.related import OneToOneRel, ManyToOneRel
-from django.db.models.related import RelatedObject
-from django.db.models.query import orderlist2sql, delete_objects
+from django.db.models.query import delete_objects
from django.db.models.options import Options, AdminOptions
from django.db import connection, backend, transaction
from django.db.models import signals
@@ -45,7 +44,7 @@ class ModelBase(type):
new_class._meta.app_label = model_module.__name__.split('.')[-2]
# Bail out early if we have already created this class.
- m = get_model(new_class._meta.app_label, name)
+ m = get_model(new_class._meta.app_label, name, False)
if m is not None:
return m
@@ -69,7 +68,7 @@ class ModelBase(type):
# the first class for this model to register with the framework. There
# should only be one class for each model, so we must always return the
# registered version.
- return get_model(new_class._meta.app_label, name)
+ return get_model(new_class._meta.app_label, name, False)
class Model(object):
__metaclass__ = ModelBase
@@ -177,11 +176,12 @@ class Model(object):
# If it does already exist, do an UPDATE.
if cursor.fetchone():
db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks]
- cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
- (backend.quote_name(self._meta.db_table),
- ','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
- backend.quote_name(self._meta.pk.column)),
- db_values + [pk_val])
+ if db_values:
+ cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
+ (backend.quote_name(self._meta.db_table),
+ ','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
+ backend.quote_name(self._meta.pk.column)),
+ db_values + [pk_val])
else:
record_exists = False
if not pk_set or not record_exists:
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 98661fe36c..02b5ba8b9e 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -5,6 +5,7 @@ from django.core import validators
from django import forms
from django.core.exceptions import ObjectDoesNotExist
from django.utils.functional import curry
+from django.utils.itercompat import tee
from django.utils.text import capfirst
from django.utils.translation import gettext, gettext_lazy
import datetime, os, time
@@ -80,7 +81,7 @@ class Field(object):
self.prepopulate_from = prepopulate_from
self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month
self.unique_for_year = unique_for_year
- self.choices = choices or []
+ self._choices = choices or []
self.radio_admin = radio_admin
self.help_text = help_text
self.db_column = db_column
@@ -325,6 +326,14 @@ class Field(object):
def bind(self, fieldmapping, original, bound_field_class):
return bound_field_class(self, fieldmapping, original)
+ def _get_choices(self):
+ if hasattr(self._choices, 'next'):
+ choices, self._choices = tee(self._choices)
+ return choices
+ else:
+ return self._choices
+ choices = property(_get_choices)
+
class AutoField(Field):
empty_strings_allowed = False
def __init__(self, *args, **kwargs):
@@ -368,8 +377,8 @@ class BooleanField(Field):
def to_python(self, value):
if value in (True, False): return value
- if value in ('t', 'True'): return True
- if value in ('f', 'False'): return False
+ if value in ('t', 'True', '1'): return True
+ if value in ('f', 'False', '0'): return False
raise validators.ValidationError, gettext("This value must be either True or False.")
def get_manipulator_field_objs(self):
diff --git a/django/db/models/fields/generic.py b/django/db/models/fields/generic.py
index 5f4de40e69..7d7651029c 100644
--- a/django/db/models/fields/generic.py
+++ b/django/db/models/fields/generic.py
@@ -117,7 +117,7 @@ class GenericRelation(RelatedField, Field):
return self.object_id_field_name
def m2m_reverse_name(self):
- return self.model._meta.pk.attname
+ return self.object_id_field_name
def contribute_to_class(self, cls, name):
super(GenericRelation, self).contribute_to_class(cls, name)
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 9a8a61878e..bd9262d55a 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -1,8 +1,8 @@
-from django.db import backend, connection, transaction
+from django.db import backend, transaction
from django.db.models import signals, get_model
from django.db.models.fields import AutoField, Field, IntegerField, get_ul_class
from django.db.models.related import RelatedObject
-from django.utils.translation import gettext_lazy, string_concat
+from django.utils.translation import gettext_lazy, string_concat, ngettext
from django.utils.functional import curry
from django.core import validators
from django import forms
@@ -23,9 +23,9 @@ def add_lookup(rel_cls, field):
name = field.rel.to
module = rel_cls.__module__
key = (module, name)
- # Has the model already been loaded?
+ # Has the model already been loaded?
# If so, resolve the string reference right away
- model = get_model(rel_cls._meta.app_label,field.rel.to)
+ model = get_model(rel_cls._meta.app_label, field.rel.to, False)
if model:
field.rel.to = model
field.do_related_class(model, rel_cls)
@@ -46,7 +46,7 @@ def manipulator_valid_rel_key(f, self, field_data, all_data):
"Validates that the value is a valid foreign key"
klass = f.rel.to
try:
- klass._default_manager.get(pk=field_data)
+ klass._default_manager.get(**{f.rel.field_name: field_data})
except klass.DoesNotExist:
raise validators.ValidationError, _("Please enter a valid %s.") % f.verbose_name
@@ -79,11 +79,11 @@ class RelatedField(object):
self.contribute_to_related_class(other, related)
def get_db_prep_lookup(self, lookup_type, value):
- # If we are doing a lookup on a Related Field, we must be
- # comparing object instances. The value should be the PK of value,
+ # If we are doing a lookup on a Related Field, we must be
+ # comparing object instances. The value should be the PK of value,
# not value itself.
def pk_trace(value):
- # Value may be a primary key, or an object held in a relation.
+ # Value may be a primary key, or an object held in a relation.
# If it is an object, then we need to get the primary key value for
# that object. In certain conditions (especially one-to-one relations),
# the primary key may itself be an object - so we need to keep drilling
@@ -94,8 +94,8 @@ class RelatedField(object):
v = getattr(v, v._meta.pk.name)
except AttributeError:
pass
- return v
-
+ return v
+
if lookup_type == 'exact':
return [pk_trace(value)]
if lookup_type == 'in':
@@ -103,7 +103,7 @@ class RelatedField(object):
elif lookup_type == 'isnull':
return []
raise TypeError, "Related Field has invalid lookup: %s" % lookup_type
-
+
def _get_related_query_name(self, opts):
# This method defines the name that can be used to identify this related object
# in a table-spanning query. It uses the lower-cased object_name by default,
@@ -618,7 +618,7 @@ class ManyToManyField(RelatedField, Field):
msg = gettext_lazy('Separate multiple IDs with commas.')
else:
msg = gettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.')
- self.help_text = string_concat(self.help_text, msg)
+ self.help_text = string_concat(self.help_text, ' ', msg)
def get_manipulator_field_objs(self):
if self.rel.raw_id_admin:
diff --git a/django/db/models/loading.py b/django/db/models/loading.py
index c7920fa4e0..22f83bfd78 100644
--- a/django/db/models/loading.py
+++ b/django/db/models/loading.py
@@ -32,7 +32,7 @@ def get_apps():
_app_errors[app_name] = e
return _app_list
-def get_app(app_label, emptyOK = False):
+def get_app(app_label, emptyOK=False):
"Returns the module containing the models for the given app_label. If the app has no models in it and 'emptyOK' is True, returns None."
get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish.
for app_name in settings.INSTALLED_APPS:
@@ -75,11 +75,15 @@ def get_models(app_mod=None):
model_list.extend(get_models(app_mod))
return model_list
-def get_model(app_label, model_name):
+def get_model(app_label, model_name, seed_cache=True):
"""
- Returns the model matching the given app_label and case-insensitive model_name.
+ Returns the model matching the given app_label and case-insensitive
+ model_name.
+
Returns None if no model is found.
"""
+ if seed_cache:
+ get_apps()
try:
model_dict = _app_models[app_label]
except KeyError:
diff --git a/django/db/models/manager.py b/django/db/models/manager.py
index 46a1710c1c..6005874516 100644
--- a/django/db/models/manager.py
+++ b/django/db/models/manager.py
@@ -1,10 +1,7 @@
-from django.utils.functional import curry
-from django.db import backend, connection
from django.db.models.query import QuerySet
from django.dispatch import dispatcher
from django.db.models import signals
from django.db.models.fields import FieldDoesNotExist
-from django.utils.datastructures import SortedDict
# Size of each "chunk" for get_iterator calls.
# Larger values are slightly faster at the expense of more storage space.
diff --git a/django/db/models/manipulators.py b/django/db/models/manipulators.py
index 454c318e5d..83ddda844e 100644
--- a/django/db/models/manipulators.py
+++ b/django/db/models/manipulators.py
@@ -5,7 +5,7 @@ from django.db.models.fields import FileField, AutoField
from django.dispatch import dispatcher
from django.db.models import signals
from django.utils.functional import curry
-from django.utils.datastructures import DotExpandedDict, MultiValueDict
+from django.utils.datastructures import DotExpandedDict
from django.utils.text import capfirst
import types
@@ -76,7 +76,7 @@ class AutomaticManipulator(forms.Manipulator):
# Add field for ordering.
if self.change and self.opts.get_ordered_objects():
- self.fields.append(formfields.CommaSeparatedIntegerField(field_name="order_"))
+ self.fields.append(forms.CommaSeparatedIntegerField(field_name="order_"))
def save(self, new_data):
# TODO: big cleanup when core fields go -> use recursive manipulators.
@@ -138,7 +138,7 @@ class AutomaticManipulator(forms.Manipulator):
child_follow = self.follow.get(related.name, None)
if child_follow:
- obj_list = expanded_data[related.var_name].items()
+ obj_list = expanded_data.get(related.var_name, {}).items()
if not obj_list:
continue
@@ -177,7 +177,7 @@ class AutomaticManipulator(forms.Manipulator):
# case, because they'll be dealt with later.
if f == related.field:
- param = getattr(new_object, related.field.rel.field_name)
+ param = getattr(new_object, related.field.rel.get_related_field().attname)
elif (not self.change) and isinstance(f, AutoField):
param = None
elif self.change and (isinstance(f, FileField) or not child_follow.get(f.name, None)):
@@ -215,8 +215,11 @@ class AutomaticManipulator(forms.Manipulator):
# Save many-to-many objects.
for f in related.opts.many_to_many:
if child_follow.get(f.name, None) and not f.rel.edit_inline:
- was_changed = getattr(new_rel_obj, 'set_%s' % f.name)(rel_new_data[f.attname])
- if self.change and was_changed:
+ new_value = rel_new_data[f.attname]
+ if f.rel.raw_id_admin:
+ new_value = new_value[0]
+ setattr(new_rel_obj, f.name, f.rel.to.objects.filter(pk__in=new_value))
+ if self.change:
self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
# If, in the change stage, all of the core fields were blank and
@@ -300,7 +303,7 @@ def manipulator_validator_unique_together(field_name_list, opts, self, field_dat
pass
else:
raise validators.ValidationError, _("%(object)s with this %(type)s already exists for the given %(field)s.") % \
- {'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list(field_name_list[1:], 'and')}
+ {'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list([f.verbose_name for f in field_list[1:]], 'and')}
def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_type, self, field_data, all_data):
from django.db.models.fields.related import ManyToOneRel
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 2b4a13354b..53ed63ae5b 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -18,7 +18,7 @@ QUERY_TERMS = (
'exact', 'iexact', 'contains', 'icontains',
'gt', 'gte', 'lt', 'lte', 'in',
'startswith', 'istartswith', 'endswith', 'iendswith',
- 'range', 'year', 'month', 'day', 'isnull',
+ 'range', 'year', 'month', 'day', 'isnull', 'search',
)
# Size of each "chunk" for get_iterator calls.
@@ -707,34 +707,35 @@ def parse_lookup(kwarg_items, opts):
joins, where, params = SortedDict(), [], []
for kwarg, value in kwarg_items:
- if value is not None:
- path = kwarg.split(LOOKUP_SEPARATOR)
- # Extract the last elements of the kwarg.
- # The very-last is the lookup_type (equals, like, etc).
- # The second-last is the table column on which the lookup_type is
- # to be performed.
- # The exceptions to this are:
- # 1) "pk", which is an implicit id__exact;
- # if we find "pk", make the lookup_type "exact', and insert
- # a dummy name of None, which we will replace when
- # we know which table column to grab as the primary key.
- # 2) If there is only one part, or the last part is not a query
- # term, assume that the query is an __exact
- lookup_type = path.pop()
- if lookup_type == 'pk':
- lookup_type = 'exact'
- path.append(None)
- elif len(path) == 0 or lookup_type not in QUERY_TERMS:
- path.append(lookup_type)
- lookup_type = 'exact'
+ path = kwarg.split(LOOKUP_SEPARATOR)
+ # Extract the last elements of the kwarg.
+ # The very-last is the lookup_type (equals, like, etc).
+ # The second-last is the table column on which the lookup_type is
+ # to be performed. If this name is 'pk', it will be substituted with
+ # the name of the primary key.
+ # If there is only one part, or the last part is not a query
+ # term, assume that the query is an __exact
+ lookup_type = path.pop()
+ if lookup_type == 'pk':
+ lookup_type = 'exact'
+ path.append(None)
+ elif len(path) == 0 or lookup_type not in QUERY_TERMS:
+ path.append(lookup_type)
+ lookup_type = 'exact'
- if len(path) < 1:
- raise TypeError, "Cannot parse keyword query %r" % kwarg
+ if len(path) < 1:
+ raise TypeError, "Cannot parse keyword query %r" % kwarg
+
+ if value is None:
+ # Interpret '__exact=None' as the sql '= NULL'; otherwise, reject
+ # all uses of None as a query value.
+ if lookup_type != 'exact':
+ raise ValueError, "Cannot use None as a query value"
- joins2, where2, params2 = lookup_inner(path, lookup_type, value, opts, opts.db_table, None)
- joins.update(joins2)
- where.extend(where2)
- params.extend(params2)
+ joins2, where2, params2 = lookup_inner(path, lookup_type, value, opts, opts.db_table, None)
+ joins.update(joins2)
+ where.extend(where2)
+ params.extend(params2)
return joins, where, params
class FieldFound(Exception):
@@ -766,7 +767,7 @@ def lookup_inner(path, lookup_type, value, opts, table, column):
name = path.pop(0)
# Has the primary key been requested? If so, expand it out
# to be the name of the current class' primary key
- if name is None:
+ if name is None or name == 'pk':
name = current_opts.pk.name
# Try to find the name in the fields associated with the current class
diff --git a/django/db/models/related.py b/django/db/models/related.py
index ee3b916cf4..ac1ec50ca2 100644
--- a/django/db/models/related.py
+++ b/django/db/models/related.py
@@ -131,6 +131,9 @@ class RelatedObject(object):
# many-to-many objects. It uses the lower-cased object_name + "_set",
# but this can be overridden with the "related_name" option.
if self.field.rel.multiple:
+ # If this is a symmetrical m2m relation on self, there is no reverse accessor.
+ if getattr(self.field.rel, 'symmetrical', False) and self.model == self.parent_model:
+ return None
return self.field.rel.related_name or (self.opts.object_name.lower() + '_set')
else:
return self.field.rel.related_name or (self.opts.object_name.lower())
diff --git a/django/dispatch/dispatcher.py b/django/dispatch/dispatcher.py
index d93f696685..1a617b5946 100644
--- a/django/dispatch/dispatcher.py
+++ b/django/dispatch/dispatcher.py
@@ -6,24 +6,24 @@ system.
Module attributes of note:
- Any -- Singleton used to signal either "Any Sender" or
- "Any Signal". See documentation of the _Any class.
- Anonymous -- Singleton used to signal "Anonymous Sender"
- See documentation of the _Anonymous class.
+ Any -- Singleton used to signal either "Any Sender" or
+ "Any Signal". See documentation of the _Any class.
+ Anonymous -- Singleton used to signal "Anonymous Sender"
+ See documentation of the _Anonymous class.
Internal attributes:
- WEAKREF_TYPES -- tuple of types/classes which represent
- weak references to receivers, and thus must be de-
- referenced on retrieval to retrieve the callable
- object
- connections -- { senderkey (id) : { signal : [receivers...]}}
- senders -- { senderkey (id) : weakref(sender) }
- used for cleaning up sender references on sender
- deletion
- sendersBack -- { receiverkey (id) : [senderkey (id)...] }
- used for cleaning up receiver references on receiver
- deletion, (considerably speeds up the cleanup process
- vs. the original code.)
+ WEAKREF_TYPES -- tuple of types/classes which represent
+ weak references to receivers, and thus must be de-
+ referenced on retrieval to retrieve the callable
+ object
+ connections -- { senderkey (id) : { signal : [receivers...]}}
+ senders -- { senderkey (id) : weakref(sender) }
+ used for cleaning up sender references on sender
+ deletion
+ sendersBack -- { receiverkey (id) : [senderkey (id)...] }
+ used for cleaning up receiver references on receiver
+ deletion, (considerably speeds up the cleanup process
+ vs. the original code.)
"""
from __future__ import generators
import types, weakref
@@ -34,44 +34,44 @@ __cvsid__ = "$Id: dispatcher.py,v 1.9 2005/09/17 04:55:57 mcfletch Exp $"
__version__ = "$Revision: 1.9 $"[11:-2]
try:
- True
+ True
except NameError:
- True = 1==1
- False = 1==0
+ True = 1==1
+ False = 1==0
class _Parameter:
- """Used to represent default parameter values."""
- def __repr__(self):
- return self.__class__.__name__
+ """Used to represent default parameter values."""
+ def __repr__(self):
+ return self.__class__.__name__
class _Any(_Parameter):
- """Singleton used to signal either "Any Sender" or "Any Signal"
+ """Singleton used to signal either "Any Sender" or "Any Signal"
- The Any object can be used with connect, disconnect,
- send, or sendExact to signal that the parameter given
- Any should react to all senders/signals, not just
- a particular sender/signal.
- """
+ The Any object can be used with connect, disconnect,
+ send, or sendExact to signal that the parameter given
+ Any should react to all senders/signals, not just
+ a particular sender/signal.
+ """
Any = _Any()
class _Anonymous(_Parameter):
- """Singleton used to signal "Anonymous Sender"
+ """Singleton used to signal "Anonymous Sender"
- The Anonymous object is used to signal that the sender
- of a message is not specified (as distinct from being
- "any sender"). Registering callbacks for Anonymous
- will only receive messages sent without senders. Sending
- with anonymous will only send messages to those receivers
- registered for Any or Anonymous.
+ The Anonymous object is used to signal that the sender
+ of a message is not specified (as distinct from being
+ "any sender"). Registering callbacks for Anonymous
+ will only receive messages sent without senders. Sending
+ with anonymous will only send messages to those receivers
+ registered for Any or Anonymous.
- Note:
- The default sender for connect is Any, while the
- default sender for send is Anonymous. This has
- the effect that if you do not specify any senders
- in either function then all messages are routed
- as though there was a single sender (Anonymous)
- being used everywhere.
- """
+ Note:
+ The default sender for connect is Any, while the
+ default sender for send is Anonymous. This has
+ the effect that if you do not specify any senders
+ in either function then all messages are routed
+ as though there was a single sender (Anonymous)
+ being used everywhere.
+ """
Anonymous = _Anonymous()
WEAKREF_TYPES = (weakref.ReferenceType, saferef.BoundMethodWeakref)
@@ -82,416 +82,416 @@ sendersBack = {}
def connect(receiver, signal=Any, sender=Any, weak=True):
- """Connect receiver to sender for signal
+ """Connect receiver to sender for signal
- receiver -- a callable Python object which is to receive
- messages/signals/events. Receivers must be hashable
- objects.
+ receiver -- a callable Python object which is to receive
+ messages/signals/events. Receivers must be hashable
+ objects.
- if weak is True, then receiver must be weak-referencable
- (more precisely saferef.safeRef() must be able to create
- a reference to the receiver).
-
- Receivers are fairly flexible in their specification,
- as the machinery in the robustApply module takes care
- of most of the details regarding figuring out appropriate
- subsets of the sent arguments to apply to a given
- receiver.
+ if weak is True, then receiver must be weak-referencable
+ (more precisely saferef.safeRef() must be able to create
+ a reference to the receiver).
+
+ Receivers are fairly flexible in their specification,
+ as the machinery in the robustApply module takes care
+ of most of the details regarding figuring out appropriate
+ subsets of the sent arguments to apply to a given
+ receiver.
- Note:
- if receiver is itself a weak reference (a callable),
- it will be de-referenced by the system's machinery,
- so *generally* weak references are not suitable as
- receivers, though some use might be found for the
- facility whereby a higher-level library passes in
- pre-weakrefed receiver references.
+ Note:
+ if receiver is itself a weak reference (a callable),
+ it will be de-referenced by the system's machinery,
+ so *generally* weak references are not suitable as
+ receivers, though some use might be found for the
+ facility whereby a higher-level library passes in
+ pre-weakrefed receiver references.
- signal -- the signal to which the receiver should respond
-
- if Any, receiver will receive any signal from the
- indicated sender (which might also be Any, but is not
- necessarily Any).
-
- Otherwise must be a hashable Python object other than
- None (DispatcherError raised on None).
-
- sender -- the sender to which the receiver should respond
-
- if Any, receiver will receive the indicated signals
- from any sender.
-
- if Anonymous, receiver will only receive indicated
- signals from send/sendExact which do not specify a
- sender, or specify Anonymous explicitly as the sender.
+ signal -- the signal to which the receiver should respond
+
+ if Any, receiver will receive any signal from the
+ indicated sender (which might also be Any, but is not
+ necessarily Any).
+
+ Otherwise must be a hashable Python object other than
+ None (DispatcherError raised on None).
+
+ sender -- the sender to which the receiver should respond
+
+ if Any, receiver will receive the indicated signals
+ from any sender.
+
+ if Anonymous, receiver will only receive indicated
+ signals from send/sendExact which do not specify a
+ sender, or specify Anonymous explicitly as the sender.
- Otherwise can be any python object.
-
- weak -- whether to use weak references to the receiver
- By default, the module will attempt to use weak
- references to the receiver objects. If this parameter
- is false, then strong references will be used.
+ Otherwise can be any python object.
+
+ weak -- whether to use weak references to the receiver
+ By default, the module will attempt to use weak
+ references to the receiver objects. If this parameter
+ is false, then strong references will be used.
- returns None, may raise DispatcherTypeError
- """
- if signal is None:
- raise errors.DispatcherTypeError(
- 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
- )
- if weak:
- receiver = saferef.safeRef(receiver, onDelete=_removeReceiver)
- senderkey = id(sender)
- if connections.has_key(senderkey):
- signals = connections[senderkey]
- else:
- connections[senderkey] = signals = {}
- # Keep track of senders for cleanup.
- # Is Anonymous something we want to clean up?
- if sender not in (None, Anonymous, Any):
- def remove(object, senderkey=senderkey):
- _removeSender(senderkey=senderkey)
- # Skip objects that can not be weakly referenced, which means
- # they won't be automatically cleaned up, but that's too bad.
- try:
- weakSender = weakref.ref(sender, remove)
- senders[senderkey] = weakSender
- except:
- pass
-
- receiverID = id(receiver)
- # get current set, remove any current references to
- # this receiver in the set, including back-references
- if signals.has_key(signal):
- receivers = signals[signal]
- _removeOldBackRefs(senderkey, signal, receiver, receivers)
- else:
- receivers = signals[signal] = []
- try:
- current = sendersBack.get( receiverID )
- if current is None:
- sendersBack[ receiverID ] = current = []
- if senderkey not in current:
- current.append(senderkey)
- except:
- pass
+ returns None, may raise DispatcherTypeError
+ """
+ if signal is None:
+ raise errors.DispatcherTypeError(
+ 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
+ )
+ if weak:
+ receiver = saferef.safeRef(receiver, onDelete=_removeReceiver)
+ senderkey = id(sender)
+ if connections.has_key(senderkey):
+ signals = connections[senderkey]
+ else:
+ connections[senderkey] = signals = {}
+ # Keep track of senders for cleanup.
+ # Is Anonymous something we want to clean up?
+ if sender not in (None, Anonymous, Any):
+ def remove(object, senderkey=senderkey):
+ _removeSender(senderkey=senderkey)
+ # Skip objects that can not be weakly referenced, which means
+ # they won't be automatically cleaned up, but that's too bad.
+ try:
+ weakSender = weakref.ref(sender, remove)
+ senders[senderkey] = weakSender
+ except:
+ pass
+
+ receiverID = id(receiver)
+ # get current set, remove any current references to
+ # this receiver in the set, including back-references
+ if signals.has_key(signal):
+ receivers = signals[signal]
+ _removeOldBackRefs(senderkey, signal, receiver, receivers)
+ else:
+ receivers = signals[signal] = []
+ try:
+ current = sendersBack.get( receiverID )
+ if current is None:
+ sendersBack[ receiverID ] = current = []
+ if senderkey not in current:
+ current.append(senderkey)
+ except:
+ pass
- receivers.append(receiver)
+ receivers.append(receiver)
def disconnect(receiver, signal=Any, sender=Any, weak=True):
- """Disconnect receiver from sender for signal
+ """Disconnect receiver from sender for signal
- receiver -- the registered receiver to disconnect
- signal -- the registered signal to disconnect
- sender -- the registered sender to disconnect
- weak -- the weakref state to disconnect
+ receiver -- the registered receiver to disconnect
+ signal -- the registered signal to disconnect
+ sender -- the registered sender to disconnect
+ weak -- the weakref state to disconnect
- disconnect reverses the process of connect,
- the semantics for the individual elements are
- logically equivalent to a tuple of
- (receiver, signal, sender, weak) used as a key
- to be deleted from the internal routing tables.
- (The actual process is slightly more complex
- but the semantics are basically the same).
+ disconnect reverses the process of connect,
+ the semantics for the individual elements are
+ logically equivalent to a tuple of
+ (receiver, signal, sender, weak) used as a key
+ to be deleted from the internal routing tables.
+ (The actual process is slightly more complex
+ but the semantics are basically the same).
- Note:
- Using disconnect is not required to cleanup
- routing when an object is deleted, the framework
- will remove routes for deleted objects
- automatically. It's only necessary to disconnect
- if you want to stop routing to a live object.
-
- returns None, may raise DispatcherTypeError or
- DispatcherKeyError
- """
- if signal is None:
- raise errors.DispatcherTypeError(
- 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
- )
- if weak: receiver = saferef.safeRef(receiver)
- senderkey = id(sender)
- try:
- signals = connections[senderkey]
- receivers = signals[signal]
- except KeyError:
- raise errors.DispatcherKeyError(
- """No receivers found for signal %r from sender %r""" %(
- signal,
- sender
- )
- )
- try:
- # also removes from receivers
- _removeOldBackRefs(senderkey, signal, receiver, receivers)
- except ValueError:
- raise errors.DispatcherKeyError(
- """No connection to receiver %s for signal %s from sender %s""" %(
- receiver,
- signal,
- sender
- )
- )
- _cleanupConnections(senderkey, signal)
+ Note:
+ Using disconnect is not required to cleanup
+ routing when an object is deleted, the framework
+ will remove routes for deleted objects
+ automatically. It's only necessary to disconnect
+ if you want to stop routing to a live object.
+
+ returns None, may raise DispatcherTypeError or
+ DispatcherKeyError
+ """
+ if signal is None:
+ raise errors.DispatcherTypeError(
+ 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
+ )
+ if weak: receiver = saferef.safeRef(receiver)
+ senderkey = id(sender)
+ try:
+ signals = connections[senderkey]
+ receivers = signals[signal]
+ except KeyError:
+ raise errors.DispatcherKeyError(
+ """No receivers found for signal %r from sender %r""" %(
+ signal,
+ sender
+ )
+ )
+ try:
+ # also removes from receivers
+ _removeOldBackRefs(senderkey, signal, receiver, receivers)
+ except ValueError:
+ raise errors.DispatcherKeyError(
+ """No connection to receiver %s for signal %s from sender %s""" %(
+ receiver,
+ signal,
+ sender
+ )
+ )
+ _cleanupConnections(senderkey, signal)
def getReceivers( sender = Any, signal = Any ):
- """Get list of receivers from global tables
+ """Get list of receivers from global tables
- This utility function allows you to retrieve the
- raw list of receivers from the connections table
- for the given sender and signal pair.
+ This utility function allows you to retrieve the
+ raw list of receivers from the connections table
+ for the given sender and signal pair.
- Note:
- there is no guarantee that this is the actual list
- stored in the connections table, so the value
- should be treated as a simple iterable/truth value
- rather than, for instance a list to which you
- might append new records.
+ Note:
+ there is no guarantee that this is the actual list
+ stored in the connections table, so the value
+ should be treated as a simple iterable/truth value
+ rather than, for instance a list to which you
+ might append new records.
- Normally you would use liveReceivers( getReceivers( ...))
- to retrieve the actual receiver objects as an iterable
- object.
- """
- try:
- return connections[id(sender)][signal]
- except KeyError:
- return []
+ Normally you would use liveReceivers( getReceivers( ...))
+ to retrieve the actual receiver objects as an iterable
+ object.
+ """
+ try:
+ return connections[id(sender)][signal]
+ except KeyError:
+ return []
def liveReceivers(receivers):
- """Filter sequence of receivers to get resolved, live receivers
+ """Filter sequence of receivers to get resolved, live receivers
- This is a generator which will iterate over
- the passed sequence, checking for weak references
- and resolving them, then returning all live
- receivers.
- """
- for receiver in receivers:
- if isinstance( receiver, WEAKREF_TYPES):
- # Dereference the weak reference.
- receiver = receiver()
- if receiver is not None:
- yield receiver
- else:
- yield receiver
+ This is a generator which will iterate over
+ the passed sequence, checking for weak references
+ and resolving them, then returning all live
+ receivers.
+ """
+ for receiver in receivers:
+ if isinstance( receiver, WEAKREF_TYPES):
+ # Dereference the weak reference.
+ receiver = receiver()
+ if receiver is not None:
+ yield receiver
+ else:
+ yield receiver
def getAllReceivers( sender = Any, signal = Any ):
- """Get list of all receivers from global tables
+ """Get list of all receivers from global tables
- This gets all receivers which should receive
- the given signal from sender, each receiver should
- be produced only once by the resulting generator
- """
- receivers = {}
- for set in (
- # Get receivers that receive *this* signal from *this* sender.
- getReceivers( sender, signal ),
- # Add receivers that receive *any* signal from *this* sender.
- getReceivers( sender, Any ),
- # Add receivers that receive *this* signal from *any* sender.
- getReceivers( Any, signal ),
- # Add receivers that receive *any* signal from *any* sender.
- getReceivers( Any, Any ),
- ):
- for receiver in set:
- if receiver: # filter out dead instance-method weakrefs
- try:
- if not receivers.has_key( receiver ):
- receivers[receiver] = 1
- yield receiver
- except TypeError:
- # dead weakrefs raise TypeError on hash...
- pass
+ This gets all receivers which should receive
+ the given signal from sender, each receiver should
+ be produced only once by the resulting generator
+ """
+ receivers = {}
+ for set in (
+ # Get receivers that receive *this* signal from *this* sender.
+ getReceivers( sender, signal ),
+ # Add receivers that receive *any* signal from *this* sender.
+ getReceivers( sender, Any ),
+ # Add receivers that receive *this* signal from *any* sender.
+ getReceivers( Any, signal ),
+ # Add receivers that receive *any* signal from *any* sender.
+ getReceivers( Any, Any ),
+ ):
+ for receiver in set:
+ if receiver: # filter out dead instance-method weakrefs
+ try:
+ if not receivers.has_key( receiver ):
+ receivers[receiver] = 1
+ yield receiver
+ except TypeError:
+ # dead weakrefs raise TypeError on hash...
+ pass
def send(signal=Any, sender=Anonymous, *arguments, **named):
- """Send signal from sender to all connected receivers.
-
- signal -- (hashable) signal value, see connect for details
+ """Send signal from sender to all connected receivers.
+
+ signal -- (hashable) signal value, see connect for details
- sender -- the sender of the signal
-
- if Any, only receivers registered for Any will receive
- the message.
+ sender -- the sender of the signal
+
+ if Any, only receivers registered for Any will receive
+ the message.
- if Anonymous, only receivers registered to receive
- messages from Anonymous or Any will receive the message
+ if Anonymous, only receivers registered to receive
+ messages from Anonymous or Any will receive the message
- Otherwise can be any python object (normally one
- registered with a connect if you actually want
- something to occur).
+ Otherwise can be any python object (normally one
+ registered with a connect if you actually want
+ something to occur).
- arguments -- positional arguments which will be passed to
- *all* receivers. Note that this may raise TypeErrors
- if the receivers do not allow the particular arguments.
- Note also that arguments are applied before named
- arguments, so they should be used with care.
+ arguments -- positional arguments which will be passed to
+ *all* receivers. Note that this may raise TypeErrors
+ if the receivers do not allow the particular arguments.
+ Note also that arguments are applied before named
+ arguments, so they should be used with care.
- named -- named arguments which will be filtered according
- to the parameters of the receivers to only provide those
- acceptable to the receiver.
+ named -- named arguments which will be filtered according
+ to the parameters of the receivers to only provide those
+ acceptable to the receiver.
- Return a list of tuple pairs [(receiver, response), ... ]
+ Return a list of tuple pairs [(receiver, response), ... ]
- if any receiver raises an error, the error propagates back
- through send, terminating the dispatch loop, so it is quite
- possible to not have all receivers called if a raises an
- error.
- """
- # Call each receiver with whatever arguments it can accept.
- # Return a list of tuple pairs [(receiver, response), ... ].
- responses = []
- for receiver in liveReceivers(getAllReceivers(sender, signal)):
- response = robustapply.robustApply(
- receiver,
- signal=signal,
- sender=sender,
- *arguments,
- **named
- )
- responses.append((receiver, response))
- return responses
+ if any receiver raises an error, the error propagates back
+ through send, terminating the dispatch loop, so it is quite
+ possible to not have all receivers called if a raises an
+ error.
+ """
+ # Call each receiver with whatever arguments it can accept.
+ # Return a list of tuple pairs [(receiver, response), ... ].
+ responses = []
+ for receiver in liveReceivers(getAllReceivers(sender, signal)):
+ response = robustapply.robustApply(
+ receiver,
+ signal=signal,
+ sender=sender,
+ *arguments,
+ **named
+ )
+ responses.append((receiver, response))
+ return responses
def sendExact( signal=Any, sender=Anonymous, *arguments, **named ):
- """Send signal only to those receivers registered for exact message
+ """Send signal only to those receivers registered for exact message
- sendExact allows for avoiding Any/Anonymous registered
- handlers, sending only to those receivers explicitly
- registered for a particular signal on a particular
- sender.
- """
- responses = []
- for receiver in liveReceivers(getReceivers(sender, signal)):
- response = robustapply.robustApply(
- receiver,
- signal=signal,
- sender=sender,
- *arguments,
- **named
- )
- responses.append((receiver, response))
- return responses
-
+ sendExact allows for avoiding Any/Anonymous registered
+ handlers, sending only to those receivers explicitly
+ registered for a particular signal on a particular
+ sender.
+ """
+ responses = []
+ for receiver in liveReceivers(getReceivers(sender, signal)):
+ response = robustapply.robustApply(
+ receiver,
+ signal=signal,
+ sender=sender,
+ *arguments,
+ **named
+ )
+ responses.append((receiver, response))
+ return responses
+
def _removeReceiver(receiver):
- """Remove receiver from connections."""
- if not sendersBack:
- # During module cleanup the mapping will be replaced with None
- return False
- backKey = id(receiver)
- for senderkey in sendersBack.get(backKey,()):
- try:
- signals = connections[senderkey].keys()
- except KeyError,err:
- pass
- else:
- for signal in signals:
- try:
- receivers = connections[senderkey][signal]
- except KeyError:
- pass
- else:
- try:
- receivers.remove( receiver )
- except Exception, err:
- pass
- _cleanupConnections(senderkey, signal)
- try:
- del sendersBack[ backKey ]
- except KeyError:
- pass
-
+ """Remove receiver from connections."""
+ if not sendersBack:
+ # During module cleanup the mapping will be replaced with None
+ return False
+ backKey = id(receiver)
+ for senderkey in sendersBack.get(backKey,()):
+ try:
+ signals = connections[senderkey].keys()
+ except KeyError,err:
+ pass
+ else:
+ for signal in signals:
+ try:
+ receivers = connections[senderkey][signal]
+ except KeyError:
+ pass
+ else:
+ try:
+ receivers.remove( receiver )
+ except Exception, err:
+ pass
+ _cleanupConnections(senderkey, signal)
+ try:
+ del sendersBack[ backKey ]
+ except KeyError:
+ pass
+
def _cleanupConnections(senderkey, signal):
- """Delete any empty signals for senderkey. Delete senderkey if empty."""
- try:
- receivers = connections[senderkey][signal]
- except:
- pass
- else:
- if not receivers:
- # No more connected receivers. Therefore, remove the signal.
- try:
- signals = connections[senderkey]
- except KeyError:
- pass
- else:
- del signals[signal]
- if not signals:
- # No more signal connections. Therefore, remove the sender.
- _removeSender(senderkey)
+ """Delete any empty signals for senderkey. Delete senderkey if empty."""
+ try:
+ receivers = connections[senderkey][signal]
+ except:
+ pass
+ else:
+ if not receivers:
+ # No more connected receivers. Therefore, remove the signal.
+ try:
+ signals = connections[senderkey]
+ except KeyError:
+ pass
+ else:
+ del signals[signal]
+ if not signals:
+ # No more signal connections. Therefore, remove the sender.
+ _removeSender(senderkey)
def _removeSender(senderkey):
- """Remove senderkey from connections."""
- _removeBackrefs(senderkey)
- try:
- del connections[senderkey]
- except KeyError:
- pass
- # Senderkey will only be in senders dictionary if sender
- # could be weakly referenced.
- try:
- del senders[senderkey]
- except:
- pass
+ """Remove senderkey from connections."""
+ _removeBackrefs(senderkey)
+ try:
+ del connections[senderkey]
+ except KeyError:
+ pass
+ # Senderkey will only be in senders dictionary if sender
+ # could be weakly referenced.
+ try:
+ del senders[senderkey]
+ except:
+ pass
def _removeBackrefs( senderkey):
- """Remove all back-references to this senderkey"""
- try:
- signals = connections[senderkey]
- except KeyError:
- signals = None
- else:
- items = signals.items()
- def allReceivers( ):
- for signal,set in items:
- for item in set:
- yield item
- for receiver in allReceivers():
- _killBackref( receiver, senderkey )
+ """Remove all back-references to this senderkey"""
+ try:
+ signals = connections[senderkey]
+ except KeyError:
+ signals = None
+ else:
+ items = signals.items()
+ def allReceivers( ):
+ for signal,set in items:
+ for item in set:
+ yield item
+ for receiver in allReceivers():
+ _killBackref( receiver, senderkey )
def _removeOldBackRefs(senderkey, signal, receiver, receivers):
- """Kill old sendersBack references from receiver
+ """Kill old sendersBack references from receiver
- This guards against multiple registration of the same
- receiver for a given signal and sender leaking memory
- as old back reference records build up.
+ This guards against multiple registration of the same
+ receiver for a given signal and sender leaking memory
+ as old back reference records build up.
- Also removes old receiver instance from receivers
- """
- try:
- index = receivers.index(receiver)
- # need to scan back references here and remove senderkey
- except ValueError:
- return False
- else:
- oldReceiver = receivers[index]
- del receivers[index]
- found = 0
- signals = connections.get(signal)
- if signals is not None:
- for sig,recs in connections.get(signal,{}).iteritems():
- if sig != signal:
- for rec in recs:
- if rec is oldReceiver:
- found = 1
- break
- if not found:
- _killBackref( oldReceiver, senderkey )
- return True
- return False
-
-
+ Also removes old receiver instance from receivers
+ """
+ try:
+ index = receivers.index(receiver)
+ # need to scan back references here and remove senderkey
+ except ValueError:
+ return False
+ else:
+ oldReceiver = receivers[index]
+ del receivers[index]
+ found = 0
+ signals = connections.get(signal)
+ if signals is not None:
+ for sig,recs in connections.get(signal,{}).iteritems():
+ if sig != signal:
+ for rec in recs:
+ if rec is oldReceiver:
+ found = 1
+ break
+ if not found:
+ _killBackref( oldReceiver, senderkey )
+ return True
+ return False
+
+
def _killBackref( receiver, senderkey ):
- """Do the actual removal of back reference from receiver to senderkey"""
- receiverkey = id(receiver)
- set = sendersBack.get( receiverkey, () )
- while senderkey in set:
- try:
- set.remove( senderkey )
- except:
- break
- if not set:
- try:
- del sendersBack[ receiverkey ]
- except KeyError:
- pass
- return True
+ """Do the actual removal of back reference from receiver to senderkey"""
+ receiverkey = id(receiver)
+ set = sendersBack.get( receiverkey, () )
+ while senderkey in set:
+ try:
+ set.remove( senderkey )
+ except:
+ break
+ if not set:
+ try:
+ del sendersBack[ receiverkey ]
+ except KeyError:
+ pass
+ return True
diff --git a/django/dispatch/errors.py b/django/dispatch/errors.py
index a2eb32ed75..a4c924dbe9 100644
--- a/django/dispatch/errors.py
+++ b/django/dispatch/errors.py
@@ -2,9 +2,9 @@
"""
class DispatcherError(Exception):
- """Base class for all Dispatcher errors"""
+ """Base class for all Dispatcher errors"""
class DispatcherKeyError(KeyError, DispatcherError):
- """Error raised when unknown (sender,signal) set specified"""
+ """Error raised when unknown (sender,signal) set specified"""
class DispatcherTypeError(TypeError, DispatcherError):
- """Error raised when inappropriate signal-type specified (None)"""
+ """Error raised when inappropriate signal-type specified (None)"""
diff --git a/django/dispatch/license.txt b/django/dispatch/license.txt
index 2f0b6b5ef2..8ff5d28613 100644
--- a/django/dispatch/license.txt
+++ b/django/dispatch/license.txt
@@ -1,34 +1,34 @@
PyDispatcher License
- Copyright (c) 2001-2003, Patrick K. O'Brien and Contributors
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- The name of Patrick K. O'Brien, or the name of any Contributor,
- may not be used to endorse or promote products derived from this
- software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- OF THE POSSIBILITY OF SUCH DAMAGE.
+ Copyright (c) 2001-2003, Patrick K. O'Brien and Contributors
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ The name of Patrick K. O'Brien, or the name of any Contributor,
+ may not be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/django/dispatch/robust.py b/django/dispatch/robust.py
index ba19934d43..8b1590de35 100644
--- a/django/dispatch/robust.py
+++ b/django/dispatch/robust.py
@@ -3,55 +3,55 @@ from django.dispatch.dispatcher import Any, Anonymous, liveReceivers, getAllRece
from django.dispatch.robustapply import robustApply
def sendRobust(
- signal=Any,
- sender=Anonymous,
- *arguments, **named
+ signal=Any,
+ sender=Anonymous,
+ *arguments, **named
):
- """Send signal from sender to all connected receivers catching errors
-
- signal -- (hashable) signal value, see connect for details
+ """Send signal from sender to all connected receivers catching errors
+
+ signal -- (hashable) signal value, see connect for details
- sender -- the sender of the signal
-
- if Any, only receivers registered for Any will receive
- the message.
+ sender -- the sender of the signal
+
+ if Any, only receivers registered for Any will receive
+ the message.
- if Anonymous, only receivers registered to receive
- messages from Anonymous or Any will receive the message
+ if Anonymous, only receivers registered to receive
+ messages from Anonymous or Any will receive the message
- Otherwise can be any python object (normally one
- registered with a connect if you actually want
- something to occur).
+ Otherwise can be any python object (normally one
+ registered with a connect if you actually want
+ something to occur).
- arguments -- positional arguments which will be passed to
- *all* receivers. Note that this may raise TypeErrors
- if the receivers do not allow the particular arguments.
- Note also that arguments are applied before named
- arguments, so they should be used with care.
+ arguments -- positional arguments which will be passed to
+ *all* receivers. Note that this may raise TypeErrors
+ if the receivers do not allow the particular arguments.
+ Note also that arguments are applied before named
+ arguments, so they should be used with care.
- named -- named arguments which will be filtered according
- to the parameters of the receivers to only provide those
- acceptable to the receiver.
+ named -- named arguments which will be filtered according
+ to the parameters of the receivers to only provide those
+ acceptable to the receiver.
- Return a list of tuple pairs [(receiver, response), ... ]
+ Return a list of tuple pairs [(receiver, response), ... ]
- if any receiver raises an error (specifically any subclass of Exception),
- the error instance is returned as the result for that receiver.
- """
- # Call each receiver with whatever arguments it can accept.
- # Return a list of tuple pairs [(receiver, response), ... ].
- responses = []
- for receiver in liveReceivers(getAllReceivers(sender, signal)):
- try:
- response = robustApply(
- receiver,
- signal=signal,
- sender=sender,
- *arguments,
- **named
- )
- except Exception, err:
- responses.append((receiver, err))
- else:
- responses.append((receiver, response))
- return responses
+ if any receiver raises an error (specifically any subclass of Exception),
+ the error instance is returned as the result for that receiver.
+ """
+ # Call each receiver with whatever arguments it can accept.
+ # Return a list of tuple pairs [(receiver, response), ... ].
+ responses = []
+ for receiver in liveReceivers(getAllReceivers(sender, signal)):
+ try:
+ response = robustApply(
+ receiver,
+ signal=signal,
+ sender=sender,
+ *arguments,
+ **named
+ )
+ except Exception, err:
+ responses.append((receiver, err))
+ else:
+ responses.append((receiver, response))
+ return responses
diff --git a/django/dispatch/robustapply.py b/django/dispatch/robustapply.py
index 0350e60cfc..14ba2b51ac 100644
--- a/django/dispatch/robustapply.py
+++ b/django/dispatch/robustapply.py
@@ -7,43 +7,41 @@ those which are acceptable.
"""
def function( receiver ):
- """Get function-like callable object for given receiver
+ """Get function-like callable object for given receiver
- returns (function_or_method, codeObject, fromMethod)
+ returns (function_or_method, codeObject, fromMethod)
- If fromMethod is true, then the callable already
- has its first argument bound
- """
- if hasattr(receiver, '__call__'):
- # receiver is a class instance; assume it is callable.
- # Reassign receiver to the actual method that will be called.
- if hasattr( receiver.__call__, 'im_func') or hasattr( receiver.__call__, 'im_code'):
- receiver = receiver.__call__
- if hasattr( receiver, 'im_func' ):
- # an instance-method...
- return receiver, receiver.im_func.func_code, 1
- elif not hasattr( receiver, 'func_code'):
- raise ValueError('unknown reciever type %s %s'%(receiver, type(receiver)))
- return receiver, receiver.func_code, 0
+ If fromMethod is true, then the callable already
+ has its first argument bound
+ """
+ if hasattr(receiver, '__call__'):
+ # receiver is a class instance; assume it is callable.
+ # Reassign receiver to the actual method that will be called.
+ if hasattr( receiver.__call__, 'im_func') or hasattr( receiver.__call__, 'im_code'):
+ receiver = receiver.__call__
+ if hasattr( receiver, 'im_func' ):
+ # an instance-method...
+ return receiver, receiver.im_func.func_code, 1
+ elif not hasattr( receiver, 'func_code'):
+ raise ValueError('unknown reciever type %s %s'%(receiver, type(receiver)))
+ return receiver, receiver.func_code, 0
def robustApply(receiver, *arguments, **named):
- """Call receiver with arguments and an appropriate subset of named
- """
- receiver, codeObject, startIndex = function( receiver )
- acceptable = codeObject.co_varnames[startIndex+len(arguments):codeObject.co_argcount]
- for name in codeObject.co_varnames[startIndex:startIndex+len(arguments)]:
- if named.has_key( name ):
- raise TypeError(
- """Argument %r specified both positionally and as a keyword for calling %r"""% (
- name, receiver,
- )
- )
- if not (codeObject.co_flags & 8):
- # fc does not have a **kwds type parameter, therefore
- # remove unacceptable arguments.
- for arg in named.keys():
- if arg not in acceptable:
- del named[arg]
- return receiver(*arguments, **named)
-
- \ No newline at end of file
+ """Call receiver with arguments and an appropriate subset of named
+ """
+ receiver, codeObject, startIndex = function( receiver )
+ acceptable = codeObject.co_varnames[startIndex+len(arguments):codeObject.co_argcount]
+ for name in codeObject.co_varnames[startIndex:startIndex+len(arguments)]:
+ if named.has_key( name ):
+ raise TypeError(
+ """Argument %r specified both positionally and as a keyword for calling %r"""% (
+ name, receiver,
+ )
+ )
+ if not (codeObject.co_flags & 8):
+ # fc does not have a **kwds type parameter, therefore
+ # remove unacceptable arguments.
+ for arg in named.keys():
+ if arg not in acceptable:
+ del named[arg]
+ return receiver(*arguments, **named)
diff --git a/django/dispatch/saferef.py b/django/dispatch/saferef.py
index 6b3eda1d38..74b7a41942 100644
--- a/django/dispatch/saferef.py
+++ b/django/dispatch/saferef.py
@@ -2,164 +2,164 @@
import weakref, traceback
def safeRef(target, onDelete = None):
- """Return a *safe* weak reference to a callable target
+ """Return a *safe* weak reference to a callable target
- target -- the object to be weakly referenced, if it's a
- bound method reference, will create a BoundMethodWeakref,
- otherwise creates a simple weakref.
- onDelete -- if provided, will have a hard reference stored
- to the callable to be called after the safe reference
- goes out of scope with the reference object, (either a
- weakref or a BoundMethodWeakref) as argument.
- """
- if hasattr(target, 'im_self'):
- if target.im_self is not None:
- # Turn a bound method into a BoundMethodWeakref instance.
- # Keep track of these instances for lookup by disconnect().
- assert hasattr(target, 'im_func'), """safeRef target %r has im_self, but no im_func, don't know how to create reference"""%( target,)
- reference = BoundMethodWeakref(
- target=target,
- onDelete=onDelete
- )
- return reference
- if callable(onDelete):
- return weakref.ref(target, onDelete)
- else:
- return weakref.ref( target )
+ target -- the object to be weakly referenced, if it's a
+ bound method reference, will create a BoundMethodWeakref,
+ otherwise creates a simple weakref.
+ onDelete -- if provided, will have a hard reference stored
+ to the callable to be called after the safe reference
+ goes out of scope with the reference object, (either a
+ weakref or a BoundMethodWeakref) as argument.
+ """
+ if hasattr(target, 'im_self'):
+ if target.im_self is not None:
+ # Turn a bound method into a BoundMethodWeakref instance.
+ # Keep track of these instances for lookup by disconnect().
+ assert hasattr(target, 'im_func'), """safeRef target %r has im_self, but no im_func, don't know how to create reference"""%( target,)
+ reference = BoundMethodWeakref(
+ target=target,
+ onDelete=onDelete
+ )
+ return reference
+ if callable(onDelete):
+ return weakref.ref(target, onDelete)
+ else:
+ return weakref.ref( target )
class BoundMethodWeakref(object):
- """'Safe' and reusable weak references to instance methods
+ """'Safe' and reusable weak references to instance methods
- BoundMethodWeakref objects provide a mechanism for
- referencing a bound method without requiring that the
- method object itself (which is normally a transient
- object) is kept alive. Instead, the BoundMethodWeakref
- object keeps weak references to both the object and the
- function which together define the instance method.
+ BoundMethodWeakref objects provide a mechanism for
+ referencing a bound method without requiring that the
+ method object itself (which is normally a transient
+ object) is kept alive. Instead, the BoundMethodWeakref
+ object keeps weak references to both the object and the
+ function which together define the instance method.
- Attributes:
- key -- the identity key for the reference, calculated
- by the class's calculateKey method applied to the
- target instance method
- deletionMethods -- sequence of callable objects taking
- single argument, a reference to this object which
- will be called when *either* the target object or
- target function is garbage collected (i.e. when
- this object becomes invalid). These are specified
- as the onDelete parameters of safeRef calls.
- weakSelf -- weak reference to the target object
- weakFunc -- weak reference to the target function
+ Attributes:
+ key -- the identity key for the reference, calculated
+ by the class's calculateKey method applied to the
+ target instance method
+ deletionMethods -- sequence of callable objects taking
+ single argument, a reference to this object which
+ will be called when *either* the target object or
+ target function is garbage collected (i.e. when
+ this object becomes invalid). These are specified
+ as the onDelete parameters of safeRef calls.
+ weakSelf -- weak reference to the target object
+ weakFunc -- weak reference to the target function
- Class Attributes:
- _allInstances -- class attribute pointing to all live
- BoundMethodWeakref objects indexed by the class's
- calculateKey(target) method applied to the target
- objects. This weak value dictionary is used to
- short-circuit creation so that multiple references
- to the same (object, function) pair produce the
- same BoundMethodWeakref instance.
+ Class Attributes:
+ _allInstances -- class attribute pointing to all live
+ BoundMethodWeakref objects indexed by the class's
+ calculateKey(target) method applied to the target
+ objects. This weak value dictionary is used to
+ short-circuit creation so that multiple references
+ to the same (object, function) pair produce the
+ same BoundMethodWeakref instance.
- """
- _allInstances = weakref.WeakValueDictionary()
- def __new__( cls, target, onDelete=None, *arguments,**named ):
- """Create new instance or return current instance
+ """
+ _allInstances = weakref.WeakValueDictionary()
+ def __new__( cls, target, onDelete=None, *arguments,**named ):
+ """Create new instance or return current instance
- Basically this method of construction allows us to
- short-circuit creation of references to already-
- referenced instance methods. The key corresponding
- to the target is calculated, and if there is already
- an existing reference, that is returned, with its
- deletionMethods attribute updated. Otherwise the
- new instance is created and registered in the table
- of already-referenced methods.
- """
- key = cls.calculateKey(target)
- current =cls._allInstances.get(key)
- if current is not None:
- current.deletionMethods.append( onDelete)
- return current
- else:
- base = super( BoundMethodWeakref, cls).__new__( cls )
- cls._allInstances[key] = base
- base.__init__( target, onDelete, *arguments,**named)
- return base
- def __init__(self, target, onDelete=None):
- """Return a weak-reference-like instance for a bound method
+ Basically this method of construction allows us to
+ short-circuit creation of references to already-
+ referenced instance methods. The key corresponding
+ to the target is calculated, and if there is already
+ an existing reference, that is returned, with its
+ deletionMethods attribute updated. Otherwise the
+ new instance is created and registered in the table
+ of already-referenced methods.
+ """
+ key = cls.calculateKey(target)
+ current =cls._allInstances.get(key)
+ if current is not None:
+ current.deletionMethods.append( onDelete)
+ return current
+ else:
+ base = super( BoundMethodWeakref, cls).__new__( cls )
+ cls._allInstances[key] = base
+ base.__init__( target, onDelete, *arguments,**named)
+ return base
+ def __init__(self, target, onDelete=None):
+ """Return a weak-reference-like instance for a bound method
- target -- the instance-method target for the weak
- reference, must have im_self and im_func attributes
- and be reconstructable via:
- target.im_func.__get__( target.im_self )
- which is true of built-in instance methods.
- onDelete -- optional callback which will be called
- when this weak reference ceases to be valid
- (i.e. either the object or the function is garbage
- collected). Should take a single argument,
- which will be passed a pointer to this object.
- """
- def remove(weak, self=self):
- """Set self.isDead to true when method or instance is destroyed"""
- methods = self.deletionMethods[:]
- del self.deletionMethods[:]
- try:
- del self.__class__._allInstances[ self.key ]
- except KeyError:
- pass
- for function in methods:
- try:
- if callable( function ):
- function( self )
- except Exception, e:
- try:
- traceback.print_exc()
- except AttributeError, err:
- print '''Exception during saferef %s cleanup function %s: %s'''%(
- self, function, e
- )
- self.deletionMethods = [onDelete]
- self.key = self.calculateKey( target )
- self.weakSelf = weakref.ref(target.im_self, remove)
- self.weakFunc = weakref.ref(target.im_func, remove)
- self.selfName = str(target.im_self)
- self.funcName = str(target.im_func.__name__)
- def calculateKey( cls, target ):
- """Calculate the reference key for this reference
+ target -- the instance-method target for the weak
+ reference, must have im_self and im_func attributes
+ and be reconstructable via:
+ target.im_func.__get__( target.im_self )
+ which is true of built-in instance methods.
+ onDelete -- optional callback which will be called
+ when this weak reference ceases to be valid
+ (i.e. either the object or the function is garbage
+ collected). Should take a single argument,
+ which will be passed a pointer to this object.
+ """
+ def remove(weak, self=self):
+ """Set self.isDead to true when method or instance is destroyed"""
+ methods = self.deletionMethods[:]
+ del self.deletionMethods[:]
+ try:
+ del self.__class__._allInstances[ self.key ]
+ except KeyError:
+ pass
+ for function in methods:
+ try:
+ if callable( function ):
+ function( self )
+ except Exception, e:
+ try:
+ traceback.print_exc()
+ except AttributeError, err:
+ print '''Exception during saferef %s cleanup function %s: %s'''%(
+ self, function, e
+ )
+ self.deletionMethods = [onDelete]
+ self.key = self.calculateKey( target )
+ self.weakSelf = weakref.ref(target.im_self, remove)
+ self.weakFunc = weakref.ref(target.im_func, remove)
+ self.selfName = str(target.im_self)
+ self.funcName = str(target.im_func.__name__)
+ def calculateKey( cls, target ):
+ """Calculate the reference key for this reference
- Currently this is a two-tuple of the id()'s of the
- target object and the target function respectively.
- """
- return (id(target.im_self),id(target.im_func))
- calculateKey = classmethod( calculateKey )
- def __str__(self):
- """Give a friendly representation of the object"""
- return """%s( %s.%s )"""%(
- self.__class__.__name__,
- self.selfName,
- self.funcName,
- )
- __repr__ = __str__
- def __nonzero__( self ):
- """Whether we are still a valid reference"""
- return self() is not None
- def __cmp__( self, other ):
- """Compare with another reference"""
- if not isinstance (other,self.__class__):
- return cmp( self.__class__, type(other) )
- return cmp( self.key, other.key)
- def __call__(self):
- """Return a strong reference to the bound method
+ Currently this is a two-tuple of the id()'s of the
+ target object and the target function respectively.
+ """
+ return (id(target.im_self),id(target.im_func))
+ calculateKey = classmethod( calculateKey )
+ def __str__(self):
+ """Give a friendly representation of the object"""
+ return """%s( %s.%s )"""%(
+ self.__class__.__name__,
+ self.selfName,
+ self.funcName,
+ )
+ __repr__ = __str__
+ def __nonzero__( self ):
+ """Whether we are still a valid reference"""
+ return self() is not None
+ def __cmp__( self, other ):
+ """Compare with another reference"""
+ if not isinstance (other,self.__class__):
+ return cmp( self.__class__, type(other) )
+ return cmp( self.key, other.key)
+ def __call__(self):
+ """Return a strong reference to the bound method
- If the target cannot be retrieved, then will
- return None, otherwise returns a bound instance
- method for our object and function.
+ If the target cannot be retrieved, then will
+ return None, otherwise returns a bound instance
+ method for our object and function.
- Note:
- You may call this method any number of times,
- as it does not invalidate the reference.
- """
- target = self.weakSelf()
- if target is not None:
- function = self.weakFunc()
- if function is not None:
- return function.__get__(target)
- return None
+ Note:
+ You may call this method any number of times,
+ as it does not invalidate the reference.
+ """
+ target = self.weakSelf()
+ if target is not None:
+ function = self.weakFunc()
+ if function is not None:
+ return function.__get__(target)
+ return None
diff --git a/django/forms/__init__.py b/django/forms/__init__.py
index 4907bd76f7..5f47059f03 100644
--- a/django/forms/__init__.py
+++ b/django/forms/__init__.py
@@ -2,7 +2,7 @@ from django.core import validators
from django.core.exceptions import PermissionDenied
from django.utils.html import escape
from django.conf import settings
-from django.utils.translation import gettext, gettext_lazy, ngettext
+from django.utils.translation import gettext, ngettext
FORM_FIELD_ID_PREFIX = 'id_'
@@ -54,6 +54,7 @@ class Manipulator(object):
def get_validation_errors(self, new_data):
"Returns dictionary mapping field_names to error-message lists"
errors = {}
+ self.prepare(new_data)
for field in self.fields:
errors.update(field.get_validation_errors(new_data))
val_name = 'validate_%s' % field.field_name
@@ -343,7 +344,7 @@ class FormField(object):
def get_validation_errors(self, new_data):
errors = {}
if self.is_required and not new_data.get(self.field_name, False):
- errors.setdefault(self.field_name, []).append(gettext_lazy('This field is required.'))
+ errors.setdefault(self.field_name, []).append(gettext('This field is required.'))
return errors
try:
for validator in self.validator_list:
@@ -434,10 +435,12 @@ class HiddenField(FormField):
(self.get_id(), self.field_name, escape(data))
class CheckboxField(FormField):
- def __init__(self, field_name, checked_by_default=False):
+ def __init__(self, field_name, checked_by_default=False, validator_list=None, is_required=False):
+ if validator_list is None: validator_list = []
self.field_name = field_name
self.checked_by_default = checked_by_default
- self.is_required, self.validator_list = False, [] # because the validator looks for these
+ self.is_required = is_required
+ self.validator_list = validator_list[:]
def render(self, data):
checked_html = ''
@@ -636,9 +639,9 @@ class CheckboxSelectMultipleField(SelectMultipleField):
if str(value) in str_data_list:
checked_html = ' checked="checked"'
field_name = '%s%s' % (self.field_name, value)
- output.append('<li><input type="checkbox" id="%s" class="v%s" name="%s"%s /> <label for="%s">%s</label></li>' % \
- (self.get_id() + value , self.__class__.__name__, field_name, checked_html,
- self.get_id() + value, choice))
+ output.append('<li><input type="checkbox" id="%s" class="v%s" name="%s"%s value="on" /> <label for="%s">%s</label></li>' % \
+ (self.get_id() + escape(value), self.__class__.__name__, field_name, checked_html,
+ self.get_id() + escape(value), choice))
output.append('</ul>')
return '\n'.join(output)
@@ -741,7 +744,7 @@ class FloatField(TextField):
if validator_list is None: validator_list = []
self.max_digits, self.decimal_places = max_digits, decimal_places
validator_list = [self.isValidFloat] + validator_list
- TextField.__init__(self, field_name, max_digits+1, max_digits+1, is_required, validator_list)
+ TextField.__init__(self, field_name, max_digits+2, max_digits+2, is_required, validator_list)
def isValidFloat(self, field_data, all_data):
v = validators.IsValidFloat(self.max_digits, self.decimal_places)
@@ -950,10 +953,7 @@ class USStateField(TextField):
raise validators.CriticalValidationError, e.messages
def html2python(data):
- if data:
- return data.upper() # Should always be stored in upper case
- else:
- return None
+ return data.upper() # Should always be stored in upper case
html2python = staticmethod(html2python)
class CommaSeparatedIntegerField(TextField):
@@ -970,9 +970,19 @@ class CommaSeparatedIntegerField(TextField):
except validators.ValidationError, e:
raise validators.CriticalValidationError, e.messages
+ def render(self, data):
+ if data is None:
+ data = ''
+ elif isinstance(data, (list, tuple)):
+ data = ','.join(data)
+ return super(CommaSeparatedIntegerField, self).render(data)
+
class RawIdAdminField(CommaSeparatedIntegerField):
def html2python(data):
- return data.split(',')
+ if data:
+ return data.split(',')
+ else:
+ return []
html2python = staticmethod(html2python)
class XMLLargeTextField(LargeTextField):
diff --git a/django/http/__init__.py b/django/http/__init__.py
index 8fb4b293fc..bb0e973aae 100644
--- a/django/http/__init__.py
+++ b/django/http/__init__.py
@@ -1,3 +1,4 @@
+import os
from Cookie import SimpleCookie
from pprint import pformat
from urllib import urlencode, quote
@@ -38,6 +39,9 @@ class HttpRequest(object):
def get_full_path(self):
return ''
+ def is_secure(self):
+ return os.environ.get("HTTPS") == "on"
+
def parse_file_upload(header_dict, post_data):
"Returns a tuple of (POST MultiValueDict, FILES MultiValueDict)"
import email, email.Message
@@ -157,10 +161,10 @@ class HttpResponse(object):
if not mimetype:
mimetype = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE, settings.DEFAULT_CHARSET)
if hasattr(content, '__iter__'):
- self._iterator = content
+ self._container = content
self._is_string = False
else:
- self._iterator = [content]
+ self._container = [content]
self._is_string = True
self.headers = {'Content-Type': mimetype}
self.cookies = SimpleCookie()
@@ -199,39 +203,47 @@ class HttpResponse(object):
if val is not None:
self.cookies[key][var.replace('_', '-')] = val
- def delete_cookie(self, key):
- try:
- self.cookies[key]['max_age'] = 0
- except KeyError:
- pass
+ def delete_cookie(self, key, path='/', domain=None):
+ self.cookies[key] = ''
+ if path is not None:
+ self.cookies[key]['path'] = path
+ if domain is not None:
+ self.cookies[key]['domain'] = path
+ self.cookies[key]['expires'] = 0
+ self.cookies[key]['max-age'] = 0
def _get_content(self):
- content = ''.join(self._iterator)
+ content = ''.join(self._container)
if isinstance(content, unicode):
content = content.encode(self._charset)
return content
def _set_content(self, value):
- self._iterator = [value]
+ self._container = [value]
self._is_string = True
content = property(_get_content, _set_content)
- def _get_iterator(self):
- "Output iterator. Converts data into client charset if necessary."
- for chunk in self._iterator:
- if isinstance(chunk, unicode):
- chunk = chunk.encode(self._charset)
- yield chunk
+ def __iter__(self):
+ self._iterator = self._container.__iter__()
+ return self
+
+ def next(self):
+ chunk = self._iterator.next()
+ if isinstance(chunk, unicode):
+ chunk = chunk.encode(self._charset)
+ return chunk
- iterator = property(_get_iterator)
+ def close(self):
+ if hasattr(self._container, 'close'):
+ self._container.close()
# The remaining methods partially implement the file-like object interface.
# See http://docs.python.org/lib/bltin-file-objects.html
def write(self, content):
if not self._is_string:
raise Exception, "This %s instance is not writable" % self.__class__
- self._iterator.append(content)
+ self._container.append(content)
def flush(self):
pass
@@ -239,7 +251,7 @@ class HttpResponse(object):
def tell(self):
if not self._is_string:
raise Exception, "This %s instance cannot tell its position" % self.__class__
- return sum([len(chunk) for chunk in self._iterator])
+ return sum([len(chunk) for chunk in self._container])
class HttpResponseRedirect(HttpResponse):
def __init__(self, redirect_to):
diff --git a/django/middleware/cache.py b/django/middleware/cache.py
index 80c8626db8..58800b24da 100644
--- a/django/middleware/cache.py
+++ b/django/middleware/cache.py
@@ -1,7 +1,6 @@
from django.conf import settings
from django.core.cache import cache
from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers
-from django.http import HttpResponseNotModified
class CacheMiddleware(object):
"""
@@ -10,6 +9,11 @@ class CacheMiddleware(object):
Only parameter-less GET or HEAD-requests with status code 200 are cached.
+ If CACHE_MIDDLEWARE_ANONYMOUS_ONLY is set to True, only anonymous requests
+ (i.e., those node made by a logged-in user) will be cached. This is a
+ simple and effective way of avoiding the caching of the Django admin (and
+ any other user-specific content).
+
This middleware expects that a HEAD request is answered with a response
exactly like the corresponding GET request.
@@ -23,20 +27,31 @@ class CacheMiddleware(object):
This middleware also sets ETag, Last-Modified, Expires and Cache-Control
headers on the response object.
"""
- def __init__(self, cache_timeout=None, key_prefix=None):
+ def __init__(self, cache_timeout=None, key_prefix=None, cache_anonymous_only=None):
self.cache_timeout = cache_timeout
if cache_timeout is None:
self.cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
self.key_prefix = key_prefix
if key_prefix is None:
self.key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
+ if cache_anonymous_only is None:
+ self.cache_anonymous_only = getattr(settings, 'CACHE_MIDDLEWARE_ANONYMOUS_ONLY', False)
+ else:
+ self.cache_anonymous_only = cache_anonymous_only
def process_request(self, request):
"Checks whether the page is already cached and returns the cached version if available."
+ if self.cache_anonymous_only:
+ assert hasattr(request, 'user'), "The Django cache middleware with CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' before the CacheMiddleware."
+
if not request.method in ('GET', 'HEAD') or request.GET:
request._cache_update_cache = False
return None # Don't bother checking the cache.
+ if self.cache_anonymous_only and request.user.is_authenticated():
+ request._cache_update_cache = False
+ return None # Don't cache requests from authenticated users.
+
cache_key = get_cache_key(request, self.key_prefix)
if cache_key is None:
request._cache_update_cache = True
diff --git a/django/middleware/common.py b/django/middleware/common.py
index a42c54751d..6283214fad 100644
--- a/django/middleware/common.py
+++ b/django/middleware/common.py
@@ -1,7 +1,8 @@
from django.conf import settings
from django import http
from django.core.mail import mail_managers
-import md5, os
+import md5
+import re
class CommonMiddleware(object):
"""
@@ -44,7 +45,7 @@ class CommonMiddleware(object):
if new_url != old_url:
# Redirect
if new_url[0]:
- newurl = "%s://%s%s" % (os.environ.get('HTTPS') == 'on' and 'https' or 'http', new_url[0], new_url[1])
+ newurl = "%s://%s%s" % (request.is_secure() and 'https' or 'http', new_url[0], new_url[1])
else:
newurl = new_url[1]
if request.GET:
@@ -61,11 +62,12 @@ class CommonMiddleware(object):
# send a note to the managers.
domain = http.get_host(request)
referer = request.META.get('HTTP_REFERER', None)
- is_internal = referer and (domain in referer)
+ is_internal = _is_internal_request(domain, referer)
path = request.get_full_path()
if referer and not _is_ignorable_404(path) and (is_internal or '?' not in referer):
+ ua = request.META.get('HTTP_USER_AGENT', '<none>')
mail_managers("Broken %slink on %s" % ((is_internal and 'INTERNAL ' or ''), domain),
- "Referrer: %s\nRequested URL: %s\n" % (referer, request.get_full_path()))
+ "Referrer: %s\nRequested URL: %s\nUser agent: %s\n" % (referer, request.get_full_path(), ua))
return response
# Use ETags, if requested.
@@ -87,3 +89,8 @@ def _is_ignorable_404(uri):
if uri.endswith(end):
return True
return False
+
+def _is_internal_request(domain, referer):
+ "Return true if the referring URL is the same domain as the current request"
+ # Different subdomains are treated as different domains.
+ return referer is not None and re.match("^https?://%s/" % re.escape(domain), referer)
diff --git a/django/middleware/doc.py b/django/middleware/doc.py
index 6600e588cd..48c155c392 100644
--- a/django/middleware/doc.py
+++ b/django/middleware/doc.py
@@ -7,11 +7,12 @@ class XViewMiddleware(object):
"""
def process_view(self, request, view_func, view_args, view_kwargs):
"""
- If the request method is HEAD and the IP is internal, quickly return
- with an x-header indicating the view function. This is used by the
- documentation module to lookup the view function for an arbitrary page.
+ If the request method is HEAD and either the IP is internal or the
+ user is a logged-in staff member, quickly return with an x-header
+ indicating the view function. This is used by the documentation module
+ to lookup the view function for an arbitrary page.
"""
- if request.method == 'HEAD' and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
+ if request.method == 'HEAD' and (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or (request.user.is_authenticated() and request.user.is_staff)):
response = http.HttpResponse()
response['X-View'] = "%s.%s" % (view_func.__module__, view_func.__name__)
return response
diff --git a/django/middleware/gzip.py b/django/middleware/gzip.py
index cc8a68406c..7d860abdb1 100644
--- a/django/middleware/gzip.py
+++ b/django/middleware/gzip.py
@@ -12,7 +12,11 @@ class GZipMiddleware(object):
"""
def process_response(self, request, response):
patch_vary_headers(response, ('Accept-Encoding',))
- if response.has_header('Content-Encoding'):
+
+ # Avoid gzipping if we've already got a content-encoding or if the
+ # content-type is Javascript (silly IE...)
+ is_js = "javascript" in response.headers.get('Content-Type', '').lower()
+ if response.has_header('Content-Encoding') or is_js:
return response
ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
diff --git a/django/middleware/http.py b/django/middleware/http.py
index 12d0c0f683..3ebd8ffd1a 100644
--- a/django/middleware/http.py
+++ b/django/middleware/http.py
@@ -35,3 +35,27 @@ class ConditionalGetMiddleware(object):
response.content = ''
return response
+
+class SetRemoteAddrFromForwardedFor(object):
+ """
+ Middleware that sets REMOTE_ADDR based on HTTP_X_FORWARDED_FOR, if the
+ latter is set. This is useful if you're sitting behind a reverse proxy that
+ causes each request's REMOTE_ADDR to be set to 127.0.0.1.
+
+ Note that this does NOT validate HTTP_X_FORWARDED_FOR. If you're not behind
+ a reverse proxy that sets HTTP_X_FORWARDED_FOR automatically, do not use
+ this middleware. Anybody can spoof the value of HTTP_X_FORWARDED_FOR, and
+ because this sets REMOTE_ADDR based on HTTP_X_FORWARDED_FOR, that means
+ anybody can "fake" their IP address. Only use this when you can absolutely
+ trust the value of HTTP_X_FORWARDED_FOR.
+ """
+ def process_request(self, request):
+ try:
+ real_ip = request.META['HTTP_X_FORWARDED_FOR']
+ except KeyError:
+ return None
+ else:
+ # HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs.
+ # Take just the first one.
+ real_ip = real_ip.split(",")[0]
+ request.META['REMOTE_ADDR'] = real_ip
diff --git a/django/middleware/transaction.py b/django/middleware/transaction.py
index 4128e012f2..96b1538d9d 100644
--- a/django/middleware/transaction.py
+++ b/django/middleware/transaction.py
@@ -1,4 +1,3 @@
-from django.conf import settings
from django.db import transaction
class TransactionMiddleware(object):
diff --git a/django/template/__init__.py b/django/template/__init__.py
index e898fc7636..60526b663d 100644
--- a/django/template/__init__.py
+++ b/django/template/__init__.py
@@ -66,6 +66,7 @@ __all__ = ('Template', 'Context', 'RequestContext', 'compile_string')
TOKEN_TEXT = 0
TOKEN_VAR = 1
TOKEN_BLOCK = 2
+TOKEN_COMMENT = 3
# template syntax constants
FILTER_SEPARATOR = '|'
@@ -75,6 +76,8 @@ BLOCK_TAG_START = '{%'
BLOCK_TAG_END = '%}'
VARIABLE_TAG_START = '{{'
VARIABLE_TAG_END = '}}'
+COMMENT_TAG_START = '{#'
+COMMENT_TAG_END = '#}'
SINGLE_BRACE_START = '{'
SINGLE_BRACE_END = '}'
@@ -85,8 +88,9 @@ ALLOWED_VARIABLE_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01
UNKNOWN_SOURCE="&lt;unknown source&gt;"
# match a variable or block tag and capture the entire tag, including start/end delimiters
-tag_re = re.compile('(%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
- re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END)))
+tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
+ re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END),
+ re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END)))
# global dictionary of libraries that have been loaded using get_library
libraries = {}
@@ -137,13 +141,14 @@ class StringOrigin(Origin):
return self.source
class Template(object):
- def __init__(self, template_string, origin=None):
+ def __init__(self, template_string, origin=None, name='<Unknown Template>'):
"Compilation stage"
if settings.TEMPLATE_DEBUG and origin == None:
origin = StringOrigin(template_string)
# Could do some crazy stack-frame stuff to record where this string
# came from...
self.nodelist = compile_string(template_string, origin)
+ self.name = name
def __iter__(self):
for node in self.nodelist:
@@ -162,12 +167,12 @@ def compile_string(template_string, origin):
class Token(object):
def __init__(self, token_type, contents):
- "The token_type must be TOKEN_TEXT, TOKEN_VAR or TOKEN_BLOCK"
+ "The token_type must be TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK or TOKEN_COMMENT"
self.token_type, self.contents = token_type, contents
def __str__(self):
return '<%s token: "%s...">' % \
- ({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block'}[self.token_type],
+ ({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block', TOKEN_COMMENT: 'Comment'}[self.token_type],
self.contents[:20].replace('\n', ''))
def split_contents(self):
@@ -190,6 +195,8 @@ class Lexer(object):
token = Token(TOKEN_VAR, token_string[len(VARIABLE_TAG_START):-len(VARIABLE_TAG_END)].strip())
elif token_string.startswith(BLOCK_TAG_START):
token = Token(TOKEN_BLOCK, token_string[len(BLOCK_TAG_START):-len(BLOCK_TAG_END)].strip())
+ elif token_string.startswith(COMMENT_TAG_START):
+ token = Token(TOKEN_COMMENT, '')
else:
token = Token(TOKEN_TEXT, token_string)
return token
@@ -358,7 +365,7 @@ class DebugParser(Parser):
super(DebugParser, self).extend_nodelist(nodelist, node, token)
def unclosed_block_tag(self, parse_until):
- (command, source) = self.command_stack.pop()
+ command, source = self.command_stack.pop()
msg = "Unclosed tag '%s'. Looking for one of: %s " % (command, ', '.join(parse_until))
raise self.source_error( source, msg)
@@ -434,7 +441,7 @@ class TokenParser(object):
while i < len(subject) and subject[i] != subject[p]:
i += 1
if i >= len(subject):
- raise TemplateSyntaxError, "Searching for value. Unexpected end of string in column %d: %s" % subject
+ raise TemplateSyntaxError, "Searching for value. Unexpected end of string in column %d: %s" % (i, subject)
i += 1
res = subject[p:i]
while i < len(subject) and subject[i] in (' ', '\t'):
@@ -531,7 +538,7 @@ class FilterExpression(object):
constant_arg, i18n_arg, var_arg = match.group("constant_arg", "i18n_arg", "var_arg")
if i18n_arg:
args.append((False, _(i18n_arg.replace(r'\"', '"'))))
- elif constant_arg:
+ elif constant_arg is not None:
args.append((False, constant_arg.replace(r'\"', '"')))
elif var_arg:
args.append((True, var_arg))
@@ -548,9 +555,12 @@ class FilterExpression(object):
obj = resolve_variable(self.var, context)
except VariableDoesNotExist:
if ignore_failures:
- return None
+ obj = None
else:
- return settings.TEMPLATE_STRING_IF_INVALID
+ if settings.TEMPLATE_STRING_IF_INVALID:
+ return settings.TEMPLATE_STRING_IF_INVALID
+ else:
+ obj = settings.TEMPLATE_STRING_IF_INVALID
for func, args in self.filters:
arg_vals = []
for lookup, arg in args:
@@ -614,11 +624,7 @@ def resolve_variable(path, context):
(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
"""
- if path == 'False':
- current = False
- elif path == 'True':
- current = True
- elif path[0].isdigit():
+ if path[0].isdigit():
number_type = '.' in path and float or int
try:
current = number_type(path)
@@ -708,9 +714,9 @@ class DebugNodeList(NodeList):
if not hasattr(e, 'source'):
e.source = node.source
raise
- except Exception:
+ except Exception, e:
from sys import exc_info
- wrapped = TemplateSyntaxError('Caught an exception while rendering.')
+ wrapped = TemplateSyntaxError('Caught an exception while rendering: %s' % e)
wrapped.source = node.source
wrapped.exc_info = exc_info()
raise wrapped
@@ -817,7 +823,7 @@ class Library(object):
self.filters[name] = filter_func
return filter_func
else:
- raise InvalidTemplateLibrary, "Unsupported arguments to Library.filter: (%r, %r, %r)", (name, compile_function, has_arg)
+ raise InvalidTemplateLibrary, "Unsupported arguments to Library.filter: (%r, %r)", (name, filter_func)
def filter_function(self, func):
self.filters[func.__name__] = func
diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index 5d56ec0c49..cf1d3d5f6d 100644
--- a/django/template/defaultfilters.py
+++ b/django/template/defaultfilters.py
@@ -15,7 +15,7 @@ register = Library()
def addslashes(value):
"Adds slashes - useful for passing strings to JavaScript, for example."
- return value.replace('"', '\\"').replace("'", "\\'")
+ return value.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'")
def capfirst(value):
"Capitalizes the first character of the value"
@@ -133,7 +133,7 @@ def wordwrap(value, arg):
"""
Wraps words at specified line length
- Argument: number of words to wrap the text at.
+ Argument: number of characters to wrap the text at.
"""
from django.utils.text import wrap
return wrap(str(value), int(arg))
@@ -339,7 +339,7 @@ def date(value, arg=None):
def time(value, arg=None):
"Formats a time according to the given format"
from django.utils.dateformat import time_format
- if not value:
+ if value in (None, ''):
return ''
if arg is None:
arg = settings.TIME_FORMAT
@@ -437,8 +437,8 @@ def pluralize(value, arg='s'):
is used instead. If the provided argument contains a comma, the text before
the comma is used for the singular case.
"""
- if not ',' in arg:
- arg = ',' + arg
+ if not ',' in arg:
+ arg = ',' + arg
bits = arg.split(',')
if len(bits) > 2:
return ''
diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
index 0a4fe33d82..07e579bf9d 100644
--- a/django/template/defaulttags.py
+++ b/django/template/defaulttags.py
@@ -13,14 +13,18 @@ class CommentNode(Node):
return ''
class CycleNode(Node):
- def __init__(self, cyclevars):
+ def __init__(self, cyclevars, variable_name=None):
self.cyclevars = cyclevars
self.cyclevars_len = len(cyclevars)
self.counter = -1
+ self.variable_name = variable_name
def render(self, context):
self.counter += 1
- return self.cyclevars[self.counter % self.cyclevars_len]
+ value = self.cyclevars[self.counter % self.cyclevars_len]
+ if self.variable_name:
+ context[self.variable_name] = value
+ return value
class DebugNode(Node):
def render(self, context):
@@ -86,7 +90,7 @@ class ForNode(Node):
parentloop = {}
context.push()
try:
- values = self.sequence.resolve(context)
+ values = self.sequence.resolve(context, True)
except VariableDoesNotExist:
values = []
if values is None:
@@ -125,6 +129,8 @@ class IfChangedNode(Node):
self._last_seen = None
def render(self, context):
+ if context.has_key('forloop') and context['forloop']['first']:
+ self._last_seen = None
content = self.nodelist.render(context)
if content != self._last_seen:
firstloop = (self._last_seen == None)
@@ -212,13 +218,13 @@ class RegroupNode(Node):
self.var_name = var_name
def render(self, context):
- obj_list = self.target.resolve(context)
- if obj_list == '': # target_var wasn't found in context; fail silently
+ obj_list = self.target.resolve(context, True)
+ if obj_list == None: # target_var wasn't found in context; fail silently
context[self.var_name] = []
return ''
output = [] # list of dictionaries in the format {'grouper': 'key', 'list': [list of contents]}
for obj in obj_list:
- grouper = self.expression.resolve(Context({'var': obj}))
+ grouper = self.expression.resolve(Context({'var': obj}), True)
# TODO: Is this a sensible way to determine equality?
if output and repr(output[-1]['grouper']) == repr(grouper):
output[-1]['list'].append(obj)
@@ -251,7 +257,7 @@ class SsiNode(Node):
output = ''
if self.parsed:
try:
- t = Template(output)
+ t = Template(output, name=self.filepath)
return t.render(context)
except TemplateSyntaxError, e:
if settings.DEBUG:
@@ -385,7 +391,7 @@ def cycle(parser, token):
raise TemplateSyntaxError("Second 'cycle' argument must be 'as'")
cyclevars = [v for v in args[1].split(",") if v] # split and kill blanks
name = args[3]
- node = CycleNode(cyclevars)
+ node = CycleNode(cyclevars, name)
if not hasattr(parser, '_namedCycleNodes'):
parser._namedCycleNodes = {}
diff --git a/django/template/loader.py b/django/template/loader.py
index ebca582ef9..03e6f8d49d 100644
--- a/django/template/loader.py
+++ b/django/template/loader.py
@@ -21,7 +21,7 @@
# installed, because pkg_resources is necessary to read eggs.
from django.core.exceptions import ImproperlyConfigured
-from django.template import Origin, StringOrigin, Template, Context, TemplateDoesNotExist, add_to_builtins
+from django.template import Origin, Template, Context, TemplateDoesNotExist, add_to_builtins
from django.conf import settings
template_source_loaders = None
@@ -76,14 +76,16 @@ def get_template(template_name):
Returns a compiled Template object for the given template name,
handling template inheritance recursively.
"""
- return get_template_from_string(*find_template_source(template_name))
+ source, origin = find_template_source(template_name)
+ template = get_template_from_string(source, origin, template_name)
+ return template
-def get_template_from_string(source, origin=None):
+def get_template_from_string(source, origin=None, name=None):
"""
Returns a compiled Template object for the given template code,
handling template inheritance recursively.
"""
- return Template(source, origin)
+ return Template(source, origin, name)
def render_to_string(template_name, dictionary=None, context_instance=None):
"""
diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py
index e0d9a70a98..e329b1bb36 100644
--- a/django/template/loader_tags.py
+++ b/django/template/loader_tags.py
@@ -1,5 +1,5 @@
from django.template import TemplateSyntaxError, TemplateDoesNotExist, resolve_variable
-from django.template import Library, Context, Node
+from django.template import Library, Node
from django.template.loader import get_template, get_template_from_string, find_template_source
from django.conf import settings
@@ -50,12 +50,14 @@ class ExtendsNode(Node):
if self.parent_name_expr:
error_msg += " Got this from the %r variable." % self.parent_name_expr #TODO nice repr.
raise TemplateSyntaxError, error_msg
+ if hasattr(parent, 'render'):
+ return parent # parent is a Template object
try:
source, origin = find_template_source(parent, self.template_dirs)
except TemplateDoesNotExist:
raise TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent
else:
- return get_template_from_string(source, origin)
+ return get_template_from_string(source, origin, parent)
def render(self, context):
compiled_parent = self.get_parent(context)
@@ -125,7 +127,7 @@ def do_block(parser, token):
if block_name in parser.__loaded_blocks:
raise TemplateSyntaxError, "'%s' tag with name '%s' appears more than once" % (bits[0], block_name)
parser.__loaded_blocks.append(block_name)
- except AttributeError: # parser._loaded_blocks isn't a list yet
+ except AttributeError: # parser.__loaded_blocks isn't a list yet
parser.__loaded_blocks = [block_name]
nodelist = parser.parse(('endblock',))
parser.delete_first_token()
@@ -137,8 +139,9 @@ def do_extends(parser, token):
This tag may be used in two ways: ``{% extends "base" %}`` (with quotes)
uses the literal value "base" as the name of the parent template to extend,
- or ``{% extends variable %}`` uses the value of ``variable`` as the name
- of the parent template to extend.
+ or ``{% extends variable %}`` uses the value of ``variable`` as either the
+ name of the parent template to extend (if it evaluates to a string,) or as
+ the parent tempate itelf (if it evaluates to a Template object).
"""
bits = token.contents.split()
if len(bits) != 2:
diff --git a/django/template/loaders/filesystem.py b/django/template/loaders/filesystem.py
index 0c94021fb8..d01f54c5fe 100644
--- a/django/template/loaders/filesystem.py
+++ b/django/template/loaders/filesystem.py
@@ -17,7 +17,7 @@ def load_template_source(template_name, template_dirs=None):
return (open(filepath).read(), filepath)
except IOError:
tried.append(filepath)
- if template_dirs:
+ if tried:
error_msg = "Tried %s" % tried
else:
error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py
index 6718a0fbac..bf6497f9aa 100644
--- a/django/templatetags/i18n.py
+++ b/django/templatetags/i18n.py
@@ -1,8 +1,7 @@
-from django.template import Node, NodeList, Template, Context, resolve_variable
+from django.template import Node, resolve_variable
from django.template import TemplateSyntaxError, TokenParser, Library
-from django.template import TOKEN_BLOCK, TOKEN_TEXT, TOKEN_VAR
+from django.template import TOKEN_TEXT, TOKEN_VAR
from django.utils import translation
-import re, sys
register = Library()
@@ -228,7 +227,7 @@ def do_block_translate(parser, token):
break
if countervar and counter:
if token.contents.strip() != 'plural':
- raise TemplateSyntaxError, "'blocktrans' doesn't allow other block tags inside it" % tag
+ raise TemplateSyntaxError, "'blocktrans' doesn't allow other block tags inside it"
while parser.tokens:
token = parser.next_token()
if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
diff --git a/tests/othertests/__init__.py b/django/test/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/tests/othertests/__init__.py
+++ b/django/test/__init__.py
diff --git a/django/test/client.py b/django/test/client.py
new file mode 100644
index 0000000000..6e0b443f83
--- /dev/null
+++ b/django/test/client.py
@@ -0,0 +1,216 @@
+from cStringIO import StringIO
+from django.core.handlers.base import BaseHandler
+from django.core.handlers.wsgi import WSGIRequest
+from django.dispatch import dispatcher
+from django.http import urlencode, SimpleCookie
+from django.test import signals
+from django.utils.functional import curry
+
+class ClientHandler(BaseHandler):
+ """
+ A HTTP Handler that can be used for testing purposes.
+ Uses the WSGI interface to compose requests, but returns
+ the raw HttpResponse object
+ """
+ def __call__(self, environ):
+ from django.conf import settings
+ from django.core import signals
+
+ # Set up middleware if needed. We couldn't do this earlier, because
+ # settings weren't available.
+ if self._request_middleware is None:
+ self.load_middleware()
+
+ dispatcher.send(signal=signals.request_started)
+ try:
+ request = WSGIRequest(environ)
+ response = self.get_response(request)
+
+ # Apply response middleware
+ for middleware_method in self._response_middleware:
+ response = middleware_method(request, response)
+
+ finally:
+ dispatcher.send(signal=signals.request_finished)
+
+ return response
+
+def store_rendered_templates(store, signal, sender, template, context):
+ "A utility function for storing templates and contexts that are rendered"
+ store.setdefault('template',[]).append(template)
+ store.setdefault('context',[]).append(context)
+
+def encode_multipart(boundary, data):
+ """
+ A simple method for encoding multipart POST data from a dictionary of
+ form values.
+
+ The key will be used as the form data name; the value will be transmitted
+ as content. If the value is a file, the contents of the file will be sent
+ as an application/octet-stream; otherwise, str(value) will be sent.
+ """
+ lines = []
+ for (key, value) in data.items():
+ if isinstance(value, file):
+ lines.extend([
+ '--' + boundary,
+ 'Content-Disposition: form-data; name="%s"' % key,
+ '',
+ '--' + boundary,
+ 'Content-Disposition: form-data; name="%s_file"; filename="%s"' % (key, value.name),
+ 'Content-Type: application/octet-stream',
+ '',
+ value.read()
+ ])
+ else:
+ lines.extend([
+ '--' + boundary,
+ 'Content-Disposition: form-data; name="%s"' % key,
+ '',
+ str(value)
+ ])
+
+ lines.extend([
+ '--' + boundary + '--',
+ '',
+ ])
+ return '\r\n'.join(lines)
+
+class Client:
+ """
+ A class that can act as a client for testing purposes.
+
+ It allows the user to compose GET and POST requests, and
+ obtain the response that the server gave to those requests.
+ The server Response objects are annotated with the details
+ of the contexts and templates that were rendered during the
+ process of serving the request.
+
+ Client objects are stateful - they will retain cookie (and
+ thus session) details for the lifetime of the Client instance.
+
+ This is not intended as a replacement for Twill/Selenium or
+ the like - it is here to allow testing against the
+ contexts and templates produced by a view, rather than the
+ HTML rendered to the end-user.
+ """
+ def __init__(self, **defaults):
+ self.handler = ClientHandler()
+ self.defaults = defaults
+ self.cookie = SimpleCookie()
+
+ def request(self, **request):
+ """
+ The master request method. Composes the environment dictionary
+ and passes to the handler, returning the result of the handler.
+ Assumes defaults for the query environment, which can be overridden
+ using the arguments to the request.
+ """
+
+ environ = {
+ 'HTTP_COOKIE': self.cookie,
+ 'PATH_INFO': '/',
+ 'QUERY_STRING': '',
+ 'REQUEST_METHOD': 'GET',
+ 'SCRIPT_NAME': None,
+ 'SERVER_NAME': 'testserver',
+ 'SERVER_PORT': 80,
+ 'SERVER_PROTOCOL': 'HTTP/1.1',
+ }
+ environ.update(self.defaults)
+ environ.update(request)
+
+ # Curry a data dictionary into an instance of
+ # the template renderer callback function
+ data = {}
+ on_template_render = curry(store_rendered_templates, data)
+ dispatcher.connect(on_template_render, signal=signals.template_rendered)
+
+ response = self.handler(environ)
+
+ # Add any rendered template detail to the response
+ # If there was only one template rendered (the most likely case),
+ # flatten the list to a single element
+ for detail in ('template', 'context'):
+ if data.get(detail):
+ if len(data[detail]) == 1:
+ setattr(response, detail, data[detail][0]);
+ else:
+ setattr(response, detail, data[detail])
+ else:
+ setattr(response, detail, None)
+
+ if response.cookies:
+ self.cookie.update(response.cookies)
+
+ return response
+
+ def get(self, path, data={}, **extra):
+ "Request a response from the server using GET."
+ r = {
+ 'CONTENT_LENGTH': None,
+ 'CONTENT_TYPE': 'text/html; charset=utf-8',
+ 'PATH_INFO': path,
+ 'QUERY_STRING': urlencode(data),
+ 'REQUEST_METHOD': 'GET',
+ }
+ r.update(extra)
+
+ return self.request(**r)
+
+ def post(self, path, data={}, **extra):
+ "Request a response from the server using POST."
+
+ BOUNDARY = 'BoUnDaRyStRiNg'
+
+ encoded = encode_multipart(BOUNDARY, data)
+ stream = StringIO(encoded)
+ r = {
+ 'CONTENT_LENGTH': len(encoded),
+ 'CONTENT_TYPE': 'multipart/form-data; boundary=%s' % BOUNDARY,
+ 'PATH_INFO': path,
+ 'REQUEST_METHOD': 'POST',
+ 'wsgi.input': stream,
+ }
+ r.update(extra)
+
+ return self.request(**r)
+
+ def login(self, path, username, password, **extra):
+ """
+ A specialized sequence of GET and POST to log into a view that
+ is protected by a @login_required access decorator.
+
+ path should be the URL of the page that is login protected.
+
+ Returns the response from GETting the requested URL after
+ login is complete. Returns False if login process failed.
+ """
+ # First, GET the page that is login protected.
+ # This page will redirect to the login page.
+ response = self.get(path)
+ if response.status_code != 302:
+ return False
+
+ login_path, data = response['Location'].split('?')
+ next = data.split('=')[1]
+
+ # Second, GET the login page; required to set up cookies
+ response = self.get(login_path, **extra)
+ if response.status_code != 200:
+ return False
+
+ # Last, POST the login data.
+ form_data = {
+ 'username': username,
+ 'password': password,
+ 'next' : next,
+ }
+ response = self.post(login_path, data=form_data, **extra)
+
+ # Login page should 302 redirect to the originally requested page
+ if response.status_code != 302 or response['Location'] != path:
+ return False
+
+ # Since we are logged in, request the actual page again
+ return self.get(path)
diff --git a/tests/doctest.py b/django/test/doctest.py
index df7aa978d3..3b364f0a75 100644
--- a/tests/doctest.py
+++ b/django/test/doctest.py
@@ -1319,13 +1319,16 @@ class DocTestRunner:
__LINECACHE_FILENAME_RE = re.compile(r'<doctest '
r'(?P<name>[\w\.]+)'
r'\[(?P<examplenum>\d+)\]>$')
- def __patched_linecache_getlines(self, filename):
+ def __patched_linecache_getlines(self, filename, module_globals=None):
m = self.__LINECACHE_FILENAME_RE.match(filename)
if m and m.group('name') == self.test.name:
example = self.test.examples[int(m.group('examplenum'))]
return example.source.splitlines(True)
else:
- return self.save_linecache_getlines(filename)
+ if sys.version_info < (2, 5, 0):
+ return self.save_linecache_getlines(filename)
+ else:
+ return self.save_linecache_getlines(filename, module_globals)
def run(self, test, compileflags=None, out=None, clear_globs=True):
"""
@@ -2104,7 +2107,7 @@ def set_unittest_reportflags(flags):
class DocTestCase(unittest.TestCase):
def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
- checker=None):
+ checker=None, runner=DocTestRunner):
unittest.TestCase.__init__(self)
self._dt_optionflags = optionflags
@@ -2112,6 +2115,7 @@ class DocTestCase(unittest.TestCase):
self._dt_test = test
self._dt_setUp = setUp
self._dt_tearDown = tearDown
+ self._dt_runner = runner
def setUp(self):
test = self._dt_test
@@ -2138,8 +2142,8 @@ class DocTestCase(unittest.TestCase):
# so add the default reporting flags
optionflags |= _unittest_reportflags
- runner = DocTestRunner(optionflags=optionflags,
- checker=self._dt_checker, verbose=False)
+ runner = self._dt_runner(optionflags=optionflags,
+ checker=self._dt_checker, verbose=False)
try:
runner.DIVIDER = "-"*70
@@ -2248,7 +2252,7 @@ class DocTestCase(unittest.TestCase):
return "Doctest: " + self._dt_test.name
def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None,
- **options):
+ test_class=DocTestCase, **options):
"""
Convert doctest tests for a module to a unittest test suite.
@@ -2306,7 +2310,7 @@ def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None,
if filename[-4:] in (".pyc", ".pyo"):
filename = filename[:-1]
test.filename = filename
- suite.addTest(DocTestCase(test, **options))
+ suite.addTest(test_class(test, **options))
return suite
diff --git a/django/test/signals.py b/django/test/signals.py
new file mode 100644
index 0000000000..40748ff4fe
--- /dev/null
+++ b/django/test/signals.py
@@ -0,0 +1 @@
+template_rendered = object() \ No newline at end of file
diff --git a/django/test/simple.py b/django/test/simple.py
new file mode 100644
index 0000000000..628fa464d2
--- /dev/null
+++ b/django/test/simple.py
@@ -0,0 +1,85 @@
+import unittest, doctest
+from django.conf import settings
+from django.core import management
+from django.test.utils import setup_test_environment, teardown_test_environment
+from django.test.utils import create_test_db, destroy_test_db
+from django.test.testcases import OutputChecker, DocTestRunner
+
+# The module name for tests outside models.py
+TEST_MODULE = 'tests'
+
+doctestOutputChecker = OutputChecker()
+
+def build_suite(app_module):
+ "Create a complete Django test suite for the provided application module"
+ suite = unittest.TestSuite()
+
+ # Load unit and doctests in the models.py file
+ suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(app_module))
+ try:
+ suite.addTest(doctest.DocTestSuite(app_module,
+ checker=doctestOutputChecker,
+ runner=DocTestRunner))
+ except ValueError:
+ # No doc tests in models.py
+ pass
+
+ # Check to see if a separate 'tests' module exists parallel to the
+ # models module
+ try:
+ app_path = app_module.__name__.split('.')[:-1]
+ test_module = __import__('.'.join(app_path + [TEST_MODULE]), [], [], TEST_MODULE)
+
+ suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module))
+ try:
+ suite.addTest(doctest.DocTestSuite(test_module,
+ checker=doctestOutputChecker,
+ runner=DocTestRunner))
+ except ValueError:
+ # No doc tests in tests.py
+ pass
+ except ImportError, e:
+ # Couldn't import tests.py. Was it due to a missing file, or
+ # due to an import error in a tests.py that actually exists?
+ import os.path
+ from imp import find_module
+ try:
+ mod = find_module(TEST_MODULE, [os.path.dirname(app_module.__file__)])
+ except ImportError:
+ # 'tests' module doesn't exist. Move on.
+ pass
+ else:
+ # The module exists, so there must be an import error in the
+ # test module itself. We don't need the module; close the file
+ # handle returned by find_module.
+ mod[0].close()
+ raise
+
+ return suite
+
+def run_tests(module_list, verbosity=1, extra_tests=[]):
+ """
+ Run the unit tests for all the modules in the provided list.
+ This testrunner will search each of the modules in the provided list,
+ looking for doctests and unittests in models.py or tests.py within
+ the module. A list of 'extra' tests may also be provided; these tests
+ will be added to the test suite.
+ """
+ setup_test_environment()
+
+ settings.DEBUG = False
+ suite = unittest.TestSuite()
+
+ for module in module_list:
+ suite.addTest(build_suite(module))
+
+ for test in extra_tests:
+ suite.addTest(test)
+
+ old_name = settings.DATABASE_NAME
+ create_test_db(verbosity)
+ management.syncdb(verbosity, interactive=False)
+ unittest.TextTestRunner(verbosity=verbosity).run(suite)
+ destroy_test_db(old_name, verbosity)
+
+ teardown_test_environment()
diff --git a/django/test/testcases.py b/django/test/testcases.py
new file mode 100644
index 0000000000..1cfef6f19e
--- /dev/null
+++ b/django/test/testcases.py
@@ -0,0 +1,30 @@
+import re, doctest, unittest
+from django.db import transaction
+
+normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)
+
+class OutputChecker(doctest.OutputChecker):
+ def check_output(self, want, got, optionflags):
+ ok = doctest.OutputChecker.check_output(self, want, got, optionflags)
+
+ # Doctest does an exact string comparison of output, which means long
+ # integers aren't equal to normal integers ("22L" vs. "22"). The
+ # following code normalizes long integers so that they equal normal
+ # integers.
+ if not ok:
+ return normalize_long_ints(want) == normalize_long_ints(got)
+ return ok
+
+class DocTestRunner(doctest.DocTestRunner):
+ def __init__(self, *args, **kwargs):
+ doctest.DocTestRunner.__init__(self, *args, **kwargs)
+ self.optionflags = doctest.ELLIPSIS
+
+ def report_unexpected_exception(self, out, test, example, exc_info):
+ doctest.DocTestRunner.report_unexpected_exception(self,out,test,example,exc_info)
+
+ # Rollback, in case of database errors. Otherwise they'd have
+ # side effects on other tests.
+ from django.db import transaction
+ transaction.rollback_unless_managed()
+
diff --git a/django/test/utils.py b/django/test/utils.py
new file mode 100644
index 0000000000..039a6dd7a2
--- /dev/null
+++ b/django/test/utils.py
@@ -0,0 +1,107 @@
+import sys, time
+from django.conf import settings
+from django.db import connection, transaction, backend
+from django.dispatch import dispatcher
+from django.test import signals
+from django.template import Template
+
+# The prefix to put on the default database name when creating
+# the test database.
+TEST_DATABASE_PREFIX = 'test_'
+
+def instrumented_test_render(self, context):
+ """An instrumented Template render method, providing a signal
+ that can be intercepted by the test system Client
+
+ """
+ dispatcher.send(signal=signals.template_rendered, sender=self, template=self, context=context)
+ return self.nodelist.render(context)
+
+def setup_test_environment():
+ """Perform any global pre-test setup. This involves:
+
+ - Installing the instrumented test renderer
+
+ """
+ Template.original_render = Template.render
+ Template.render = instrumented_test_render
+
+def teardown_test_environment():
+ """Perform any global post-test teardown. This involves:
+
+ - Restoring the original test renderer
+
+ """
+ Template.render = Template.original_render
+ del Template.original_render
+
+def _set_autocommit(connection):
+ "Make sure a connection is in autocommit mode."
+ if hasattr(connection.connection, "autocommit"):
+ connection.connection.autocommit(True)
+ elif hasattr(connection.connection, "set_isolation_level"):
+ connection.connection.set_isolation_level(0)
+
+def create_test_db(verbosity=1, autoclobber=False):
+ if verbosity >= 1:
+ print "Creating test database..."
+ # If we're using SQLite, it's more convenient to test against an
+ # in-memory database.
+ if settings.DATABASE_ENGINE == "sqlite3":
+ TEST_DATABASE_NAME = ":memory:"
+ else:
+ if settings.TEST_DATABASE_NAME:
+ TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME
+ else:
+ TEST_DATABASE_NAME = TEST_DATABASE_PREFIX + settings.DATABASE_NAME
+
+ # Create the test database and connect to it. We need to autocommit
+ # if the database supports it because PostgreSQL doesn't allow
+ # CREATE/DROP DATABASE statements within transactions.
+ cursor = connection.cursor()
+ _set_autocommit(connection)
+ try:
+ cursor.execute("CREATE DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME))
+ except Exception, e:
+ sys.stderr.write("Got an error creating the test database: %s\n" % e)
+ if not autoclobber:
+ confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME)
+ if autoclobber or confirm == 'yes':
+ try:
+ if verbosity >= 1:
+ print "Destroying old test database..."
+ cursor.execute("DROP DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME))
+ if verbosity >= 1:
+ print "Creating test database..."
+ cursor.execute("CREATE DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME))
+ except Exception, e:
+ sys.stderr.write("Got an error recreating the test database: %s\n" % e)
+ sys.exit(2)
+ else:
+ print "Tests cancelled."
+ sys.exit(1)
+
+ connection.close()
+ settings.DATABASE_NAME = TEST_DATABASE_NAME
+
+ # Get a cursor (even though we don't need one yet). This has
+ # the side effect of initializing the test database.
+ cursor = connection.cursor()
+
+def destroy_test_db(old_database_name, verbosity=1):
+ # Unless we're using SQLite, remove the test database to clean up after
+ # ourselves. Connect to the previous database (not the test database)
+ # to do so, because it's not allowed to delete a database while being
+ # connected to it.
+ if verbosity >= 1:
+ print "Destroying test database..."
+ connection.close()
+ TEST_DATABASE_NAME = settings.DATABASE_NAME
+ settings.DATABASE_NAME = old_database_name
+
+ if settings.DATABASE_ENGINE != "sqlite3":
+ cursor = connection.cursor()
+ _set_autocommit(connection)
+ time.sleep(1) # To avoid "database is being accessed by other users" errors.
+ cursor.execute("DROP DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME))
+ connection.close()
diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py
index 6363af7835..e05b7fafe1 100644
--- a/django/utils/autoreload.py
+++ b/django/utils/autoreload.py
@@ -35,6 +35,14 @@ try:
except ImportError:
import dummy_thread as thread
+# This import does nothing, but it's necessary to avoid some race conditions
+# in the threading module. See http://code.djangoproject.com/ticket/2330 .
+try:
+ import threading
+except ImportError:
+ pass
+
+
RUN_RELOADER = True
def reloader_thread():
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index 632e804f26..cecb4da170 100644
--- a/django/utils/datastructures.py
+++ b/django/utils/datastructures.py
@@ -14,6 +14,9 @@ class MergeDict(object):
pass
raise KeyError
+ def __contains__(self, key):
+ return self.has_key(key)
+
def get(self, key, default):
try:
return self[key]
@@ -187,17 +190,23 @@ class MultiValueDict(dict):
"Returns a copy of this object."
return self.__deepcopy__()
- def update(self, other_dict):
- "update() extends rather than replaces existing key lists."
- if isinstance(other_dict, MultiValueDict):
- for key, value_list in other_dict.lists():
- self.setlistdefault(key, []).extend(value_list)
- else:
- try:
- for key, value in other_dict.items():
- self.setlistdefault(key, []).append(value)
- except TypeError:
- raise ValueError, "MultiValueDict.update() takes either a MultiValueDict or dictionary"
+ def update(self, *args, **kwargs):
+ "update() extends rather than replaces existing key lists. Also accepts keyword args."
+ if len(args) > 1:
+ raise TypeError, "update expected at most 1 arguments, got %d", len(args)
+ if args:
+ other_dict = args[0]
+ if isinstance(other_dict, MultiValueDict):
+ for key, value_list in other_dict.lists():
+ self.setlistdefault(key, []).extend(value_list)
+ else:
+ try:
+ for key, value in other_dict.items():
+ self.setlistdefault(key, []).append(value)
+ except TypeError:
+ raise ValueError, "MultiValueDict.update() takes either a MultiValueDict or dictionary"
+ for key, value in kwargs.iteritems():
+ self.setlistdefault(key, []).append(value)
class DotExpandedDict(dict):
"""
diff --git a/django/utils/functional.py b/django/utils/functional.py
index d1514d5728..e3c0a3c76b 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -1,6 +1,6 @@
-def curry(*args, **kwargs):
+def curry(_curried_func, *args, **kwargs):
def _curried(*moreargs, **morekwargs):
- return args[0](*(args[1:]+moreargs), **dict(kwargs.items() + morekwargs.items()))
+ return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
return _curried
class Promise:
diff --git a/django/utils/itercompat.py b/django/utils/itercompat.py
new file mode 100644
index 0000000000..370988bedb
--- /dev/null
+++ b/django/utils/itercompat.py
@@ -0,0 +1,31 @@
+"""
+Providing iterator functions that are not in all version of Python we support.
+Where possible, we try to use the system-native version and only fall back to
+these implementations if necessary.
+"""
+
+import itertools
+
+def compat_tee(iterable):
+ """Return two independent iterators from a single iterable.
+
+ Based on http://www.python.org/doc/2.3.5/lib/itertools-example.html
+ """
+ # Note: Using a dictionary and a list as the default arguments here is
+ # deliberate and safe in this instance.
+ def gen(next, data={}, cnt=[0]):
+ dpop = data.pop
+ for i in itertools.count():
+ if i == cnt[0]:
+ item = data[i] = next()
+ cnt[0] += 1
+ else:
+ item = dpop(i)
+ yield item
+ next = iter(iterable).next
+ return gen(next), gen(next)
+
+if hasattr(itertools, 'tee'):
+ tee = itertools.tee
+else:
+ tee = compat_tee
diff --git a/django/utils/simplejson/scanner.py b/django/utils/simplejson/scanner.py
index c2e9b6eb89..b9244cfed1 100644
--- a/django/utils/simplejson/scanner.py
+++ b/django/utils/simplejson/scanner.py
@@ -3,12 +3,11 @@ Iterator based sre token scanner
"""
import sre_parse, sre_compile, sre_constants
from sre_constants import BRANCH, SUBPATTERN
-from sre import VERBOSE, MULTILINE, DOTALL
import re
__all__ = ['Scanner', 'pattern']
-FLAGS = (VERBOSE | MULTILINE | DOTALL)
+FLAGS = (re.VERBOSE | re.MULTILINE | re.DOTALL)
class Scanner(object):
def __init__(self, lexicon, flags=FLAGS):
self.actions = [None]
diff --git a/django/utils/termcolors.py b/django/utils/termcolors.py
index 3ce1d5bb6b..17a600f899 100644
--- a/django/utils/termcolors.py
+++ b/django/utils/termcolors.py
@@ -2,8 +2,6 @@
termcolors.py
"""
-import types
-
color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white')
foreground = dict([(color_names[x], '3%s' % x) for x in range(8)])
background = dict([(color_names[x], '4%s' % x) for x in range(8)])
diff --git a/django/utils/text.py b/django/utils/text.py
index 7df9bc03b7..9e7bb3b6c4 100644
--- a/django/utils/text.py
+++ b/django/utils/text.py
@@ -94,7 +94,8 @@ def compress_string(s):
return zbuf.getvalue()
ustring_re = re.compile(u"([\u0080-\uffff])")
-def javascript_quote(s):
+
+def javascript_quote(s, quote_double_quotes=False):
def fix(match):
return r"\u%04x" % ord(match.group(1))
@@ -104,9 +105,12 @@ def javascript_quote(s):
elif type(s) != unicode:
raise TypeError, s
s = s.replace('\\', '\\\\')
+ s = s.replace('\r', '\\r')
s = s.replace('\n', '\\n')
s = s.replace('\t', '\\t')
s = s.replace("'", "\\'")
+ if quote_double_quotes:
+ s = s.replace('"', '&quot;')
return str(ustring_re.sub(fix, s))
smart_split_re = re.compile('("(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'|[^\\s]+)')
diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py
index ed25cae05b..75ad573357 100644
--- a/django/utils/translation/trans_null.py
+++ b/django/utils/translation/trans_null.py
@@ -17,3 +17,14 @@ get_language = lambda: settings.LANGUAGE_CODE
get_language_bidi = lambda: settings.LANGUAGE_CODE in settings.LANGUAGES_BIDI
get_date_formats = lambda: (settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT)
get_partial_date_formats = lambda: (settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT)
+check_for_language = lambda x: True
+
+def to_locale(language):
+ p = language.find('-')
+ if p >= 0:
+ return language[:p].lower()+'_'+language[p+1:].upper()
+ else:
+ return language.lower()
+
+def get_language_from_request(request):
+ return settings.LANGUAGE_CODE
diff --git a/django/views/debug.py b/django/views/debug.py
index 6cbbde987b..a7f44d17b3 100644
--- a/django/views/debug.py
+++ b/django/views/debug.py
@@ -3,10 +3,8 @@ from django.template import Template, Context, TemplateDoesNotExist
from django.utils.html import escape
from django.http import HttpResponseServerError, HttpResponseNotFound
import os, re
-from itertools import count, izip
-from os.path import dirname, join as pathjoin
-HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD')
+HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD|PROFANITIES_LIST')
def linebreak_iter(template_source):
yield 0
@@ -117,14 +115,14 @@ def technical_500_response(request, exc_type, exc_value, tb):
'function': '?',
'lineno': '?',
}]
- t = Template(TECHNICAL_500_TEMPLATE)
+ t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template')
c = Context({
'exception_type': exc_type.__name__,
'exception_value': exc_value,
'frames': frames,
'lastframe': frames[-1],
'request': request,
- 'request_protocol': os.environ.get("HTTPS") == "on" and "https" or "http",
+ 'request_protocol': request.is_secure() and "https" or "http",
'settings': get_safe_settings(),
'template_info': template_info,
'template_does_not_exist': template_does_not_exist,
@@ -143,20 +141,20 @@ def technical_404_response(request, exception):
# tried exists but is an empty list. The URLconf must've been empty.
return empty_urlconf(request)
- t = Template(TECHNICAL_404_TEMPLATE)
+ t = Template(TECHNICAL_404_TEMPLATE, name='Technical 404 template')
c = Context({
'root_urlconf': settings.ROOT_URLCONF,
'urlpatterns': tried,
'reason': str(exception),
'request': request,
- 'request_protocol': os.environ.get("HTTPS") == "on" and "https" or "http",
+ 'request_protocol': request.is_secure() and "https" or "http",
'settings': get_safe_settings(),
})
return HttpResponseNotFound(t.render(c), mimetype='text/html')
def empty_urlconf(request):
"Create an empty URLconf 404 error response."
- t = Template(EMPTY_URLCONF_TEMPLATE)
+ t = Template(EMPTY_URLCONF_TEMPLATE, name='Empty URLConf template')
c = Context({
'project_name': settings.SETTINGS_MODULE.split('.')[0]
})
@@ -191,7 +189,7 @@ TECHNICAL_500_TEMPLATE = """
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="robots" content="NONE,NOARCHIVE" />
- <title>{{ exception_type }} at {{ request.path }}</title>
+ <title>{{ exception_type }} at {{ request.path|escape }}</title>
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }
@@ -294,7 +292,7 @@ TECHNICAL_500_TEMPLATE = """
<body>
<div id="summary">
- <h1>{{ exception_type }} at {{ request.path }}</h1>
+ <h1>{{ exception_type }} at {{ request.path|escape }}</h1>
<h2>{{ exception_value|escape }}</h2>
<table class="meta">
<tr>
@@ -303,7 +301,7 @@ TECHNICAL_500_TEMPLATE = """
</tr>
<tr>
<th>Request URL:</th>
- <td>{{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path }}</td>
+ <td>{{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path|escape }}</td>
</tr>
<tr>
<th>Exception Type:</th>
@@ -311,7 +309,7 @@ TECHNICAL_500_TEMPLATE = """
</tr>
<tr>
<th>Exception Value:</th>
- <td>{{ exception_value }}</td>
+ <td>{{ exception_value|escape }}</td>
</tr>
<tr>
<th>Exception Location:</th>
@@ -414,7 +412,7 @@ Traceback (most recent call last):<br/>
&nbsp;&nbsp;{{ frame.lineno }}. {{ frame.context_line|escape }}<br/>
{% endif %}
{% endfor %}<br/>
-&nbsp;&nbsp;{{ exception_type }} at {{ request.path }}<br/>
+&nbsp;&nbsp;{{ exception_type }} at {{ request.path|escape }}<br/>
&nbsp;&nbsp;{{ exception_value|escape }}</code>
</td>
</tr>
@@ -548,7 +546,7 @@ TECHNICAL_404_TEMPLATE = """
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <title>Page not found at {{ request.path }}</title>
+ <title>Page not found at {{ request.path|escape }}</title>
<meta name="robots" content="NONE,NOARCHIVE" />
<style type="text/css">
html * { padding:0; margin:0; }
@@ -578,7 +576,7 @@ TECHNICAL_404_TEMPLATE = """
</tr>
<tr>
<th>Request URL:</th>
- <td>{{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path }}</td>
+ <td>{{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path|escape }}</td>
</tr>
</table>
</div>
@@ -593,7 +591,7 @@ TECHNICAL_404_TEMPLATE = """
<li>{{ pattern|escape }}</li>
{% endfor %}
</ol>
- <p>The current URL, <code>{{ request.path }}</code>, didn't match any of these.</p>
+ <p>The current URL, <code>{{ request.path|escape }}</code>, didn't match any of these.</p>
{% else %}
<p>{{ reason|escape }}</p>
{% endif %}
diff --git a/django/views/decorators/cache.py b/django/views/decorators/cache.py
index 5467ff501e..b04cc2340b 100644
--- a/django/views/decorators/cache.py
+++ b/django/views/decorators/cache.py
@@ -10,7 +10,6 @@ example, as that is unique across a Django project.
Additionally, all headers from the response's Vary header will be taken into
account on caching -- just like the middleware does.
"""
-import re
from django.utils.decorators import decorator_from_middleware
from django.utils.cache import patch_cache_control, add_never_cache_headers
diff --git a/django/views/generic/create_update.py b/django/views/generic/create_update.py
index b5fdd3e4cc..3a03fa59e4 100644
--- a/django/views/generic/create_update.py
+++ b/django/views/generic/create_update.py
@@ -4,9 +4,9 @@ from django import forms
from django.db.models import FileField
from django.contrib.auth.views import redirect_to_login
from django.template import RequestContext
-from django.core.paginator import ObjectPaginator, InvalidPage
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
+from django.utils.translation import gettext
def create_object(request, model, template_name=None,
template_loader=loader, extra_context=None, post_save_redirect=None,
@@ -20,7 +20,7 @@ def create_object(request, model, template_name=None,
the form wrapper for the object
"""
if extra_context is None: extra_context = {}
- if login_required and request.user.is_anonymous():
+ if login_required and not request.user.is_authenticated():
return redirect_to_login(request.path)
manipulator = model.AddManipulator(follow=follow)
@@ -39,8 +39,8 @@ def create_object(request, model, template_name=None,
# No errors -- this means we can save the data!
new_object = manipulator.save(new_data)
- if not request.user.is_anonymous():
- request.user.message_set.create(message="The %s was created successfully." % model._meta.verbose_name)
+ if request.user.is_authenticated():
+ request.user.message_set.create(message=gettext("The %(verbose_name)s was created successfully.") % {"verbose_name": model._meta.verbose_name})
# Redirect to the new object: first by trying post_save_redirect,
# then by obj.get_absolute_url; fail if neither works.
@@ -86,7 +86,7 @@ def update_object(request, model, object_id=None, slug=None,
the original object being edited
"""
if extra_context is None: extra_context = {}
- if login_required and request.user.is_anonymous():
+ if login_required and not request.user.is_authenticated():
return redirect_to_login(request.path)
# Look up the object to be edited
@@ -102,7 +102,7 @@ def update_object(request, model, object_id=None, slug=None,
except ObjectDoesNotExist:
raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
- manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.name), follow=follow)
+ manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.attname), follow=follow)
if request.POST:
new_data = request.POST.copy()
@@ -113,8 +113,8 @@ def update_object(request, model, object_id=None, slug=None,
if not errors:
object = manipulator.save(new_data)
- if not request.user.is_anonymous():
- request.user.message_set.create(message="The %s was updated successfully." % model._meta.verbose_name)
+ if request.user.is_authenticated():
+ request.user.message_set.create(message=gettext("The %(verbose_name)s was updated successfully.") % {"verbose_name": model._meta.verbose_name})
# Do a post-after-redirect so that reload works, etc.
if post_save_redirect:
@@ -142,7 +142,7 @@ def update_object(request, model, object_id=None, slug=None,
else:
c[key] = value
response = HttpResponse(t.render(c))
- populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
+ populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
return response
def delete_object(request, model, post_delete_redirect,
@@ -162,7 +162,7 @@ def delete_object(request, model, post_delete_redirect,
the original object being deleted
"""
if extra_context is None: extra_context = {}
- if login_required and request.user.is_anonymous():
+ if login_required and not request.user.is_authenticated():
return redirect_to_login(request.path)
# Look up the object to be edited
@@ -180,8 +180,8 @@ def delete_object(request, model, post_delete_redirect,
if request.method == 'POST':
object.delete()
- if not request.user.is_anonymous():
- request.user.message_set.create(message="The %s was deleted." % model._meta.verbose_name)
+ if request.user.is_authenticated():
+ request.user.message_set.create(message=gettext("The %(verbose_name)s was deleted.") % {"verbose_name": model._meta.verbose_name})
return HttpResponseRedirect(post_delete_redirect)
else:
if not template_name:
@@ -196,5 +196,5 @@ def delete_object(request, model, post_delete_redirect,
else:
c[key] = value
response = HttpResponse(t.render(c))
- populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
+ populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
return response
diff --git a/django/views/generic/date_based.py b/django/views/generic/date_based.py
index 7084cdfe5e..d13c0293be 100644
--- a/django/views/generic/date_based.py
+++ b/django/views/generic/date_based.py
@@ -1,13 +1,14 @@
from django.template import loader, RequestContext
from django.core.exceptions import ObjectDoesNotExist
from django.core.xheaders import populate_xheaders
+from django.db.models.fields import DateTimeField
from django.http import Http404, HttpResponse
import datetime, time
def archive_index(request, queryset, date_field, num_latest=15,
template_name=None, template_loader=loader,
extra_context=None, allow_empty=False, context_processors=None,
- mimetype=None):
+ mimetype=None, allow_future=False):
"""
Generic top-level archive of date-based objects.
@@ -20,7 +21,8 @@ def archive_index(request, queryset, date_field, num_latest=15,
"""
if extra_context is None: extra_context = {}
model = queryset.model
- queryset = queryset.filter(**{'%s__lte' % date_field: datetime.datetime.now()})
+ if not allow_future:
+ queryset = queryset.filter(**{'%s__lte' % date_field: datetime.datetime.now()})
date_list = queryset.dates(date_field, 'year')[::-1]
if not date_list and not allow_empty:
raise Http404, "No %s available" % model._meta.verbose_name
@@ -47,7 +49,7 @@ def archive_index(request, queryset, date_field, num_latest=15,
def archive_year(request, year, queryset, date_field, template_name=None,
template_loader=loader, extra_context=None, allow_empty=False,
context_processors=None, template_object_name='object', mimetype=None,
- make_object_list=False):
+ make_object_list=False, allow_future=False):
"""
Generic yearly archive view.
@@ -67,8 +69,8 @@ def archive_year(request, year, queryset, date_field, template_name=None,
lookup_kwargs = {'%s__year' % date_field: year}
- # Only bother to check current date if the year isn't in the past.
- if int(year) >= now.year:
+ # Only bother to check current date if the year isn't in the past and future objects aren't requested.
+ if int(year) >= now.year and not allow_future:
lookup_kwargs['%s__lte' % date_field] = now
date_list = queryset.filter(**lookup_kwargs).dates(date_field, 'month')
if not date_list and not allow_empty:
@@ -95,7 +97,7 @@ def archive_year(request, year, queryset, date_field, template_name=None,
def archive_month(request, year, month, queryset, date_field,
month_format='%b', template_name=None, template_loader=loader,
extra_context=None, allow_empty=False, context_processors=None,
- template_object_name='object', mimetype=None):
+ template_object_name='object', mimetype=None, allow_future=False):
"""
Generic monthly archive view.
@@ -127,19 +129,28 @@ def archive_month(request, year, month, queryset, date_field,
last_day = first_day.replace(month=first_day.month + 1)
lookup_kwargs = {'%s__range' % date_field: (first_day, last_day)}
- # Only bother to check current date if the month isn't in the past.
- if last_day >= now.date():
+ # Only bother to check current date if the month isn't in the past and future objects are requested.
+ if last_day >= now.date() and not allow_future:
lookup_kwargs['%s__lte' % date_field] = now
object_list = queryset.filter(**lookup_kwargs)
if not object_list and not allow_empty:
raise Http404
+
+ # Calculate the next month, if applicable.
+ if allow_future:
+ next_month = last_day + datetime.timedelta(days=1)
+ elif last_day < datetime.date.today():
+ next_month = last_day + datetime.timedelta(days=1)
+ else:
+ next_month = None
+
if not template_name:
template_name = "%s/%s_archive_month.html" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name)
c = RequestContext(request, {
'%s_list' % template_object_name: object_list,
'month': date,
- 'next_month': (last_day < datetime.date.today()) and (last_day + datetime.timedelta(days=1)) or None,
+ 'next_month': next_month,
'previous_month': first_day - datetime.timedelta(days=1),
}, context_processors)
for key, value in extra_context.items():
@@ -152,7 +163,7 @@ def archive_month(request, year, month, queryset, date_field,
def archive_week(request, year, week, queryset, date_field,
template_name=None, template_loader=loader,
extra_context=None, allow_empty=True, context_processors=None,
- template_object_name='object', mimetype=None):
+ template_object_name='object', mimetype=None, allow_future=False):
"""
Generic weekly archive view.
@@ -177,8 +188,8 @@ def archive_week(request, year, week, queryset, date_field,
last_day = date + datetime.timedelta(days=7)
lookup_kwargs = {'%s__range' % date_field: (first_day, last_day)}
- # Only bother to check current date if the week isn't in the past.
- if last_day >= now.date():
+ # Only bother to check current date if the week isn't in the past and future objects aren't requested.
+ if last_day >= now.date() and not allow_future:
lookup_kwargs['%s__lte' % date_field] = now
object_list = queryset.filter(**lookup_kwargs)
if not object_list and not allow_empty:
@@ -201,7 +212,7 @@ def archive_day(request, year, month, day, queryset, date_field,
month_format='%b', day_format='%d', template_name=None,
template_loader=loader, extra_context=None, allow_empty=False,
context_processors=None, template_object_name='object',
- mimetype=None):
+ mimetype=None, allow_future=False):
"""
Generic daily archive view.
@@ -225,16 +236,26 @@ def archive_day(request, year, month, day, queryset, date_field,
model = queryset.model
now = datetime.datetime.now()
- lookup_kwargs = {
- '%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
- }
+ if isinstance(model._meta.get_field(date_field), DateTimeField):
+ lookup_kwargs = {'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max))}
+ else:
+ lookup_kwargs = {date_field: date}
- # Only bother to check current date if the date isn't in the past.
- if date >= now.date():
+ # Only bother to check current date if the date isn't in the past and future objects aren't requested.
+ if date >= now.date() and not allow_future:
lookup_kwargs['%s__lte' % date_field] = now
object_list = queryset.filter(**lookup_kwargs)
if not allow_empty and not object_list:
raise Http404
+
+ # Calculate the next day, if applicable.
+ if allow_future:
+ next_day = date + datetime.timedelta(days=1)
+ elif date < datetime.date.today():
+ next_day = date + datetime.timedelta(days=1)
+ else:
+ next_day = None
+
if not template_name:
template_name = "%s/%s_archive_day.html" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name)
@@ -242,7 +263,7 @@ def archive_day(request, year, month, day, queryset, date_field,
'%s_list' % template_object_name: object_list,
'day': date,
'previous_day': date - datetime.timedelta(days=1),
- 'next_day': (date < datetime.date.today()) and (date + datetime.timedelta(days=1)) or None,
+ 'next_day': next_day,
}, context_processors)
for key, value in extra_context.items():
if callable(value):
@@ -267,7 +288,7 @@ def object_detail(request, year, month, day, queryset, date_field,
month_format='%b', day_format='%d', object_id=None, slug=None,
slug_field=None, template_name=None, template_name_field=None,
template_loader=loader, extra_context=None, context_processors=None,
- template_object_name='object', mimetype=None):
+ template_object_name='object', mimetype=None, allow_future=False):
"""
Generic detail view from year/month/day/slug or year/month/day/id structure.
@@ -285,12 +306,13 @@ def object_detail(request, year, month, day, queryset, date_field,
model = queryset.model
now = datetime.datetime.now()
- lookup_kwargs = {
- '%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
- }
+ if isinstance(model._meta.get_field(date_field), DateTimeField):
+ lookup_kwargs = {'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max))}
+ else:
+ lookup_kwargs = {date_field: date}
- # Only bother to check current date if the date isn't in the past.
- if date >= now.date():
+ # Only bother to check current date if the date isn't in the past and future objects aren't requested.
+ if date >= now.date() and not allow_future:
lookup_kwargs['%s__lte' % date_field] = now
if object_id:
lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
diff --git a/django/views/static.py b/django/views/static.py
index 072a01671e..3ec4ca14a1 100644
--- a/django/views/static.py
+++ b/django/views/static.py
@@ -1,5 +1,4 @@
from django.template import loader
-from django.core.exceptions import ImproperlyConfigured
from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified
from django.template import Template, Context, TemplateDoesNotExist
import mimetypes
@@ -82,7 +81,7 @@ def directory_index(path, fullpath):
try:
t = loader.get_template('static/directory_index')
except TemplateDoesNotExist:
- t = Template(DEFAULT_DIRECTORY_INDEX_TEMPLATE)
+ t = Template(DEFAULT_DIRECTORY_INDEX_TEMPLATE, name='Default directory index template')
files = []
for f in os.listdir(fullpath):
if not f.startswith('.'):
diff --git a/docs/add_ons.txt b/docs/add_ons.txt
index 90c98b7176..a0377700d7 100644
--- a/docs/add_ons.txt
+++ b/docs/add_ons.txt
@@ -2,12 +2,15 @@
The "contrib" add-ons
=====================
-Django aims to follow Python's "batteries included" philosophy. It ships with a
-variety of extra, optional tools that solve common Web-development problems.
+Django aims to follow Python's `"batteries included" philosophy`_. It ships
+with a variety of extra, optional tools that solve common Web-development
+problems.
This code lives in ``django/contrib`` in the Django distribution. Here's a
rundown of the packages in ``contrib``:
+.. _"batteries included" philosophy: http://docs.python.org/tut/node12.html#batteries-included
+
admin
=====
@@ -150,6 +153,15 @@ See the `sites documentation`_.
.. _sites documentation: http://www.djangoproject.com/documentation/sites/
+sitemaps
+========
+
+A framework for generating Google sitemap XML files.
+
+See the `sitemaps documentation`_.
+
+.. _sitemaps documentation: http://www.djangoproject.com/documentation/sitemaps/
+
syndication
===========
diff --git a/docs/admin_css.txt b/docs/admin_css.txt
index 069012a84b..5822e26e45 100644
--- a/docs/admin_css.txt
+++ b/docs/admin_css.txt
@@ -82,7 +82,7 @@ There are also a few styles for styling text.
.help
This is a custom class for blocks of inline help text explaining the
function of form elements. It makes text smaller and gray, and when applied
- to ``p`` elements withing ``.form-row`` elements (see Form Styles below),
+ to ``p`` elements within ``.form-row`` elements (see Form Styles below),
it will offset the text to align with the form field. Use this for help
text, instead of ``small quiet``. It works on other elements, but try to
put the class on a ``p`` whenever you can.
@@ -118,8 +118,8 @@ additional class on the ``a`` for that tool. These are ``.addlink`` and
Example from a changelist page::
<ul class="object-tools">
- <li><a href="/stories/add/" class="addlink">Add redirect</a></li>
- </ul>
+ <li><a href="/stories/add/" class="addlink">Add redirect</a></li>
+ </ul>
.. image:: http://media.djangoproject.com/img/doc/admincss/objecttools_01.gif
:alt: Object tools on a changelist page
@@ -170,4 +170,4 @@ Labels
Form labels should always precede the field, except in the case
of checkboxes and radio buttons, where the ``input`` should come first. Any
explanation or help text should follow the ``label`` in a ``p`` with class
-``.help``. \ No newline at end of file
+``.help``.
diff --git a/docs/apache_auth.txt b/docs/apache_auth.txt
index 72e0841305..b85057924b 100644
--- a/docs/apache_auth.txt
+++ b/docs/apache_auth.txt
@@ -6,7 +6,7 @@ Since keeping multiple authentication databases in sync is a common problem when
dealing with Apache, you can configuring Apache to authenticate against Django's
`authentication system`_ directly. For example, you could:
- * Serve media files directly from Apache only to authenticated users.
+ * Serve static/media files directly from Apache only to authenticated users.
* Authenticate access to a Subversion_ repository against Django users with
a certain permission.
diff --git a/docs/api_stability.txt b/docs/api_stability.txt
new file mode 100644
index 0000000000..18885fbe63
--- /dev/null
+++ b/docs/api_stability.txt
@@ -0,0 +1,123 @@
+=============
+API stability
+=============
+
+Although Django has not reached a 1.0 release, the bulk of Django's public APIs are
+stable as of the 0.95 release. This document explains which APIs will and will not
+change before the 1.0 release.
+
+What "stable" means
+===================
+
+In this context, stable means:
+
+ - All the public APIs -- everything documented in the linked documents, and
+ all methods that don't begin with an underscore -- will not be moved or
+ renamed without providing backwards-compatible aliases.
+
+ - If new features are added to these APIs -- which is quite possible --
+ they will not break or change the meaning of existing methods. In other
+ words, "stable" does not (necessarily) mean "complete."
+
+ - If, for some reason, an API declared stable must be removed or replaced, it
+ will be declared deprecated but will remain in the API until at least
+ version 1.1. Warnings will be issued when the deprecated method is
+ called.
+
+ - We'll only break backwards compatibility of these APIs if a bug or
+ security hole makes it completely unavoidable.
+
+Stable APIs
+===========
+
+These APIs are stable:
+
+ - `Caching`_.
+
+ - `Custom template tags and libraries`_ (with the possible exception for a
+ small change in the way templates are registered and loaded).
+
+ - `Database lookup`_ (with the exception of validation; see below).
+
+ - `django-admin utility`_.
+
+ - `FastCGI integration`_.
+
+ - `Flatpages`_.
+
+ - `Generic views`_.
+
+ - `Internationalization`_.
+
+ - `Legacy database integration`_.
+
+ - `Model definition`_ (with the exception of generic relations; see below).
+
+ - `mod_python integration`_.
+
+ - `Redirects`_.
+
+ - `Request/response objects`_.
+
+ - `Sending email`_.
+
+ - `Sessions`_.
+
+ - `Settings`_.
+
+ - `Syndication`_.
+
+ - `Template language`_ (with the exception of some possible disambiguation
+ of how tag arguments are passed to tags and filters).
+
+ - `Transactions`_.
+
+ - `URL dispatch`_.
+
+You'll notice that this list comprises the bulk of Django's APIs. That's right
+-- most of the changes planned between now and Django 1.0 are either under the
+hood, feature additions, or changes to a few select bits. A good estimate is
+that 90% of Django can be considered forwards-compatible at this point.
+
+That said, these APIs should *not* be considered stable, and are likely to
+change:
+
+ - `Forms and validation`_ will most likely be completely rewritten to
+ deemphasize Manipulators in favor of validation-aware models.
+
+ - `Serialization`_ is under heavy development; changes are likely.
+
+ - The `authentication`_ framework is changing to be far more flexible, and
+ API changes may be necessary.
+
+ - Generic relations will most likely be moved out of core and into the
+ content-types contrib package to avoid core dependancies on optional
+ components.
+
+ - The comments framework, which is yet undocumented, will likely get a complete
+ rewrite before Django 1.0. Even if the change isn't quite that drastic,
+ there will at least be moderate changes.
+
+.. _caching: http://www.djangoproject.com/documentation/cache/
+.. _custom template tags and libraries: http://www.djangoproject.com/documentation/templates_python/
+.. _database lookup: http://www.djangoproject.com/documentation/db_api/
+.. _django-admin utility: http://www.djangoproject.com/documentation/django_admin/
+.. _fastcgi integration: http://www.djangoproject.com/documentation/fastcgi/
+.. _flatpages: http://www.djangoproject.com/documentation/flatpages/
+.. _generic views: http://www.djangoproject.com/documentation/generic_views/
+.. _internationalization: http://www.djangoproject.com/documentation/i18n/
+.. _legacy database integration: http://www.djangoproject.com/documentation/legacy_databases/
+.. _model definition: http://www.djangoproject.com/documentation/model_api/
+.. _mod_python integration: http://www.djangoproject.com/documentation/modpython/
+.. _redirects: http://www.djangoproject.com/documentation/redirects/
+.. _request/response objects: http://www.djangoproject.com/documentation/request_response/
+.. _sending email: http://www.djangoproject.com/documentation/email/
+.. _sessions: http://www.djangoproject.com/documentation/sessions/
+.. _settings: http://www.djangoproject.com/documentation/settings/
+.. _syndication: http://www.djangoproject.com/documentation/syndication/
+.. _template language: http://www.djangoproject.com/documentation/templates/
+.. _transactions: http://www.djangoproject.com/documentation/transactions/
+.. _url dispatch: http://www.djangoproject.com/documentation/url_dispatch/
+.. _forms and validation: http://www.djangoproject.com/documentation/forms/
+.. _serialization: http://www.djangoproject.com/documentation/serialization/
+.. _authentication: http://www.djangoproject.com/documentation/authentication/
diff --git a/docs/authentication.txt b/docs/authentication.txt
index 68b9024a90..2a61ec82b5 100644
--- a/docs/authentication.txt
+++ b/docs/authentication.txt
@@ -66,8 +66,8 @@ Fields
long and can contain any character. See the "Passwords" section below.
* ``is_staff`` -- Boolean. Designates whether this user can access the
admin site.
- * ``is_active`` -- Boolean. Designates whether this user can log into the
- Django admin. Set this to ``False`` instead of deleting accounts.
+ * ``is_active`` -- Boolean. Designates whether this account can be used
+ to log in. Set this flag to ``False`` instead of deleting accounts.
* ``is_superuser`` -- Boolean. Designates that this user has all permissions
without explicitly assigning them.
* ``last_login`` -- A datetime of the user's last login. Is set to the
@@ -82,20 +82,26 @@ Methods
``user_permissions``. ``User`` objects can access their related
objects in the same way as any other `Django model`_::
- myuser.objects.groups = [group_list]
- myuser.objects.groups.add(group, group,...)
- myuser.objects.groups.remove(group, group,...)
- myuser.objects.groups.clear()
- myuser.objects.permissions = [permission_list]
- myuser.objects.permissions.add(permission, permission, ...)
- myuser.objects.permissions.remove(permission, permission, ...]
- myuser.objects.permissions.clear()
+ myuser.groups = [group_list]
+ myuser.groups.add(group, group,...)
+ myuser.groups.remove(group, group,...)
+ myuser.groups.clear()
+ myuser.permissions = [permission_list]
+ myuser.permissions.add(permission, permission, ...)
+ myuser.permissions.remove(permission, permission, ...]
+ myuser.permissions.clear()
In addition to those automatic API methods, ``User`` objects have the following
custom methods:
* ``is_anonymous()`` -- Always returns ``False``. This is a way of
- comparing ``User`` objects to anonymous users.
+ differentiating ``User`` and ``AnonymousUser`` objects. Generally, you
+ should prefer using ``is_authenticated()`` to this method.
+
+ * ``is_authenticated()`` -- Always returns ``True``. This is a way to
+ tell if the user has been authenticated. This does not imply any
+ permissions, and doesn't check if the user is active - it only indicates
+ that the user has provided a valid username and password.
* ``get_full_name()`` -- Returns the ``first_name`` plus the ``last_name``,
with a space in between.
@@ -116,13 +122,16 @@ custom methods:
* ``has_perm(perm)`` -- Returns ``True`` if the user has the specified
permission, where perm is in the format ``"package.codename"``.
+ If the user is inactive, this method will always return ``False``.
* ``has_perms(perm_list)`` -- Returns ``True`` if the user has each of the
specified permissions, where each perm is in the format
- ``"package.codename"``.
+ ``"package.codename"``. If the user is inactive, this method will
+ always return ``False``.
* ``has_module_perms(package_name)`` -- Returns ``True`` if the user has
any permissions in the given package (the Django app label).
+ If the user is inactive, this method will always return ``False``.
* ``get_and_delete_messages()`` -- Returns a list of ``Message`` objects in
the user's queue and deletes the messages from the queue.
@@ -219,6 +228,7 @@ the ``django.contrib.auth.models.User`` interface, with these differences:
* ``id`` is always ``None``.
* ``is_anonymous()`` returns ``True`` instead of ``False``.
+ * ``is_authenticated()`` returns ``False`` instead of ``True``.
* ``has_perm()`` always returns ``False``.
* ``set_password()``, ``check_password()``, ``save()``, ``delete()``,
``set_groups()`` and ``set_permissions()`` raise ``NotImplementedError``.
@@ -254,12 +264,12 @@ Once you have those middlewares installed, you'll be able to access
``request.user`` in views. ``request.user`` will give you a ``User`` object
representing the currently logged-in user. If a user isn't currently logged in,
``request.user`` will be set to an instance of ``AnonymousUser`` (see the
-previous section). You can tell them apart with ``is_anonymous()``, like so::
+previous section). You can tell them apart with ``is_authenticated()``, like so::
- if request.user.is_anonymous():
- # Do something for anonymous users.
+ if request.user.is_authenticated():
+ # Do something for authenticated users.
else:
- # Do something for logged-in users.
+ # Do something for anonymous users.
.. _request objects: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
.. _session documentation: http://www.djangoproject.com/documentation/sessions/
@@ -278,7 +288,10 @@ password is invalid, ``authenticate()`` returns ``None``. Example::
from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
- print "You provided a correct username and password!"
+ if user.is_active:
+ print "You provided a correct username and password!"
+ else:
+ print "Your account has been disabled!"
else:
print "Your username and password were incorrect."
@@ -296,10 +309,13 @@ This example shows how you might use both ``authenticate()`` and ``login()``::
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
- login(request, user)
- # Redirect to a success page.
+ if user.is_active:
+ login(request, user)
+ # Redirect to a success page.
+ else:
+ # Return a 'disabled account' error message
else:
- # Return an error message.
+ # Return an 'invalid login' error message.
How to log a user out
---------------------
@@ -323,19 +339,19 @@ The raw way
~~~~~~~~~~~
The simple, raw way to limit access to pages is to check
-``request.user.is_anonymous()`` and either redirect to a login page::
+``request.user.is_authenticated()`` and either redirect to a login page::
from django.http import HttpResponseRedirect
def my_view(request):
- if request.user.is_anonymous():
+ if not request.user.is_authenticated():
return HttpResponseRedirect('/login/?next=%s' % request.path)
# ...
...or display an error message::
def my_view(request):
- if request.user.is_anonymous():
+ if not request.user.is_authenticated():
return render_to_response('myapp/login_error.html')
# ...
@@ -439,7 +455,7 @@ For example, this view checks to make sure the user is logged in and has the
permission ``polls.can_vote``::
def my_view(request):
- if request.user.is_anonymous() or not request.user.has_perm('polls.can_vote'):
+ if not (request.user.is_authenticated() and request.user.has_perm('polls.can_vote')):
return HttpResponse("You can't vote in this poll.")
# ...
@@ -451,6 +467,10 @@ As a shortcut, you can use the convenient ``user_passes_test`` decorator::
# ...
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'))(my_view)
+We're using this particular test as a relatively simple example. However, if
+you just want to test whether a permission is available to a user, you can use
+the ``permission_required()`` decorator, described later in this document.
+
Here's the same thing, using Python 2.4's decorator syntax::
from django.contrib.auth.decorators import user_passes_test
@@ -483,6 +503,34 @@ Example in Python 2.4 syntax::
def my_view(request):
# ...
+The permission_required decorator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**New in Django development version**
+
+It's a relatively common task to check whether a user has a particular
+permission. For that reason, Django provides a shortcut for that case: the
+``permission_required()`` decorator. Using this decorator, the earlier example
+can be written as::
+
+ from django.contrib.auth.decorators import permission_required
+
+ def my_view(request):
+ # ...
+ my_view = permission_required('polls.can_vote')(my_view)
+
+Note that ``permission_required()`` also takes an optional ``login_url``
+parameter. Example::
+
+ from django.contrib.auth.decorators import permission_required
+
+ def my_view(request):
+ # ...
+ my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view)
+
+As in the ``login_required`` decorator, ``login_url`` defaults to
+``'/accounts/login/'``.
+
Limiting access to generic views
--------------------------------
@@ -605,10 +653,10 @@ Users
The currently logged-in user, either a ``User`` instance or an``AnonymousUser``
instance, is stored in the template variable ``{{ user }}``::
- {% if user.is_anonymous %}
- <p>Welcome, new user. Please log in.</p>
- {% else %}
+ {% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
+ {% else %}
+ <p>Welcome, new user. Please log in.</p>
{% endif %}
Permissions
@@ -672,7 +720,7 @@ timestamps.
Messages are used by the Django admin after successful actions. For example,
``"The poll Foo was created successfully."`` is a message.
-The API is simple::
+The API is simple:
* To create a new message, use
``user_obj.message_set.create(message='message_text')``.
diff --git a/docs/cache.txt b/docs/cache.txt
index 2ef3d6503f..1795345ed9 100644
--- a/docs/cache.txt
+++ b/docs/cache.txt
@@ -230,8 +230,16 @@ Then, add the following required settings to your Django settings file:
collisions. Use an empty string if you don't care.
The cache middleware caches every page that doesn't have GET or POST
-parameters. Additionally, ``CacheMiddleware`` automatically sets a few headers
-in each ``HttpResponse``:
+parameters. Optionally, if the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting is
+``True``, only anonymous requests (i.e., not those made by a logged-in user)
+will be cached. This is a simple and effective way of disabling caching for any
+user-specific pages (include Django's admin interface). Note that if you use
+``CACHE_MIDDLEWARE_ANONYMOUS_ONLY``, you should make sure you've activated
+``AuthenticationMiddleware`` and that ``AuthenticationMiddleware`` appears
+before ``CacheMiddleware`` in your ``MIDDLEWARE_CLASSES``.
+
+Additionally, ``CacheMiddleware`` automatically sets a few headers in each
+``HttpResponse``:
* Sets the ``Last-Modified`` header to the current date/time when a fresh
(uncached) version of the page is requested.
diff --git a/docs/contributing.txt b/docs/contributing.txt
index d7552cdc7c..6ff0b038a3 100644
--- a/docs/contributing.txt
+++ b/docs/contributing.txt
@@ -168,6 +168,23 @@ Please follow these coding standards when writing code for inclusion in Django:
{{foo}}
+ * In Django views, the first parameter in a view function should be called
+ ``request``.
+
+ Do this::
+
+ def my_view(request, foo):
+ # ...
+
+ Don't do this::
+
+ def my_view(req, foo):
+ # ...
+
+ * Please don't put your name in the code. While we appreciate all
+ contributions to Django, our policy is not to publish individual
+ developer names in code -- for instance, at the top of Python modules.
+
Committing code
===============
@@ -212,6 +229,10 @@ repository:
first, then the "Fixed #abc." For example:
"magic-removal: Fixed #123 -- Added whizbang feature."
+ For the curious: We're using a `Trac post-commit hook`_ for this.
+
+ .. _Trac post-commit hook: http://trac.edgewall.org/browser/trunk/contrib/trac-post-commit-hook
+
* If your commit references a ticket in the Django `ticket tracker`_ but
does *not* close the ticket, include the phrase "Refs #abc", where "abc"
is the number of the ticket your commit references. We've rigged
@@ -226,18 +247,23 @@ Django tarball. It's our policy to make sure all tests pass at all times.
The tests cover:
- * Models and the database API (``tests/testapp/models``).
- * The cache system (``tests/otherthests/cache.py``).
- * The ``django.utils.dateformat`` module (``tests/othertests/dateformat.py``).
- * Database typecasts (``tests/othertests/db_typecasts.py``).
- * The template system (``tests/othertests/templates.py`` and
- ``tests/othertests/defaultfilters.py``).
- * ``QueryDict`` objects (``tests/othertests/httpwrappers.py``).
- * Markup template tags (``tests/othertests/markup.py``).
- * The ``django.utils.timesince`` module (``tests/othertests/timesince.py``).
+ * Models and the database API (``tests/modeltests/``).
+ * The cache system (``tests/regressiontests/cache.py``).
+ * The ``django.utils.dateformat`` module (``tests/regressiontests/dateformat/``).
+ * Database typecasts (``tests/regressiontests/db_typecasts/``).
+ * The template system (``tests/regressiontests/templates/`` and
+ ``tests/regressiontests/defaultfilters/``).
+ * ``QueryDict`` objects (``tests/regressiontests/httpwrappers/``).
+ * Markup template tags (``tests/regressiontests/markup/``).
We appreciate any and all contributions to the test suite!
+The Django tests all use the testing infrastructure that ships with Django for
+testing applications. See `Testing Django applications`_ for an explanation of
+how to write new tests.
+
+.. _Testing Django applications: http://www.djangoproject.com/documentation/testing/
+
Running the unit tests
----------------------
@@ -247,10 +273,14 @@ To run the tests, ``cd`` to the ``tests/`` directory and type::
Yes, the unit tests need a settings module, but only for database connection
info -- the ``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD``.
+You will also need a ``ROOT_URLCONF`` setting (its value is ignored; it just
+needs to be present) and a ``SITE_ID`` setting (any integer value will do) in
+order for all the tests to pass.
-The unit tests will not touch your database; they create a new database, called
-``django_test_db``, which is deleted when the tests are finished. This means
-your user account needs permission to execute ``CREATE DATABASE``.
+The unit tests will not touch your existing databases; they create a new
+database, called ``django_test_db``, which is deleted when the tests are
+finished. This means your user account needs permission to execute ``CREATE
+DATABASE``.
Requesting features
===================
diff --git a/docs/db-api.txt b/docs/db-api.txt
index ce6bb0ab3b..2f0c8b0589 100644
--- a/docs/db-api.txt
+++ b/docs/db-api.txt
@@ -578,6 +578,9 @@ related ``Person`` *and* the related ``City``::
p = b.author # Hits the database.
c = p.hometown # Hits the database.
+Note that ``select_related()`` does not follow foreign keys that have
+``null=True``.
+
``extra(select=None, where=None, params=None, tables=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -715,12 +718,12 @@ The ``DoesNotExist`` exception inherits from
A convenience method for creating an object and saving it all in one step. Thus::
p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
-
+
and::
p = Person(first_name="Bruce", last_name="Springsteen")
p.save()
-
+
are equivalent.
``get_or_create(**kwargs)``
@@ -873,15 +876,18 @@ The database API supports the following lookup types:
exact
~~~~~
-Exact match.
+Exact match. If the value provided for comparison is ``None``, it will
+be interpreted as an SQL ``NULL`` (See isnull_ for more details).
-Example::
+Examples::
Entry.objects.get(id__exact=14)
+ Entry.objects.get(id__exact=None)
-SQL equivalent::
+SQL equivalents::
SELECT ... WHERE id = 14;
+ SELECT ... WHERE id = NULL;
iexact
~~~~~~
@@ -1100,8 +1106,8 @@ such as January 3, July 3, etc.
isnull
~~~~~~
-``NULL`` or ``IS NOT NULL`` match. Takes either ``True`` or ``False``, which
-correspond to ``IS NULL`` and ``IS NOT NULL``, respectively.
+Takes either ``True`` or ``False``, which correspond to SQL queries of
+``IS NULL`` and ``IS NOT NULL``, respectively.
Example::
@@ -1111,6 +1117,14 @@ SQL equivalent::
SELECT ... WHERE pub_date IS NULL;
+.. admonition:: ``__isnull=True`` vs ``__exact=None``
+
+ There is an important difference between ``__isnull=True`` and
+ ``__exact=None``. ``__exact=None`` will *always* return an empty result
+ set, because SQL requires that no value is equal to ``NULL``.
+ ``__isnull`` determines if the field is currently holding the value
+ of ``NULL`` without performing a comparison.
+
search
~~~~~~
@@ -1137,7 +1151,7 @@ The pk lookup shortcut
----------------------
For convenience, Django provides a ``pk`` lookup type, which stands for
-"primary_key". This is shorthand for "an exact lookup on the primary-key."
+"primary_key".
In the example ``Blog`` model, the primary key is the ``id`` field, so these
three statements are equivalent::
@@ -1146,6 +1160,14 @@ three statements are equivalent::
Blog.objects.get(id=14) # __exact is implied
Blog.objects.get(pk=14) # pk implies id__exact
+The use of ``pk`` isn't limited to ``__exact`` queries -- any query term
+can be combined with ``pk`` to perform a query on the primary key of a model::
+
+ # Get blogs entries with id 1, 4 and 7
+ Blog.objects.filter(pk__in=[1,4,7])
+ # Get all blog entries with id > 14
+ Blog.objects.filter(pk__gt=14)
+
``pk`` lookups also work across joins. For example, these three statements are
equivalent::
@@ -1468,11 +1490,12 @@ the ``ForeignKey`` ``Manager`` has these additional methods:
b.entry_set.remove(e) # Disassociates Entry e from Blog b.
In order to prevent database inconsistency, this method only exists on
- ``ForeignKey``s where ``null=True``. If the related field can't be set to
- ``None`` (``NULL``), then an object can't be removed from a relation
- without being added to another. In the above example, removing ``e`` from
- ``b.entry_set()`` is equivalent to doing ``e.blog = None``, and because
- the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this is invalid.
+ ``ForeignKey`` objects where ``null=True``. If the related field can't be
+ set to ``None`` (``NULL``), then an object can't be removed from a
+ relation without being added to another. In the above example, removing
+ ``e`` from ``b.entry_set()`` is equivalent to doing ``e.blog = None``,
+ and because the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this
+ is invalid.
* ``clear()``: Removes all objects from the related object set.
@@ -1507,7 +1530,7 @@ Many-to-many relationships
--------------------------
Both ends of a many-to-many relationship get automatic API access to the other
-end. The API works just as a "backward" one-to-many relationship. See _Backward
+end. The API works just as a "backward" one-to-many relationship. See Backward_
above.
The only difference is in the attribute naming: The model that defines the
@@ -1556,13 +1579,13 @@ Queries over related objects
----------------------------
Queries involving related objects follow the same rules as queries involving
-normal value fields. When specifying the the value for a query to match, you
-may use either an object instance itself, or the primary key value for the
+normal value fields. When specifying the the value for a query to match, you
+may use either an object instance itself, or the primary key value for the
object.
For example, if you have a Blog object ``b`` with ``id=5``, the following
three queries would be identical::
-
+
Entry.objects.filter(blog=b) # Query using object instance
Entry.objects.filter(blog=b.id) # Query using id from instance
Entry.objects.filter(blog=5) # Query using id directly
diff --git a/docs/design_philosophies.txt b/docs/design_philosophies.txt
index 17ed3ad6da..7fdc7ea01b 100644
--- a/docs/design_philosophies.txt
+++ b/docs/design_philosophies.txt
@@ -274,8 +274,8 @@ Loose coupling
A view shouldn't care about which template system the developer uses -- or even
whether a template system is used at all.
-Designate between GET and POST
-------------------------------
+Differentiate between GET and POST
+----------------------------------
GET and POST are distinct; developers should explicitly use one or the other.
The framework should make it easy to distinguish between GET and POST data.
diff --git a/docs/django-admin.txt b/docs/django-admin.txt
index 04d86aa3b4..7f9682b443 100644
--- a/docs/django-admin.txt
+++ b/docs/django-admin.txt
@@ -192,6 +192,14 @@ documentation.
.. _serving static files: http://www.djangoproject.com/documentation/static_files/
+Turning off auto-reload
+~~~~~~~~~~~~~~~~~~~~~~~
+
+To disable auto-reloading of code while the development server is running, use the
+``--noreload`` option, like so::
+
+ django-admin.py runserver --noreload
+
shell
-----
@@ -284,6 +292,15 @@ this command to install the default apps.
If you're installing the ``django.contrib.auth`` application, ``syncdb`` will
give you the option of creating a superuser immediately.
+test
+----
+
+**New in Django development version**
+
+Discover and run tests for all installed models. See `Testing Django applications`_ for more information.
+
+.. _testing django applications: ../testing/
+
validate
--------
@@ -330,6 +347,20 @@ setting the Python path for you.
Displays a help message that includes a terse list of all available actions and
options.
+--noinput
+---------
+
+**New in Django development version**
+
+Inform django-admin that the user should NOT be prompted for any input. Useful
+if the django-admin script will be executed as an unattended, automated
+script.
+
+--noreload
+----------
+
+Disable the use of the auto-reloader when running the development server.
+
--version
---------
@@ -340,6 +371,32 @@ Example output::
0.9.1
0.9.1 (SVN)
+--verbosity
+-----------
+
+**New in Django development version**
+
+Example usage::
+
+ django-admin.py syncdb --verbosity=2
+
+Verbosity determines the amount of notification and debug information that
+will be printed to the console. '0' is no output, '1' is normal output,
+and `2` is verbose output.
+
+--adminmedia
+------------
+
+**New in Django development version**
+
+Example usage::
+ django-admin.py manage.py --adminmedia=/tmp/new-admin-style/
+
+Tells Django where to find the various CSS and JavaScript files for the admin
+interface when running the development server. Normally these files are served
+out of the Django source tree, but because some designers customize these files
+for their site, this option allows you to test against custom versions.
+
Extra niceties
==============
diff --git a/docs/documentation.txt b/docs/documentation.txt
new file mode 100644
index 0000000000..bacfb176b1
--- /dev/null
+++ b/docs/documentation.txt
@@ -0,0 +1,148 @@
+====================================
+How to read the Django documentation
+====================================
+
+We've put a lot of effort into making Django's documentation useful, easy to
+read and as complete as possible. Here are a few tips on how to make the best
+of it, along with some style guidelines.
+
+(Yes, this is documentation about documentation. Rest assured we have no plans
+to write a document about how to read the document about documentation.)
+
+How documentation is updated
+============================
+
+Just as the Django code base is developed and improved on a daily basis, our
+documentation is consistently improving. We improve documentation for several
+reasons:
+
+ * To make content fixes, such as grammar/typo corrections.
+ * To add information and/or examples to existing sections that need to be
+ expanded.
+ * To document Django features that aren't yet documented. (The list of
+ such features is shrinking but exists nonetheless.)
+ * To add documentation for new features as new features get added, or as
+ Django APIs or behaviors change.
+
+Django's documentation is kept in the same source control system as its code.
+It lives in the `django/trunk/docs`_ directory of our Subversion repository.
+Each document is a separate text file that covers a narrowly focused topic,
+such as the "generic views" framework or how to construct a database model.
+
+.. _django/trunk/docs: http://code.djangoproject.com/browser/django/trunk/docs
+
+Where to get it
+===============
+
+You can read Django documentation in several ways. They are, in order of
+preference:
+
+On the Web
+----------
+
+The most recent version of the Django documentation lives at
+http://www.djangoproject.com/documentation/ . These HTML pages are generated
+automatically from the text files in source control every 15 minutes. That
+means they reflect the "latest and greatest" in Django -- they include the very
+latest corrections and additions, and they discuss the latest Django features,
+which may only be available to users of the Django development version. (See
+"Differences between versions" below.)
+
+A key advantage of the Web-based documentation is the comment section at the
+bottom of each document. This is an area for anybody to submit changes,
+corrections and suggestions about the given document. The Django developers
+frequently monitor the comments there and use them to improve the documentation
+for everybody.
+
+We encourage you to help improve the docs: it's easy! Note, however, that
+comments should explicitly relate to the documentation, rather than asking
+broad tech-support questions. If you need help with your particular Django
+setup, try the `django-users mailing list`_ instead of posting a comment to the
+documentation.
+
+.. _django-users mailing list: http://groups.google.com/group/django-users
+
+In plain text
+-------------
+
+For offline reading, or just for convenience, you can read the Django
+documentation in plain text.
+
+If you're using an official release of Django, note that the zipped package
+(tarball) of the code includes a ``docs/`` directory, which contains all the
+documentation for that release.
+
+If you're using the development version of Django (aka the Subversion "trunk"),
+note that the ``docs/`` directory contains all of the documentation. You can
+``svn update`` it, just as you ``svn update`` the Python code, in order to get
+the latest changes.
+
+You can check out the latest Django documentation from Subversion using this
+shell command::
+
+ svn co http://code.djangoproject.com/svn/django/trunk/docs/ django_docs
+
+One low-tech way of taking advantage of the text documentation is by using the
+Unix ``grep`` utility to search for a phrase in all of the documentation. For
+example, this will show you each mention of the phrase "edit_inline" in any
+Django document::
+
+ grep edit_inline /path/to/django/docs/*.txt
+
+Formatting
+~~~~~~~~~~
+
+The text documentation is written in ReST (ReStructured Text) format. That
+means it's easy to read but is also formatted in a way that makes it easy to
+convert into other formats, such as HTML. If you're interested, the script that
+converts the ReST text docs into djangoproject.com's HTML lives at
+`djangoproject.com/django_website/apps/docs/parts/build_documentation.py`_ in
+the Django Subversion repository.
+
+.. _djangoproject.com/django_website/apps/docs/parts/build_documentation.py: http://code.djangoproject.com/browser/djangoproject.com/django_website/apps/docs/parts/build_documentation.py
+
+Differences between versions
+============================
+
+As previously mentioned, the text documentation in our Subversion repository
+contains the "latest and greatest" changes and additions. These changes often
+include documentation of new features added in the Django development version
+-- the Subversion ("trunk") version of Django. For that reason, it's worth
+pointing out our policy on keeping straight the documentation for various
+versions of the framework.
+
+We follow this policy:
+
+ * The primary documentation on djangoproject.com is an HTML version of the
+ latest docs in Subversion. These docs always correspond to the latest
+ official Django release, plus whatever features we've added/changed in
+ the framework *since* the latest release.
+
+ * As we add features to Django's development version, we try to update the
+ documentation in the same Subversion commit transaction.
+
+ * To distinguish feature changes/additions in the docs, we use the phrase
+ **New in Django development version**. In practice, this means that the
+ current documentation on djangoproject.com can be used by users of either
+ the latest release *or* the development version.
+
+ * Documentation for a particular Django release is frozen once the version
+ has been released officially. It remains a snapshot of the docs as of the
+ moment of the release. We will make exceptions to this rule in
+ the case of retroactive security updates or other such retroactive
+ changes. Once documentation is frozen, we add a note to the top of each
+ frozen document that says "These docs are frozen for Django version XXX"
+ and links to the current version of that document.
+
+ * Once a document is frozen for a Django release, we remove comments from
+ that page, in favor of having comments on the latest version of that
+ document. This is for the sake of maintainability and usability, so that
+ users have one, and only one, place to leave comments on a particular
+ document. We realize that some people may be stuck on a previous version
+ of Django, but we believe the usability problems with multiple versions
+ of a document the outweigh the benefits.
+
+ * The `main documentation Web page`_ includes links to documentation for
+ all previous versions.
+
+.. _main documentation Web page: http://www.djangoproject.com/documentation/
diff --git a/docs/faq.txt b/docs/faq.txt
index b374abfbf3..eaccc6be43 100644
--- a/docs/faq.txt
+++ b/docs/faq.txt
@@ -16,12 +16,17 @@ hours to take a complicated Web application from concept to public launch.
At the same time, the World Online Web developers have consistently been
perfectionists when it comes to following best practices of Web development.
-Thus, Django was designed not only to allow fast Web development, but
-*best-practice* Web development.
+In fall 2003, the World Online developers (Adrian Holovaty and Simon Willison)
+ditched PHP and began using Python to develop its Web sites. As they built
+intensive, richly interactive sites such as Lawrence.com, they began to extract
+a generic Web development framework that let them build Web applications more
+and more quickly. They tweaked this framework constantly, adding improvements
+over two years.
-Django would not be possible without a whole host of open-source projects --
-`Apache`_, `Python`_, and `PostgreSQL`_ to name a few -- and we're thrilled to
-be able to give something back to the open-source community.
+In summer 2005, World Online decided to open-source the resulting software,
+Django. Django would not be possible without a whole host of open-source
+projects -- `Apache`_, `Python`_, and `PostgreSQL`_ to name a few -- and we're
+thrilled to be able to give something back to the open-source community.
.. _Apache: http://httpd.apache.org/
.. _Python: http://www.python.org/
@@ -42,8 +47,8 @@ Django is pronounced **JANG**-oh. Rhymes with FANG-oh. The "D" is silent.
Is Django stable?
-----------------
-Yes. World Online has been using Django for more than two years. Sites built on
-Django have weathered traffic spikes of over one million hits an hour and a
+Yes. World Online has been using Django for more than three years. Sites built
+on Django have weathered traffic spikes of over one million hits an hour and a
number of Slashdottings. Yes, it's quite stable.
Does Django scale?
@@ -98,10 +103,9 @@ Lawrence, Kansas, USA.
On IRC, Simon goes by ``SimonW``.
`Wilson Miner`_
- Wilson's design-fu makes us all look like rock stars. When not sneaking
- into apartment complex swimming pools, he's the Commercial Development
- Director for World Online, which means he makes the money that pays all our
- paychecks. He lives in Lawrence, Kansas.
+ Wilson's design-fu makes us all look like rock stars. By day, he's an
+ interactive designer for `Apple`. Don't ask him what he's working on, or
+ he'll have to kill you. He lives in San Francisco.
On IRC, Wilson goes by ``wilsonian``.
@@ -113,6 +117,7 @@ Lawrence, Kansas, USA.
.. _`simon.incutio.com`: http://simon.incutio.com/
.. _`Jacob Kaplan-Moss`: http://www.jacobian.org/
.. _`Wilson Miner`: http://www.wilsonminer.com/
+.. _`Apple`: http://www.apple.com/
Which sites use Django?
-----------------------
@@ -156,7 +161,7 @@ logical to us.
-----------------------------------------------------
We're well aware that there are other awesome Web frameworks out there, and
-we're not adverse to borrowing ideas where appropriate. However, Django was
+we're not averse to borrowing ideas where appropriate. However, Django was
developed precisely because we were unhappy with the status quo, so please be
aware that "because <Framework X>" does it is not going to be sufficient reason
to add a given feature to Django.
@@ -222,9 +227,7 @@ When will you release Django 1.0?
Short answer: When we're comfortable with Django's APIs, have added all
features that we feel are necessary to earn a "1.0" status, and are ready to
-begin maintaining backwards compatibility. This should happen in a couple of
-months or so, although it's entirely possible that it could happen earlier.
-That translates into summer 2006.
+begin maintaining backwards compatibility.
The merging of Django's `magic-removal branch`_ went a long way toward Django
1.0.
@@ -251,6 +254,16 @@ information than the docs that come with the latest Django release.
.. _stored in revision control: http://code.djangoproject.com/browser/django/trunk/docs
+Where can I find Django developers for hire?
+--------------------------------------------
+
+Consult our `developers for hire page`_ for a list of Django developers who
+would be happy to help you.
+
+You might also be interested in posting a job to http://www.gypsyjobs.com/ .
+
+.. _developers for hire page: http://code.djangoproject.com/wiki/DevelopersForHire
+
Installation questions
======================
@@ -298,6 +311,18 @@ PostgreSQL fans, and MySQL_ and `SQLite 3`_ are also supported.
.. _MySQL: http://www.mysql.com/
.. _`SQLite 3`: http://www.sqlite.org/
+Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5?
+----------------------------------------------------------------------------------------
+
+No. Django itself is guaranteed to work with any version of Python from 2.3
+and higher.
+
+If you use a Python version newer than 2.3, you will, of course, be able to
+take advantage of newer Python features in your own code, along with the speed
+improvements and other optimizations that have been made to the Python language
+itself. But the Django framework itself should work equally well on 2.3 as it
+does on 2.4 or 2.5.
+
Do I have to use mod_python?
----------------------------
@@ -472,7 +497,7 @@ specify an object to edit or delete.
How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type?
------------------------------------------------------------------------------------------------------------------
-We try to avoid adding special cases in the Django code to accomodate all the
+We try to avoid adding special cases in the Django code to accommodate all the
database-specific options such as table type, etc. If you'd like to use any of
these options, create an `SQL initial data file`_ that contains ``ALTER TABLE``
statements that do what you want to do. The initial data files are executed in
@@ -535,13 +560,26 @@ If you're sure your username and password are correct, make sure your user
account has ``is_active`` and ``is_staff`` set to True. The admin site only
allows access to users with those two fields both set to True.
+How can I prevent the cache middleware from caching the admin site?
+-------------------------------------------------------------------
+
+Set the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting to ``True``. See the
+`cache documentation`_ for more information.
+
+.. _cache documentation: ../cache/#the-per-site-cache
+
How do I automatically set a field's value to the user who last edited the object in the admin?
-----------------------------------------------------------------------------------------------
-At this point, you can't do this. But it's an oft-requested feature, so we're
-discussing how it can be implemented. The problem is we don't want to couple
-the model layer with the admin layer with the request layer (to get the current
-user). It's a tricky problem.
+At this point, Django doesn't have an official way to do this. But it's an oft-requested
+feature, so we're discussing how it can be implemented. The problem is we don't want to couple
+the model layer with the admin layer with the request layer (to get the current user). It's a
+tricky problem.
+
+One person hacked up a `solution that doesn't require patching Django`_, but note that it's an
+unofficial solution, and there's no guarantee it won't break at some point.
+
+.. _solution that doesn't require patching Django: http://lukeplant.me.uk/blog.php?id=1107301634
How do I limit admin access so that objects can only be edited by the users who created them?
---------------------------------------------------------------------------------------------
@@ -597,12 +635,35 @@ like to make should be possible by editing the stylesheet. We've got a
How do I create users without having to edit password hashes?
-------------------------------------------------------------
-We don't recommend you create users via the admin interface, because at the
-moment it requires you to edit password hashes manually. (Passwords are hashed
-using one-way hash algorithms for security; there's currently no Web interface
-for changing passwords by entering the actual password rather than the hash.)
+If you'd like to use the admin site to create users, upgrade to the Django
+development version, where this problem was fixed on Aug. 4, 2006.
-To create a user, you'll have to use the Python API. See `creating users`_ for
-full info.
+You can also use the Python API. See `creating users`_ for full info.
.. _creating users: http://www.djangoproject.com/documentation/authentication/#creating-users
+
+Contributing code
+=================
+
+How can I get started contributing code to Django?
+--------------------------------------------------
+
+Thanks for asking! We've written an entire document devoted to this question.
+It's titled `Contributing to Django`_.
+
+.. _Contributing to Django: http://www.djangoproject.com/documentation/contributing/
+
+I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch?
+--------------------------------------------------------------------------------------------
+
+Don't worry: We're not ignoring you!
+
+It's important to understand there is a difference between "a ticket is being
+ignored" and "a ticket has not been attended to yet." Django's ticket system
+contains hundreds of open tickets, of various degrees of impact on end-user
+functionality, and Django's developers have to review and prioritize.
+
+Besides, if your feature request stands no chance of inclusion in Django, we
+won't ignore it -- we'll just close the ticket. So if your ticket is still
+open, it doesn't mean we're ignoring you; it just means we haven't had time to
+look at it yet.
diff --git a/docs/fastcgi.txt b/docs/fastcgi.txt
index 41d50d97a1..e2f4e933b4 100644
--- a/docs/fastcgi.txt
+++ b/docs/fastcgi.txt
@@ -270,7 +270,7 @@ In your Web root directory, add this to a file named ``.htaccess`` ::
AddHandler fastcgi-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
- RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
+ RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]
Then, create a small script that tells Apache how to spawn your FastCGI
program. Create a file ``mysite.fcgi`` and place it in your Web directory, and
@@ -289,7 +289,7 @@ be sure to make it executable ::
os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings"
from django.core.servers.fastcgi import runfastcgi
- runfastcgi(["method=threaded", "daemonize=false"])
+ runfastcgi(method="threaded", daemonize="false")
Restarting the spawned server
-----------------------------
diff --git a/docs/forms.txt b/docs/forms.txt
index 2fbe373744..4a4ba37289 100644
--- a/docs/forms.txt
+++ b/docs/forms.txt
@@ -136,7 +136,7 @@ template::
{% endblock %}
Before we get back to the problems with these naive set of views, let's go over
-some salient points of the above template::
+some salient points of the above template:
* Field "widgets" are handled for you: ``{{ form.field }}`` automatically
creates the "right" type of widget for the form, as you can see with the
@@ -148,8 +148,8 @@ some salient points of the above template::
If you must use tables, use tables. If you're a semantic purist, you can
probably find better HTML than in the above template.
- * To avoid name conflicts, the ``id``s of form elements take the form
- "id_*fieldname*".
+ * To avoid name conflicts, the ``id`` values of form elements take the
+ form "id_*fieldname*".
By creating a creation form we've solved problem number 3 above, but we still
don't have any validation. Let's revise the validation issue by writing a new
@@ -211,7 +211,7 @@ Below is the finished view::
def create_place(request):
manipulator = Place.AddManipulator()
- if request.POST:
+ if request.method == 'POST':
# If data was POSTed, we're trying to create a new Place.
new_data = request.POST.copy()
@@ -309,7 +309,7 @@ about editing an existing one? It's shockingly similar to creating a new one::
# Grab the Place object in question for future use.
place = manipulator.original_object
- if request.POST:
+ if request.method == 'POST':
new_data = request.POST.copy()
errors = manipulator.get_validation_errors(new_data)
if not errors:
@@ -321,7 +321,7 @@ about editing an existing one? It's shockingly similar to creating a new one::
else:
errors = {}
# This makes sure the form accurate represents the fields of the place.
- new_data = place.__dict__
+ new_data = manipulator.flatten_data()
form = forms.FormWrapper(manipulator, new_data, errors)
return render_to_response('places/edit_form.html', {'form': form, 'place': place})
@@ -336,10 +336,10 @@ The only real differences are:
* ``ChangeManipulator.original_object`` stores the instance of the
object being edited.
- * We set ``new_data`` to the original object's ``__dict__``. This makes
- sure the form fields contain the current values of the object.
- ``FormWrapper`` does not modify ``new_data`` in any way, and templates
- cannot, so this is perfectly safe.
+ * We set ``new_data`` based upon ``flatten_data()`` from the manipulator.
+ ``flatten_data()`` takes the data from the original object under
+ manipulation, and converts it into a data dictionary that can be used
+ to populate form elements with the existing values for the object.
* The above example uses a different template, so create and edit can be
"skinned" differently if needed, but the form chunk itself is completely
@@ -391,7 +391,7 @@ Here's a simple function that might drive the above form::
def contact_form(request):
manipulator = ContactManipulator()
- if request.POST:
+ if request.method == 'POST':
new_data = request.POST.copy()
errors = manipulator.get_validation_errors(new_data)
if not errors:
@@ -405,6 +405,43 @@ Here's a simple function that might drive the above form::
form = forms.FormWrapper(manipulator, new_data, errors)
return render_to_response('contact_form.html', {'form': form})
+``FileField`` and ``ImageField`` special cases
+==============================================
+
+Dealing with ``FileField`` and ``ImageField`` objects is a little more
+complicated.
+
+First, you'll need to make sure that your ``<form>`` element correctly defines
+the ``enctype`` as ``"multipart/form-data"``, in order to upload files::
+
+ <form enctype="multipart/form-data" method="post" action="/foo/">
+
+Next, you'll need to treat the field in the template slightly differently. A
+``FileField`` or ``ImageField`` is represented by *two* HTML form elements.
+
+For example, given this field in a model::
+
+ photo = model.ImageField('/path/to/upload/location')
+
+You'd need to display two formfields in the template::
+
+ <p><label for="id_photo">Photo:</label> {{ form.photo }}{{ form.photo_file }}</p>
+
+The first bit (``{{ form.photo }}``) displays the currently-selected file,
+while the second (``{{ form.photo_file }}``) actually contains the file upload
+form field. Thus, at the validation layer you need to check the ``photo_file``
+key.
+
+Finally, in your view, make sure to access ``request.FILES``, rather than
+``request.POST``, for the uploaded files. This is necessary because
+``request.POST`` does not contain file-upload data.
+
+For example, following the ``new_data`` convention, you might do something like
+this::
+
+ new_data = request.POST.copy()
+ new_data.update(request.FILES)
+
Validators
==========
@@ -444,7 +481,33 @@ the data being validated.
Also, because consistency in user interfaces is important, we strongly urge you
to put punctuation at the end of your validation messages.
-Ready-made Validators
+When are validators called?
+---------------------------
+
+After a form has been submitted, Django first checks to see that all the
+required fields are present and non-empty. For each field that passes that
+test *and if the form submission contained data* for that field, all the
+validators for that field are called in turn. The emphasized portion in the
+last sentence is important: if a form field is not submitted (because it
+contains no data -- which is normal HTML behavior), the validators are not
+run against the field.
+
+This feature is particularly important for models using
+``models.BooleanField`` or custom manipulators using things like
+``forms.CheckBoxField``. If the checkbox is not selected, it will not
+contribute to the form submission.
+
+If you would like your validator to run *always*, regardless of whether its
+attached field contains any data, set the ``always_test`` attribute on the
+validator function. For example::
+
+ def my_custom_validator(field_data, all_data):
+ # ...
+ my_custom_validator.always_test = True
+
+This validator will always be executed for any field it is attached to.
+
+Ready-made validators
---------------------
Writing your own validator is not difficult, but there are some situations
@@ -516,7 +579,7 @@ fails. If no message is passed in, a default message is used.
``ValidateIfOtherFieldEquals``
Takes three parameters: ``other_field``, ``other_value`` and
``validator_list``, in that order. If ``other_field`` has a value of
- ``other_vaue``, then the validators in ``validator_list`` are all run
+ ``other_value``, then the validators in ``validator_list`` are all run
against the current field.
``RequiredIfOtherFieldNotGiven``
diff --git a/docs/generic_views.txt b/docs/generic_views.txt
index d14fe12418..99a9b7cf6b 100644
--- a/docs/generic_views.txt
+++ b/docs/generic_views.txt
@@ -127,7 +127,7 @@ If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410).
This example redirects from ``/foo/<id>/`` to ``/bar/<id>/``::
urlpatterns = patterns('django.views.generic.simple',
- ('^foo/(?p<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}),
+ ('^foo/(?P<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}),
)
This example returns a 410 HTTP error for requests to ``/bar/``::
@@ -148,7 +148,8 @@ are views for displaying drilldown pages for date-based data.
**Description:**
A top-level index page showing the "latest" objects, by date. Objects with
-a date in the *future* are not included.
+a date in the *future* are not included unless you set ``allow_future`` to
+``True``.
**Required arguments:**
@@ -183,7 +184,12 @@ a date in the *future* are not included.
the view's template. See the `RequestContext docs`_.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
- to the value of the ``DEFAULT_MIME_TYPE`` setting.
+ to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
+
+ * ``allow_future``: A boolean specifying whether to include "future"
+ objects on this page, where "future" means objects in which the field
+ specified in ``date_field`` is greater than the current date/time. By
+ default, this is ``False``.
**Template name:**
@@ -217,7 +223,8 @@ In addition to ``extra_context``, the template's context will be:
**Description:**
A yearly archive page showing all available months in a given year. Objects
-with a date in the *future* are not displayed.
+with a date in the *future* are not displayed unless you set ``allow_future``
+to ``True``.
**Required arguments:**
@@ -263,7 +270,12 @@ with a date in the *future* are not displayed.
this is ``False``.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
- to the value of the ``DEFAULT_MIME_TYPE`` setting.
+ to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
+
+ * ``allow_future``: A boolean specifying whether to include "future"
+ objects on this page, where "future" means objects in which the field
+ specified in ``date_field`` is greater than the current date/time. By
+ default, this is ``False``.
**Template name:**
@@ -296,7 +308,8 @@ In addition to ``extra_context``, the template's context will be:
**Description:**
A monthly archive page showing all objects in a given month. Objects with a
-date in the *future* are not displayed.
+date in the *future* are not displayed unless you set ``allow_future`` to
+``True``.
**Required arguments:**
@@ -344,7 +357,12 @@ date in the *future* are not displayed.
determining the variable's name.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
- to the value of the ``DEFAULT_MIME_TYPE`` setting.
+ to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
+
+ * ``allow_future``: A boolean specifying whether to include "future"
+ objects on this page, where "future" means objects in which the field
+ specified in ``date_field`` is greater than the current date/time. By
+ default, this is ``False``.
**Template name:**
@@ -378,7 +396,7 @@ In addition to ``extra_context``, the template's context will be:
**Description:**
A weekly archive page showing all objects in a given week. Objects with a date
-in the *future* are not displayed.
+in the *future* are not displayed unless you set ``allow_future`` to ``True``.
**Required arguments:**
@@ -420,7 +438,12 @@ in the *future* are not displayed.
determining the variable's name.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
- to the value of the ``DEFAULT_MIME_TYPE`` setting.
+ to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
+
+ * ``allow_future``: A boolean specifying whether to include "future"
+ objects on this page, where "future" means objects in which the field
+ specified in ``date_field`` is greater than the current date/time. By
+ default, this is ``False``.
**Template name:**
@@ -445,7 +468,8 @@ In addition to ``extra_context``, the template's context will be:
**Description:**
A day archive page showing all objects in a given day. Days in the future throw
-a 404 error, regardless of whether any objects exist for future days.
+a 404 error, regardless of whether any objects exist for future days, unless
+you set ``allow_future`` to ``True``.
**Required arguments:**
@@ -499,7 +523,12 @@ a 404 error, regardless of whether any objects exist for future days.
determining the variable's name.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
- to the value of the ``DEFAULT_MIME_TYPE`` setting.
+ to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
+
+ * ``allow_future``: A boolean specifying whether to include "future"
+ objects on this page, where "future" means objects in which the field
+ specified in ``date_field`` is greater than the current date/time. By
+ default, this is ``False``.
**Template name:**
@@ -537,7 +566,9 @@ and today's date is used instead.
**Description:**
-A page representing an individual object.
+A page representing an individual object. If the object has a date value in the
+future, the view will throw a 404 error by default, unless you set
+``allow_future`` to ``True``.
**Required arguments:**
@@ -602,7 +633,12 @@ A page representing an individual object.
to use in the template context. By default, this is ``'object'``.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
- to the value of the ``DEFAULT_MIME_TYPE`` setting.
+ to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
+
+ * ``allow_future``: A boolean specifying whether to include "future"
+ objects on this page, where "future" means objects in which the field
+ specified in ``date_field`` is greater than the current date/time. By
+ default, this is ``False``.
**Template name:**
@@ -671,7 +707,7 @@ A page representing a list of objects.
determining the variable's name.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
- to the value of the ``DEFAULT_MIME_TYPE`` setting.
+ to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
**Template name:**
@@ -783,7 +819,7 @@ A page representing an individual object.
to use in the template context. By default, this is ``'object'``.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
- to the value of the ``DEFAULT_MIME_TYPE`` setting.
+ to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
**Template name:**
diff --git a/docs/i18n.txt b/docs/i18n.txt
index 212fb41488..4d0d92b082 100644
--- a/docs/i18n.txt
+++ b/docs/i18n.txt
@@ -48,9 +48,10 @@ bit of i18n-related overhead in certain places of the framework. If you don't
use internationalization, you should take the two seconds to set
``USE_I18N = False`` in your settings file. If ``USE_I18N`` is set to
``False``, then Django will make some optimizations so as not to load the
-internationalization machinery.
+internationalization machinery. See the `documentation for USE_I18N`_.
-See the `documentation for USE_I18N`_.
+You'll probably also want to remove ``'django.core.context_processors.i18n'``
+from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting.
.. _documentation for USE_I18N: http://www.djangoproject.com/documentation/settings/#use-i18n
@@ -224,11 +225,18 @@ block::
This will have {{ myvar }} inside.
{% endblocktrans %}
+If you need to bind more than one expression inside a ``blocktrans`` tag,
+separate the pieces with ``and``::
+
+ {% blocktrans with book|title as book_t and author|title as author_t %}
+ This is {{ book_t }} by {{ author_t }}
+ {% endblocktrans %}
+
To pluralize, specify both the singular and plural forms with the
``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and
``{% endblocktrans %}``. Example::
- {% blocktrans count list|counted as counter %}
+ {% blocktrans count list|count as counter %}
There is only one {{ name }} object.
{% plural %}
There are {{ counter }} {{ name }} objects.
@@ -306,7 +314,7 @@ marked for translation. It creates (or updates) a message file in the directory
``conf/locale``. In the ``de`` example, the file will be
``conf/locale/de/LC_MESSAGES/django.po``.
-If run over your project source tree or your appliation source tree, it will
+If run over your project source tree or your application source tree, it will
do the same, but the location of the locale directory is ``locale/LANG/LC_MESSAGES``
(note the missing ``conf`` prefix).
@@ -349,7 +357,7 @@ A quick explanation:
Long messages are a special case. There, the first string directly after the
``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be
written over the next few lines as one string per line. Those strings are
-directlyconcatenated. Don't forget trailing spaces within the strings;
+directly concatenated. Don't forget trailing spaces within the strings;
otherwise, they'll be tacked together without whitespace!
.. admonition:: Mind your charset
@@ -647,7 +655,7 @@ The ``javascript_catalog`` view
-------------------------------
The main solution to these problems is the ``javascript_catalog`` view, which
-sends out a JavaScript code library with functions that mimick the ``gettext``
+sends out a JavaScript code library with functions that mimic the ``gettext``
interface, plus an array of translation strings. Those translation strings are
taken from the application, project or Django core, according to what you
specify in either the {{{info_dict}}} or the URL.
@@ -665,7 +673,7 @@ You hook it up like this::
Each string in ``packages`` should be in Python dotted-package syntax (the
same format as the strings in ``INSTALLED_APPS``) and should refer to a package
that contains a ``locale`` directory. If you specify multiple packages, all
-those catalogs aremerged into one catalog. This is useful if you have
+those catalogs are merged into one catalog. This is useful if you have
JavaScript that uses strings from different applications.
You can make the view dynamic by putting the packages into the URL pattern::
diff --git a/docs/install.txt b/docs/install.txt
index 800c49b596..ff8e1a8318 100644
--- a/docs/install.txt
+++ b/docs/install.txt
@@ -77,44 +77,54 @@ It's easy either way.
Installing the official version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. Download Django-0.91.tar.gz from our `download page`_.
-2. ``tar xzvf Django-0.91.tar.gz``
-3. ``cd Django-0.91``
+1. Download Django-0.95.tar.gz from our `download page`_.
+2. ``tar xzvf Django-0.95.tar.gz``
+3. ``cd Django-0.95``
4. ``sudo python setup.py install``
Note that the last command will automatically download and install setuptools_
if you don't already have it installed. This requires a working Internet
+connection and may cause problems on Python 2.5. If you run into problems,
+try using our development version by following the instructions below. The
+development version no longer uses setuptools nor requires an Internet
connection.
-This will install Django in your Python installation's ``site-packages``
+The command will install Django in your Python installation's ``site-packages``
directory.
-.. note::
-
- Due to recent backwards-incompatible changes, it is strongly recommended
- that you use the development version (below) for any new applications or
- if you are just starting to work with Django. The 0.91 release is a
- dead-end branch that is primarily of use for supporting legacy Django
- applications.
-
.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
Installing the development version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you'd like to be able to update your Django code occasionally with the
+latest bug fixes and improvements, follow these instructions:
+
1. Make sure you have Subversion_ installed.
-2. ``svn co http://code.djangoproject.com/svn/django/trunk/ django_src``
-3. Symlink ``django_src/django`` so that ``django`` is within your Python
- ``site-packages`` directory:
+2. Check out the Django code into your Python ``site-packages`` directory.
+ On Linux / Mac OSX / Unix, do this::
- ``ln -s `pwd`/django_src/django /usr/lib/python2.3/site-packages/django``
+ svn co http://code.djangoproject.com/svn/django/trunk/ django_src
+ ln -s `pwd`/django_src/django /usr/lib/python2.3/site-packages/django
(In the above line, change ``python2.3`` to match your current Python version.)
-You don't have to run ``python setup.py install``.
+ On Windows, do this::
+
+ svn co http://code.djangoproject.com/svn/django/trunk/django c:\Python24\lib\site-packages\django
+
+4. Copy the file ``django_src/django/bin/django-admin.py`` to somewhere on your
+ system path, such as ``/usr/local/bin`` (Unix) or ``C:\Python24\Scripts``
+ (Windows). This step simply lets you type ``django-admin.py`` from within
+ any directory, rather than having to qualify the command with the full path
+ to the file.
+
+You *don't* have to run ``python setup.py install``, because that command
+takes care of steps 3 and 4 for you.
-When you want to update your code, just run the command ``svn update`` from
-within the ``django_src`` directory.
+When you want to update your copy of the Django source code, just run the
+command ``svn update`` from within the ``django`` directory. When you do this,
+Subversion will automatically download any changes.
.. _`download page`: http://www.djangoproject.com/download/
.. _Subversion: http://subversion.tigris.org/
diff --git a/docs/middleware.txt b/docs/middleware.txt
index bad00fd890..efc4d89569 100644
--- a/docs/middleware.txt
+++ b/docs/middleware.txt
@@ -63,7 +63,7 @@ Adds a few conveniences for perfectionists:
last component in the path contains a period. So ``foo.com/bar`` is
redirected to ``foo.com/bar/``, but ``foo.com/bar/file.txt`` is passed
through unchanged.
-
+
If ``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be
redirected to the same URL with a leading "www."
@@ -101,6 +101,22 @@ Handles conditional GET operations. If the response has a ``ETag`` or
Also removes the content from any response to a HEAD request and sets the
``Date`` and ``Content-Length`` response-headers.
+django.middleware.http.SetRemoteAddrFromForwardedFor
+----------------------------------------------------
+
+**New in Django development version**
+
+Sets ``request['REMOTE_ADDR']`` based on ``request.['HTTP_X_FORWARDED_FOR']``,
+if the latter is set. This is useful if you're sitting behind a reverse proxy
+that causes each request's ``REMOTE_ADDR`` to be set to ``127.0.0.1``.
+
+**Important note:** This does NOT validate ``HTTP_X_FORWARDED_FOR``. If you're
+not behind a reverse proxy that sets ``HTTP_X_FORWARDED_FOR`` automatically, do
+not use this middleware. Anybody can spoof the value of
+``HTTP_X_FORWARDED_FOR``, and because this sets ``REMOTE_ADDR`` based on
+``HTTP_X_FORWARDED_FOR``, that means anybody can "fake" their IP address. Only
+use this when you can absolutely trust the value of ``HTTP_X_FORWARDED_FOR``.
+
django.contrib.sessions.middleware.SessionMiddleware
----------------------------------------------------
diff --git a/docs/model-api.txt b/docs/model-api.txt
index c4d57bf8c4..1aa8c811f4 100644
--- a/docs/model-api.txt
+++ b/docs/model-api.txt
@@ -188,7 +188,8 @@ JavaScript shortcuts.
~~~~~~~~~~~~~~
A ``CharField`` that checks that the value is a valid e-mail address.
-This doesn't accept ``maxlength``.
+This doesn't accept ``maxlength``; its ``maxlength`` is automatically set to
+75.
``FileField``
~~~~~~~~~~~~~
@@ -217,12 +218,27 @@ steps:
subdirectory of ``MEDIA_ROOT`` it should upload files.
3. All that will be stored in your database is a path to the file
- (relative to ``MEDIA_ROOT``). You'll must likely want to use the
+ (relative to ``MEDIA_ROOT``). You'll most likely want to use the
convenience ``get_<fieldname>_url`` function provided by Django. For
example, if your ``ImageField`` is called ``mug_shot``, you can get
the absolute URL to your image in a template with ``{{
object.get_mug_shot_url }}``.
+For example, say your ``MEDIA_ROOT`` is set to ``'/home/media'``, and
+``upload_to`` is set to ``'photos/%Y/%m/%d'``. The ``'%Y/%m/%d'`` part of
+``upload_to`` is strftime formatting; ``'%Y'`` is the four-digit year,
+``'%m'`` is the two-digit month and ``'%d'`` is the two-digit day. If you
+upload a file on Jan. 15, 2007, it will be saved in the directory
+``/home/media/photos/2007/01/15``.
+
+Note that whenever you deal with uploaded files, you should pay close attention
+to where you're uploading them and what type of files they are, to avoid
+security holes. *Validate all uploaded files* so that you're sure the files are
+what you think they are. For example, if you blindly let somebody upload files,
+without validation, to a directory that's within your Web server's document
+root, then somebody could upload a CGI or PHP script and execute that script by
+visiting its URL on your site. Don't allow that.
+
.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941
``FilePathField``
@@ -528,7 +544,9 @@ The default value for the field.
``editable``
~~~~~~~~~~~~
-If ``False``, the field will not be editable in the admin. Default is ``True``.
+If ``False``, the field will not be editable in the admin or via form
+processing using the object's ``AddManipulator`` or ``ChangeManipulator``
+classes. Default is ``True``.
``help_text``
~~~~~~~~~~~~~
@@ -671,8 +689,9 @@ you can use the name of the model, rather than the model object itself::
class Manufacturer(models.Model):
# ...
-Note, however, that support for strings around model names in ``ForeignKey`` is
-quite new, and it can be buggy in some cases.
+Note, however, that you can only use strings to refer to models in the same
+models.py file -- you cannot use a string to reference a model in a different
+application, or to reference a model that has been imported from elsewhere.
Behind the scenes, Django appends ``"_id"`` to the field name to create its
database column name. In the above example, the database table for the ``Car``
@@ -794,7 +813,10 @@ here's how you'd represent that::
As with ``ForeignKey``, a relationship to self can be defined by using the
string ``'self'`` instead of the model name, and you can refer to as-yet
-undefined models by using a string containing the model name.
+undefined models by using a string containing the model name. However, you
+can only use strings to refer to models in the same models.py file -- you
+cannot use a string to reference a model in a different application, or to
+reference a model that has been imported from elsewhere.
It's suggested, but not required, that the name of a ``ManyToManyField``
(``toppings`` in the example above) be a plural describing the set of related
@@ -1203,10 +1225,13 @@ A few special cases to note about ``list_display``:
of the related object.
* ``ManyToManyField`` fields aren't supported, because that would entail
- executing a separate SQL statement for each row in the table.
+ executing a separate SQL statement for each row in the table. If you
+ want to do this nonetheless, give your model a custom method, and add
+ that method's name to ``list_display``. (See below for more on custom
+ methods in ``list_display``.)
- * If the field is a ``BooleanField``, Django will display a pretty "on" or
- "off" icon instead of ``True`` or ``False``.
+ * If the field is a ``BooleanField`` or ``NullBooleanField``, Django will
+ display a pretty "on" or "off" icon instead of ``True`` or ``False``.
* If the string given is a method of the model, Django will call it and
display the output. This method should have a ``short_description``
@@ -1225,6 +1250,34 @@ A few special cases to note about ``list_display``:
return self.birthday.strftime('%Y')[:3] + "0's"
decade_born_in.short_description = 'Birth decade'
+ * If the string given is a method of the model, Django will HTML-escape the
+ output by default. If you'd rather not escape the output of the method,
+ give the method an ``allow_tags`` attribute whose value is ``True``.
+
+ Here's a full example model::
+
+ class Person(models.Model):
+ first_name = models.CharField(maxlength=50)
+ last_name = models.CharField(maxlength=50)
+ color_code = models.CharField(maxlength=6)
+
+ class Admin:
+ list_display = ('first_name', 'last_name', 'colored_name')
+
+ def colored_name(self):
+ return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name)
+ colored_name.allow_tags = True
+
+ * The ``__str__()`` method is just as valid in ``list_display`` as any
+ other model method, so it's perfectly OK to do this::
+
+ list_display = ('__str__', 'some_other_field')
+
+ * For any element of ``list_display`` that is not a field on the model, the
+ change list page will not allow ordering by that column. This is because
+ ordering is done at the database level, and Django has no way of knowing
+ how to order the result of a custom method at the SQL level.
+
``list_display_links``
----------------------
@@ -1349,6 +1402,41 @@ user searches for ``john lennon``, Django will do the equivalent of this SQL
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
+**New in Django development version:** For faster and/or more restrictive
+searches, prefix the field name with an operator:
+
+``^``
+ Matches the beginning of the field. For example, if ``search_fields`` is
+ set to ``['^first_name', '^last_name']`` and a user searches for
+ ``john lennon``, Django will do the equivalent of this SQL ``WHERE``
+ clause::
+
+ WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%')
+ AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
+
+ This query is more efficient than the normal ``'%john%'`` query, because
+ the database only needs to check the beginning of a column's data, rather
+ than seeking through the entire column's data. Plus, if the column has an
+ index on it, some databases may be able to use the index for this query,
+ even though it's a ``LIKE`` query.
+
+``=``
+ Matches exactly, case-insensitive. For example, if
+ ``search_fields`` is set to ``['=first_name', '=last_name']`` and
+ a user searches for ``john lennon``, Django will do the equivalent
+ of this SQL ``WHERE`` clause::
+
+ WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john')
+ AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')
+
+ Note that the query input is split by spaces, so, following this example,
+ it's not currently not possible to search for all records in which
+ ``first_name`` is exactly ``'john winston'`` (containing a space).
+
+``@``
+ Performs a full-text match. This is like the default search method but uses
+ an index. Currently this is only available for MySQL.
+
Managers
========
diff --git a/docs/overview.txt b/docs/overview.txt
index 5a399582e8..8e6274dd9a 100644
--- a/docs/overview.txt
+++ b/docs/overview.txt
@@ -159,7 +159,7 @@ of contents for your app, it contains a simple mapping between URL patterns and
Python callback functions. URLconfs also serve to decouple URLs from Python
code.
-Here's what a URLconf might look like for the above ``Reporter``/``Article``
+Here's what a URLconf might look like for the ``Reporter``/``Article``
example above::
from django.conf.urls.defaults import *
diff --git a/docs/release_notes_0.95.txt b/docs/release_notes_0.95.txt
new file mode 100644
index 0000000000..3709cacf5a
--- /dev/null
+++ b/docs/release_notes_0.95.txt
@@ -0,0 +1,126 @@
+=================================
+Django version 0.95 release notes
+=================================
+
+
+Welcome to the Django 0.95 release.
+
+This represents a significant advance in Django development since the 0.91
+release in January 2006. The details of every change in this release would be
+too extensive to list in full, but a summary is presented below.
+
+Suitability and API stability
+=============================
+
+This release is intended to provide a stable reference point for developers
+wanting to work on production-level applications that use Django.
+
+However, it's not the 1.0 release, and we'll be introducing further changes
+before 1.0. For a clear look at which areas of the framework will change (and
+which ones will *not* change) before 1.0, see the api-stability.txt file, which
+lives in the docs/ directory of the distribution.
+
+You may have a need to use some of the features that are marked as
+"subject to API change" in that document, but that's OK with us as long as it's
+OK with you, and as long as you understand APIs may change in the future.
+
+Fortunately, most of Django's core APIs won't be changing before version 1.0.
+There likely won't be as big of a change between 0.95 and 1.0 versions as there
+was between 0.91 and 0.95.
+
+Changes and new features
+========================
+
+The major changes in this release (for developers currently using the 0.91
+release) are a result of merging the 'magic-removal' branch of development.
+This branch removed a number of constraints in the way Django code had to be
+written that were a consequence of decisions made in the early days of Django,
+prior to its open-source release. It's now possible to write more natural,
+Pythonic code that works as expected, and there's less "black magic" happening
+behind the scenes.
+
+Aside from that, another main theme of this release is a dramatic increase in
+usability. We've made countless improvements in error messages, documentation,
+etc., to improve developers' quality of life.
+
+The new features and changes introduced in 0.95 include:
+
+ * Django now uses a more consistent and natural filtering interface for
+ retrieving objects from the database.
+
+ * User-defined models, functions and constants now appear in the module
+ namespace they were defined in. (Previously everything was magically
+ transferred to the django.models.* namespace.)
+
+ * Some optional applications, such as the FlatPage, Sites and Redirects
+ apps, have been decoupled and moved into django.contrib. If you don't
+ want to use these applications, you no longer have to install their
+ database tables.
+
+ * Django now has support for managing database transactions.
+
+ * We've added the ability to write custom authentication and authorization
+ backends for authenticating users against alternate systems, such as
+ LDAP.
+
+ * We've made it easier to add custom table-level functions to models,
+ through a new "Manager" API.
+
+ * It's now possible to use Django without a database. This simply means
+ that the framework no longer requires you to have a working database set
+ up just to serve dynamic pages. In other words, you can just use
+ URLconfs/views on their own. Previously, the framework required that a
+ database be configured, regardless of whether you actually used it.
+
+ * It's now more explicit and natural to override save() and delete()
+ methods on models, rather than needing to hook into the pre_save() and
+ post_save() method hooks.
+
+ * Individual pieces of the framework now can be configured without
+ requiring the setting of an environment variable. This permits use of,
+ for example, the Django templating system inside other applications.
+
+ * More and more parts of the framework have been internationalized, as
+ we've expanded internationalization (i18n) support. The Django
+ codebase, including code and templates, has now been translated, at least
+ in part, into 31 languages. From Arabic to Chinese to Hungarian to Welsh,
+ it is now possible to use Django's admin site in your native language.
+
+The number of changes required to port from 0.91-compatible code to the 0.95
+code base are significant in some cases. However, they are, for the most part,
+reasonably routine and only need to be done once. A list of the necessary
+changes is described in the `Removing The Magic`_ wiki page. There is also an
+easy checklist_ for reference when undertaking the porting operation.
+
+.. _Removing The Magic: http://code.djangoproject.com/wiki/RemovingTheMagic
+.. _checklist: http://code.djangoproject.com/wiki/MagicRemovalCheatSheet1
+
+Problem reports and getting help
+================================
+
+Need help resolving a problem with Django? The documentation in the
+distribution is also available online_ at the `Django website`_. The FAQ_
+document is especially recommended, as it contains a number of issues that
+come up time and again.
+
+For more personalized help, the `django-users`_ mailing list is a very active
+list, with more than 2,000 subscribers who can help you solve any sort of
+Django problem. We recommend you search the archives first, though, because
+many common questions appear with some regularity, and any particular problem
+may already have been answered.
+
+Finally, for those who prefer the more immediate feedback offered by IRC,
+there's a #django channel on irc.freenode.net that is regularly populated by
+Django users and developers from around the world. Friendly people are usually
+available at any hour of the day -- to help, or just to chat.
+
+.. _online: http://www.djangoproject.com/documentation/
+.. _Django website: http://www.djangoproject.com/
+.. _FAQ: http://www.djangoproject.com/documentation/faq/
+.. _django-users: http://groups.google.com/group/django-users
+
+Thanks for using Django!
+
+The Django Team
+July 2006
+
diff --git a/docs/request_response.txt b/docs/request_response.txt
index 0bcb3a7f5b..006ac6b648 100644
--- a/docs/request_response.txt
+++ b/docs/request_response.txt
@@ -106,12 +106,12 @@ All attributes except ``session`` should be considered read-only.
A ``django.contrib.auth.models.User`` object representing the currently
logged-in user. If the user isn't currently logged in, ``user`` will be set
to an instance of ``django.contrib.auth.models.AnonymousUser``. You
- can tell them apart with ``is_anonymous()``, like so::
+ can tell them apart with ``is_authenticated()``, like so::
- if request.user.is_anonymous():
- # Do something for anonymous users.
- else:
+ if request.user.is_authenticated():
# Do something for logged-in users.
+ else:
+ # Do something for anonymous users.
``user`` is only available if your Django installation has the
``AuthenticationMiddleware`` activated. For more, see
@@ -134,21 +134,25 @@ Methods
-------
``__getitem__(key)``
- Returns the GET/POST value for the given key, checking POST first, then
- GET. Raises ``KeyError`` if the key doesn't exist.
+ Returns the GET/POST value for the given key, checking POST first, then
+ GET. Raises ``KeyError`` if the key doesn't exist.
- This lets you use dictionary-accessing syntax on an ``HttpRequest``
- instance. Example: ``request["foo"]`` would return ``True`` if either
- ``request.POST`` or ``request.GET`` had a ``"foo"`` key.
+ This lets you use dictionary-accessing syntax on an ``HttpRequest``
+ instance. Example: ``request["foo"]`` would return ``True`` if either
+ ``request.POST`` or ``request.GET`` had a ``"foo"`` key.
``has_key()``
- Returns ``True`` or ``False``, designating whether ``request.GET`` or
- ``request.POST`` has the given key.
+ Returns ``True`` or ``False``, designating whether ``request.GET`` or
+ ``request.POST`` has the given key.
``get_full_path()``
- Returns the ``path``, plus an appended query string, if applicable.
+ Returns the ``path``, plus an appended query string, if applicable.
+
+ Example: ``"/music/bands/the_beatles/?print=true"``
- Example: ``"/music/bands/the_beatles/?print=true"``
+``is_secure()``
+ Returns ``True`` if the request is secure; that is, if it was made with
+ HTTPS.
QueryDict objects
-----------------
@@ -337,9 +341,9 @@ hard-coded strings. If you use this technique, follow these guidelines:
Methods
-------
-``__init__(content='', mimetype=DEFAULT_MIME_TYPE)``
+``__init__(content='', mimetype=DEFAULT_CONTENT_TYPE)``
Instantiates an ``HttpResponse`` object with the given page content (a
- string) and MIME type. The ``DEFAULT_MIME_TYPE`` is ``'text/html'``.
+ string) and MIME type. The ``DEFAULT_CONTENT_TYPE`` is ``'text/html'``.
``content`` can be an iterator or a string. If it's an iterator, it should
return strings, and those strings will be joined together to form the
@@ -376,10 +380,14 @@ Methods
.. _`cookie Morsel`: http://www.python.org/doc/current/lib/morsel-objects.html
-``delete_cookie(key)``
+``delete_cookie(key, path='/', domain=None)``
Deletes the cookie with the given key. Fails silently if the key doesn't
exist.
+ The ``path`` and ``domain`` arguments are new in the Django development version.
+ Due to the way cookies work, ``path`` and ``domain`` should be the same
+ values you used in ``set_cookie()`` -- otherwise the cookie may not be deleted.
+
``content``
Returns the content as a Python string, encoding it from a Unicode object
if necessary. Note this is a property, not a method, so use ``r.content``
diff --git a/docs/serialization.txt b/docs/serialization.txt
index 25199e7a50..aee1b9a3bb 100644
--- a/docs/serialization.txt
+++ b/docs/serialization.txt
@@ -3,12 +3,12 @@ Serializing Django objects
==========================
.. note::
-
+
This API is currently under heavy development and may change --
perhaps drastically -- in the future.
-
+
You have been warned.
-
+
Django's serialization framework provides a mechanism for "translating" Django
objects into other formats. Usually these other formats will be text-based and
used for sending Django objects over a wire, but it's possible for a
@@ -21,7 +21,7 @@ At the highest level, serializing data is a very simple operation::
from django.core import serializers
data = serializers.serialize("xml", SomeModel.objects.all())
-
+
The arguments to the ``serialize`` function are the format to serialize the
data to (see `Serialization formats`_) and a QuerySet_ to serialize.
(Actually, the second argument can be any iterator that yields Django objects,
@@ -34,7 +34,7 @@ You can also use a serializer object directly::
xml_serializer = serializers.get_serializer("xml")
xml_serializer.serialize(queryset)
data = xml_serializer.getvalue()
-
+
This is useful if you want to serialize data directly to a file-like object
(which includes a HTTPResponse_)::
@@ -50,7 +50,7 @@ Deserializing data is also a fairly simple operation::
for obj in serializers.deserialize("xml", data):
do_something_with(obj)
-
+
As you can see, the ``deserialize`` function takes the same format argument as
``serialize``, a string or stream of data, and returns an iterator.
@@ -69,7 +69,7 @@ something like::
for deserialized_object in serializers.deserialize("xml", data):
if object_should_be_saved(deserialized_object):
obj.save()
-
+
In other words, the usual use is to examine the deserialized objects to make
sure that they are "appropriate" for saving before doing so. Of course, if you trust your data source you could just save the object and move on.
@@ -89,13 +89,28 @@ Django "ships" with a few included serializers:
bundled with Django).
``python`` Translates to and from "simple" Python objects (lists, dicts,
- strings, etc.). Not really all that useful on its own, but
+ strings, etc.). Not really all that useful on its own, but
used as a base for other serializers.
========== ==============================================================
.. _json: http://json.org/
.. _simplejson: http://undefined.org/python/#simplejson
+Notes for specific serialization formats
+----------------------------------------
+
+json
+~~~~
+
+If you're using UTF-8 (or any other non-ASCII encoding) data with the JSON
+serializer, you must pass ``ensure_ascii=False`` as a parameter to the
+``serialize()`` call. Otherwise, the output won't be encoded correctly.
+
+For example::
+
+ json_serializer = serializers.get_serializer("json")
+ json_serializer.serialize(queryset, ensure_ascii=False, stream=response)
+
Writing custom serializers
``````````````````````````
diff --git a/docs/sessions.txt b/docs/sessions.txt
index c473d0a3db..d39f42c3bf 100644
--- a/docs/sessions.txt
+++ b/docs/sessions.txt
@@ -245,6 +245,17 @@ Default: ``'sessionid'``
The name of the cookie to use for sessions. This can be whatever you want.
+SESSION_COOKIE_SECURE
+---------------------
+
+**New in Django development version**
+
+Default: ``False``
+
+Whether to use a secure cookie for the session cookie. If this is set to
+``True``, the cookie will be marked as "secure," which means browsers may
+ensure that the cookie is only sent under an HTTPS connection.
+
SESSION_EXPIRE_AT_BROWSER_CLOSE
-------------------------------
diff --git a/docs/settings.txt b/docs/settings.txt
index 5b75e29172..272b20f753 100644
--- a/docs/settings.txt
+++ b/docs/settings.txt
@@ -401,15 +401,6 @@ Subject-line prefix for e-mail messages sent with ``django.core.mail.mail_admins
or ``django.core.mail.mail_managers``. You'll probably want to include the
trailing space.
-ENABLE_PSYCO
-------------
-
-Default: ``False``
-
-Whether to enable Psyco, which optimizes Python code. Requires Psyco_.
-
-.. _Psyco: http://psyco.sourceforge.net/
-
IGNORABLE_404_ENDS
------------------
@@ -473,25 +464,36 @@ LANGUAGES
Default: A tuple of all available languages. Currently, this is::
LANGUAGES = (
+ ('ar', _('Arabic')),
('bn', _('Bengali')),
('cs', _('Czech')),
('cy', _('Welsh')),
('da', _('Danish')),
('de', _('German')),
+ ('el', _('Greek')),
('en', _('English')),
('es', _('Spanish')),
+ ('es_AR', _('Argentinean Spanish')),
('fr', _('French')),
('gl', _('Galician')),
+ ('hu', _('Hungarian')),
+ ('he', _('Hebrew')),
('is', _('Icelandic')),
('it', _('Italian')),
+ ('ja', _('Japanese')),
+ ('nl', _('Dutch')),
('no', _('Norwegian')),
('pt-br', _('Brazilian')),
('ro', _('Romanian')),
('ru', _('Russian')),
('sk', _('Slovak')),
+ ('sl', _('Slovenian')),
('sr', _('Serbian')),
('sv', _('Swedish')),
+ ('ta', _('Tamil')),
+ ('uk', _('Ukrainian')),
('zh-cn', _('Simplified Chinese')),
+ ('zh-tw', _('Traditional Chinese')),
)
A tuple of two-tuples in the format (language code, language name). This
@@ -526,7 +528,7 @@ any code that uses ``LANGUAGES`` at runtime.
MANAGERS
--------
-Default: ``ADMINS`` (Whatever ``ADMINS`` is set to)
+Default: ``()`` (Empty tuple)
A tuple in the same format as ``ADMINS`` that specifies who should get
broken-link notifications when ``SEND_BROKEN_LINK_EMAILS=True``.
@@ -585,6 +587,15 @@ Whether to prepend the "www." subdomain to URLs that don't have it. This is
only used if ``CommonMiddleware`` is installed (see the `middleware docs`_).
See also ``APPEND_SLASH``.
+PROFANITIES_LIST
+----------------
+
+A tuple of profanities, as strings, that will trigger a validation error when
+the ``hasNoProfanities`` validator is called.
+
+We don't list the default values here, because that would be profane. To see
+the default values, see the file ``django/conf/global_settings.py``.
+
ROOT_URLCONF
------------
@@ -647,6 +658,18 @@ Default: ``'sessionid'``
The name of the cookie to use for sessions. This can be whatever you want.
See the `session docs`_.
+SESSION_COOKIE_SECURE
+---------------------
+
+**New in Django development version**
+
+Default: ``False``
+
+Whether to use a secure cookie for the session cookie. If this is set to
+``True``, the cookie will be marked as "secure," which means browsers may
+ensure that the cookie is only sent under an HTTPS connection.
+See the `session docs`_.
+
SESSION_EXPIRE_AT_BROWSER_CLOSE
-------------------------------
@@ -731,6 +754,30 @@ misspelled) variables. See `How invalid variables are handled`_.
.. _How invalid variables are handled: http://www.djangoproject.com/documentation/templates_python/#how-invalid-variables-are-handled
+TEST_RUNNER
+-----------
+
+**New in Django development version**
+
+Default: ``'django.test.simple.run_tests'``
+
+The name of the method to use for starting the test suite. See
+`Testing Django Applications`_.
+
+.. _Testing Django Applications: ../testing/
+
+TEST_DATABASE_NAME
+------------------
+
+**New in Django development version**
+
+Default: ``None``
+
+The name of database to use when running the test suite. If a value of
+``None`` is specified, the test database will use the name ``'test_' + settings.DATABASE_NAME``. See `Testing Django Applications`_.
+
+.. _Testing Django Applications: ../testing/
+
TIME_FORMAT
-----------
@@ -760,6 +807,13 @@ Note that this is the time zone to which Django will convert all dates/times --
not necessarily the timezone of the server. For example, one server may serve
multiple Django-powered sites, each with a separate time-zone setting.
+Normally, Django sets the ``os.environ['TZ']`` variable to the time zone you
+specify in the ``TIME_ZONE`` setting. Thus, all your views and models will
+automatically operate in the correct time zone. However, if you're using the
+manual configuration option (see below), Django will *not* touch the ``TZ``
+environment variable, and it'll be up to you to ensure your processes are
+running in the correct environment.
+
USE_ETAGS
---------
@@ -837,6 +891,15 @@ uppercase, with the same name as the settings described above. If a particular
setting is not passed to ``configure()`` and is needed at some later point,
Django will use the default setting value.
+Configuring Django in this fashion is mostly necessary -- and, indeed,
+recommended -- when you're using a piece of the framework inside a larger
+application.
+
+Consequently, when configured via ``settings.configure()``, Django will not
+make any modifications to the process environment variables. (See the
+explanation of ``TIME_ZONE``, above, for why this would normally occur.) It's
+assumed that you're already in full control of your environment in these cases.
+
Custom default settings
-----------------------
diff --git a/docs/sitemaps.txt b/docs/sitemaps.txt
new file mode 100644
index 0000000000..fec65572f2
--- /dev/null
+++ b/docs/sitemaps.txt
@@ -0,0 +1,320 @@
+=====================
+The sitemap framework
+=====================
+
+**New in Django development version**.
+
+Django comes with a high-level sitemap-generating framework that makes
+creating `Google Sitemap`_ XML files easy.
+
+.. _Google Sitemap: http://www.google.com/webmasters/sitemaps/docs/en/protocol.html
+
+Overview
+========
+
+A sitemap is an XML file on your Web site that tells search-engine indexers how
+frequently your pages change and how "important" certain pages are in relation
+to other pages on your site. This information helps search engines index your
+site.
+
+The Django sitemap framework automates the creation of this XML file by letting
+you express this information in Python code.
+
+It works much like Django's `syndication framework`_. To create a sitemap, just
+write a ``Sitemap`` class and point to it in your URLconf_.
+
+.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
+.. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
+
+Installation
+============
+
+To install the sitemap app, follow these steps:
+
+ 1. Add ``'django.contrib.sitemaps'`` to your INSTALLED_APPS_ setting.
+ 2. Make sure ``'django.template.loaders.app_directories.load_template_source'``
+ is in your TEMPLATE_LOADERS_ setting. It's in there by default, so
+ you'll only need to change this if you've changed that setting.
+ 3. Make sure you've installed the `sites framework`_.
+
+(Note: The sitemap application doesn't install any database tables. The only
+reason it needs to go into ``INSTALLED_APPS`` is so that the
+``load_template_source`` template loader can find the default templates.)
+
+.. _INSTALLED_APPS: http://www.djangoproject.com/documentation/settings/#installed-apps
+.. _TEMPLATE_LOADERS: http://www.djangoproject.com/documentation/settings/#template-loaders
+.. _sites framework: http://www.djangoproject.com/documentation/sites/
+
+Initialization
+==============
+
+To activate sitemap generation on your Django site, add this line to your
+URLconf_:
+
+ (r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})
+
+This tells Django to build a sitemap when a client accesses ``/sitemap.xml``.
+
+The name of the sitemap file is not important, but the location is. Google will
+only index links in your sitemap for the current URL level and below. For
+instance, if ``sitemap.xml`` lives in your root directory, it may reference any
+URL in your site. However, if your sitemap lives at ``/content/sitemap.xml``,
+it may only reference URLs that begin with ``/content/``.
+
+The sitemap view takes an extra, required argument: ``{'sitemaps': sitemaps}``.
+``sitemaps`` should be a dictionary that maps a short section label (e.g.,
+``blog`` or ``news``) to its ``Sitemap`` class (e.g., ``BlogSitemap`` or
+``NewsSitemap``). It may also map to an *instance* of a ``Sitemap`` class
+(e.g., ``BlogSitemap(some_var)``).
+
+.. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
+
+Sitemap classes
+===============
+
+A ``Sitemap`` class is a simple Python class that represents a "section" of
+entries in your sitemap. For example, one ``Sitemap`` class could represent all
+the entries of your weblog, while another could represent all of the events in
+your events calendar.
+
+In the simplest case, all these sections get lumped together into one
+``sitemap.xml``, but it's also possible to use the framework to generate a
+sitemap index that references individual sitemap files, one per section. (See
+`Creating a sitemap index`_ below.)
+
+``Sitemap`` classes must subclass ``django.contrib.sitemaps.Sitemap``. They can
+live anywhere in your codebase.
+
+A simple example
+================
+
+Let's assume you have a blog system, with an ``Entry`` model, and you want your
+sitemap to include all the links to your individual blog entries. Here's how
+your sitemap class might look::
+
+ from django.contrib.sitemaps import Sitemap
+ from mysite.blog.models import Entry
+
+ class BlogSitemap(Sitemap):
+ changefreq = "never"
+ priority = 0.5
+
+ def items(self):
+ return Entry.objects.filter(is_draft=False)
+
+ def lastmod(self, obj):
+ return obj.pub_date
+
+Note:
+
+ * ``changefreq`` and ``priority`` are class attributes corresponding to
+ ``<changefreq>`` and ``<priority>`` elements, respectively. They can be
+ made callable as functions, as ``lastmod`` was in the example.
+ * ``items()`` is simply a method that returns a list of objects. The objects
+ returned will get passed to any callable methods corresponding to a
+ sitemap property (``location``, ``lastmod``, ``changefreq``, and
+ ``priority``).
+ * ``lastmod`` should return a Python ``datetime`` object.
+ * There is no ``location`` method in this example, but you can provide it
+ in order to specify the URL for your object. By default, ``location()``
+ calls ``get_absolute_url()`` on each object and returns the result.
+
+Sitemap class reference
+=======================
+
+A ``Sitemap`` class can define the following methods/attributes:
+
+``items``
+---------
+
+**Required.** A method that returns a list of objects. The framework doesn't
+care what *type* of objects they are; all that matters is that these objects
+get passed to the ``location()``, ``lastmod()``, ``changefreq()`` and
+``priority()`` methods.
+
+``location``
+------------
+
+**Optional.** Either a method or attribute.
+
+If it's a method, it should return the absolute URL for a given object as
+returned by ``items()``.
+
+If it's an attribute, its value should be a string representing an absolute URL
+to use for *every* object returned by ``items()``.
+
+In both cases, "absolute URL" means a URL that doesn't include the protocol or
+domain. Examples:
+
+ * Good: ``'/foo/bar/'``
+ * Bad: ``'example.com/foo/bar/'``
+ * Bad: ``'http://example.com/foo/bar/'``
+
+If ``location`` isn't provided, the framework will call the
+``get_absolute_url()`` method on each object as returned by ``items()``.
+
+``lastmod``
+-----------
+
+**Optional.** Either a method or attribute.
+
+If it's a method, it should take one argument -- an object as returned by
+``items()`` -- and return that object's last-modified date/time, as a Python
+``datetime.datetime`` object.
+
+If it's an attribute, its value should be a Python ``datetime.datetime`` object
+representing the last-modified date/time for *every* object returned by
+``items()``.
+
+``changefreq``
+--------------
+
+**Optional.** Either a method or attribute.
+
+If it's a method, it should take one argument -- an object as returned by
+``items()`` -- and return that object's change frequency, as a Python string.
+
+If it's an attribute, its value should be a string representing the change
+frequency of *every* object returned by ``items()``.
+
+Possible values for ``changefreq``, whether you use a method or attribute, are:
+
+ * ``'always'``
+ * ``'hourly'``
+ * ``'daily'``
+ * ``'weekly'``
+ * ``'monthly'``
+ * ``'yearly'``
+ * ``'never'``
+
+``priority``
+------------
+
+**Optional.** Either a method or attribute.
+
+If it's a method, it should take one argument -- an object as returned by
+``items()`` -- and return that object's priority, as either a string or float.
+
+If it's an attribute, its value should be either a string or float representing
+the priority of *every* object returned by ``items()``.
+
+Example values for ``priority``: ``0.4``, ``1.0``. The default priority of a
+page is ``0.5``. See Google's documentation for more documentation.
+
+.. _Google's documentation: http://www.google.com/webmasters/sitemaps/docs/en/protocol.html
+
+Shortcuts
+=========
+
+The sitemap framework provides a couple convenience classes for common cases:
+
+``FlatPageSitemap``
+-------------------
+
+The ``django.contrib.sitemaps.FlatPageSitemap`` class looks at all flatpages_
+defined for the current ``SITE_ID`` (see the `sites documentation`_) and
+creates an entry in the sitemap. These entries include only the ``location``
+attribute -- not ``lastmod``, ``changefreq`` or ``priority``.
+
+.. _flatpages: http://www.djangoproject.com/documentation/flatpages/
+.. _sites documentation: http://www.djangoproject.com/documentation/sites/
+
+``GenericSitemap``
+------------------
+
+The ``GenericSitemap`` class works with any `generic views`_ you already have.
+To use it, create an instance, passing in the same ``info_dict`` you pass to
+the generic views. The only requirement is that the dictionary have a
+``queryset`` entry. It may also have a ``date_field`` entry that specifies a
+date field for objects retrieved from the ``queryset``. This will be used for
+the ``lastmod`` attribute in the generated sitemap. You may also pass
+``priority`` and ``changefreq`` keyword arguments to the ``GenericSitemap``
+constructor to specify these attributes for all URLs.
+
+.. _generic views: http://www.djangoproject.com/documentation/generic_views/
+
+Example
+-------
+
+Here's an example of a URLconf_ using both::
+
+ from django.conf.urls.defaults import *
+ from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap
+ from mysite.blog.models import Entry
+
+ info_dict = {
+ 'queryset': Entry.objects.all(),
+ 'date_field': 'pub_date',
+ }
+
+ sitemaps = {
+ 'flatpages': FlatPageSitemap,
+ 'blog': GenericSitemap(info_dict, priority=0.6),
+ }
+
+ urlpatterns = patterns('',
+ # some generic view using info_dict
+ # ...
+
+ # the sitemap
+ (r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})
+ )
+
+.. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
+
+Creating a sitemap index
+========================
+
+The sitemap framework also has the ability to create a sitemap index that
+references individual sitemap files, one per each section defined in your
+``sitemaps`` dictionary. The only differences in usage are:
+
+ * You use two views in your URLconf: ``django.contrib.sitemaps.views.index``
+ and ``django.contrib.sitemaps.views.sitemap``.
+ * The ``django.contrib.sitemaps.views.sitemap`` view should take a
+ ``section`` keyword argument.
+
+Here is what the relevant URLconf lines would look like for the example above::
+
+ (r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps})
+ (r'^sitemap-(?P<section>.+).xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})
+
+This will automatically generate a ``sitemap.xml`` file that references
+both ``sitemap-flatpages.xml`` and ``sitemap-blog.xml``. The ``Sitemap``
+classes and the ``sitemaps`` dict don't change at all.
+
+Pinging Google
+==============
+
+You may want to "ping" Google when your sitemap changes, to let it know to
+reindex your site. The framework provides a function to do just that:
+``django.contrib.sitemaps.ping_google()``.
+
+``ping_google()`` takes an optional argument, ``sitemap_url``, which should be
+the absolute URL of your site's sitemap (e.g., ``'/sitemap.xml'``). If this
+argument isn't provided, ``ping_google()`` will attempt to figure out your
+sitemap by performing a reverse looking in your URLconf.
+
+``ping_google()`` raises the exception
+``django.contrib.sitemaps.SitemapNotFound`` if it cannot determine your sitemap
+URL.
+
+One useful way to call ``ping_google()`` is from a model's ``save()`` method::
+
+ from django.contrib.sitemaps import ping_google
+
+ class Entry(models.Model):
+ # ...
+ def save(self):
+ super(Entry, self).save()
+ try:
+ ping_google()
+ except Exception:
+ # Bare 'except' because we could get a variety
+ # of HTTP-related exceptions.
+ pass
+
+A more efficient solution, however, would be to call ``ping_google()`` from a
+cron script, or some other scheduled task. The function makes an HTTP request
+to Google's servers, so you may not want to introduce that network overhead
+each time you call ``save()``.
diff --git a/docs/sites.txt b/docs/sites.txt
index cca9f14f31..8c5f1fc64b 100644
--- a/docs/sites.txt
+++ b/docs/sites.txt
@@ -266,7 +266,18 @@ this::
If you attempt to use ``CurrentSiteManager`` and pass a field name that doesn't
exist, Django will raise a ``ValueError``.
+Finally, note that you'll probably want to keep a normal (non-site-specific)
+``Manager`` on your model, even if you use ``CurrentSiteManager``. As explained
+in the `manager documentation`_, if you define a manager manually, then Django
+won't create the automatic ``objects = models.Manager()`` manager for you.
+Also, note that certain parts of Django -- namely, the Django admin site and
+generic views -- use whichever manager is defined *first* in the model, so if
+you want your admin site to have access to all objects (not just site-specific
+ones), put ``objects = models.Manager()`` in your model, before you define
+``CurrentSiteManager``.
+
.. _manager: http://www.djangoproject.com/documentation/model_api/#managers
+.. _manager documentation: http://www.djangoproject.com/documentation/model_api/#managers
How Django uses the sites framework
===================================
diff --git a/docs/syndication_feeds.txt b/docs/syndication_feeds.txt
index c84785b20b..225b67eb02 100644
--- a/docs/syndication_feeds.txt
+++ b/docs/syndication_feeds.txt
@@ -427,7 +427,7 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
author's e-mail as a normal Python string.
"""
- def author_name(self):
+ def author_email(self):
"""
Returns the feed's author's e-mail as a normal Python string.
"""
@@ -707,7 +707,7 @@ This example creates an Atom 1.0 feed and prints it to standard output::
... title=u"My Weblog",
... link=u"http://www.example.com/",
... description=u"In which I write about what I ate today.",
- ... language=u"en"),
+ ... language=u"en")
>>> f.add_item(title=u"Hot dog today",
... link=u"http://www.example.com/entries/1/",
... description=u"<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>")
diff --git a/docs/templates.txt b/docs/templates.txt
index 4ba52b3263..0f0009b495 100644
--- a/docs/templates.txt
+++ b/docs/templates.txt
@@ -47,7 +47,7 @@ explained later in this document.::
JavaScript and CSV. You can use the template language for any text-based
format.
- Oh, and one more thing: Making humans edit XML is masochistic!
+ Oh, and one more thing: Making humans edit XML is sadistic!
Variables
=========
@@ -109,6 +109,21 @@ Some tags require beginning and ending tags (i.e.
below describes all the built-in tags. You can create your own tags, if you
know how to write Python code.
+Comments
+========
+
+**New in Django development version**
+
+To comment-out part of a template, use the comment syntax: ``{# #}``.
+
+For example, this template would render as ``'hello'``::
+
+ {# greeting #}hello
+
+A comment can contain any template code, invalid or not. For example::
+
+ {# {% if foo %}bar{% else %} #}
+
Template inheritance
====================
@@ -141,6 +156,7 @@ It's easiest to understand template inheritance by starting with an example::
{% block content %}{% endblock %}
</div>
</body>
+ </html>
This template, which we'll call ``base.html``, defines a simple HTML skeleton
document that you might use for a simple two-column page. It's the job of
@@ -196,6 +212,7 @@ like::
<p>This is my second entry.</p>
</div>
</body>
+ </html>
Note that since the child template didn't define the ``sidebar`` block, the
value from the parent template is used instead. Content within a ``{% block %}``
@@ -363,10 +380,15 @@ extends
Signal that this template extends a parent template.
-This tag may be used in two ways: ``{% extends "base.html" %}`` (with quotes)
-uses the literal value "base.html" as the name of the parent template to
-extend, or ``{% extends variable %}`` uses the value of ``variable`` as the
-name of the parent template to extend.
+This tag can be used in two ways:
+
+ * ``{% extends "base.html" %}`` (with quotes) uses the literal value
+ ``"base.html"`` as the name of the parent template to extend.
+
+ * ``{% extends variable %}`` uses the value of ``variable``. If the variable
+ evaluates to a string, Django will use that string as the name of the
+ parent template. If the variable evaluates to a ``Template`` object,
+ Django will use that object as the parent template.
See `Template inheritance`_ for more information.
@@ -493,6 +515,11 @@ If you need to combine ``and`` and ``or`` to do advanced logic, just use nested
{% endif %}
{% endif %}
+Multiple uses of the same logical operator are fine, as long as you use the
+same operator. For example, this is valid::
+
+ {% if athlete_list or coach_list or parent_list or teacher_list %}
+
ifchanged
~~~~~~~~~
@@ -528,6 +555,11 @@ The arguments can be hard-coded strings, so the following is valid::
...
{% endifequal %}
+It is only possible to compare an argument to template variables or strings.
+You cannot check for equality with Python objects such as ``True`` or
+``False``. If you need to test if something is true or false, use the ``if``
+and ``ifnot`` tags instead.
+
ifnotequal
~~~~~~~~~~
@@ -951,13 +983,13 @@ any string.
pluralize
~~~~~~~~~
-Returns a plural suffix if the value is not 1. By default, this suffix is ``'s'``.
+Returns a plural suffix if the value is not 1. By default, this suffix is ``'s'``.
Example::
You have {{ num_messages }} message{{ num_messages|pluralize }}.
-For words that require a suffix other than ``'s'``, you can provide an alternate
+For words that require a suffix other than ``'s'``, you can provide an alternate
suffix as a parameter to the filter.
Example::
@@ -1039,7 +1071,7 @@ Formats a date as the time since that date (i.e. "4 days, 6 hours").
Takes an optional argument that is a variable containing the date to use as
the comparison point (without the argument, the comparison point is *now*).
For example, if ``blog_date`` is a date instance representing midnight on 1
-June 2006, and ``comment_date`` is a date instanace for 08:00 on 1 June 2006,
+June 2006, and ``comment_date`` is a date instance for 08:00 on 1 June 2006,
then ``{{ comment_date|timesince:blog_date }}`` would return "8 hours".
timeuntil
diff --git a/docs/templates_python.txt b/docs/templates_python.txt
index d353abb5bc..ae2582d7b8 100644
--- a/docs/templates_python.txt
+++ b/docs/templates_python.txt
@@ -198,25 +198,35 @@ some things to keep in mind:
How invalid variables are handled
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In Django 0.91, if a variable doesn't exist, the template system fails
-silently. The variable is replaced with an empty string::
+Generally, if a variable doesn't exist, the template system inserts the
+value of the ``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''``
+(the empty string) by default.
- >>> t = Template("My name is {{ my_name }}.")
- >>> c = Context({"foo": "bar"})
- >>> t.render(c)
- "My name is ."
-
-This applies to any level of lookup::
+Filters that are applied to an invalid variable will only be applied if
+``TEMPLATE_STRING_IF_INVALID`` is set to ``''`` (the empty string). If
+``TEMPLATE_STRING_IF_INVALID`` is set to any other value, variable
+filters will be ignored.
- >>> t = Template("My name is {{ person.fname }} {{ person.lname }}.")
- >>> c = Context({"person": {"fname": "Stan"}})
- >>> t.render(c)
- "My name is Stan ."
+This behavior is slightly different for the ``if``, ``for`` and ``regroup``
+template tags. If an invalid variable is provided to one of these template
+tags, the variable will be interpreted as ``None``. Filters are always
+applied to invalid variables within these template tags.
-If a variable doesn't exist, the template system inserts the value of the
-``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` (the empty
-string) by default.
+.. admonition:: For debug purposes only!
+ While ``TEMPLATE_STRING_IF_INVALID`` can be a useful debugging tool,
+ it is a bad idea to turn it on as a 'development default'.
+
+ Many templates, including those in the Admin site, rely upon the
+ silence of the template system when a non-existent variable is
+ encountered. If you assign a value other than ``''`` to
+ ``TEMPLATE_STRING_IF_INVALID``, you will experience rendering
+ problems with these templates and sites.
+
+ Generally, ``TEMPLATE_STRING_IF_INVALID`` should only be enabled
+ in order to debug a specific template problem, then cleared
+ once debugging is complete.
+
Playing with Context objects
----------------------------
@@ -274,9 +284,10 @@ an `HttpRequest object`_ as its first argument. For example::
The second difference is that it automatically populates the context with a few
variables, according to your `TEMPLATE_CONTEXT_PROCESSORS setting`_.
-The ``TEMPLATE_CONTEXT_PROCESSORS`` setting is a tuple of callables that take a
-request object as their argument and return a dictionary of items to be merged
-into the context. By default, ``TEMPLATE_CONTEXT_PROCESSORS`` is set to::
+The ``TEMPLATE_CONTEXT_PROCESSORS`` setting is a tuple of callables -- called
+**context processors** -- that take a request object as their argument and
+return a dictionary of items to be merged into the context. By default,
+``TEMPLATE_CONTEXT_PROCESSORS`` is set to::
("django.core.context_processors.auth",
"django.core.context_processors.debug",
@@ -300,6 +311,20 @@ optional, third positional argument, ``processors``. In this example, the
'foo': 'bar',
}, [ip_address_processor])
+Note::
+ If you're using Django's ``render_to_response()`` shortcut to populate a
+ template with the contents of a dictionary, your template will be passed a
+ ``Context`` instance by default (not a ``RequestContext``). To use a
+ ``RequestContext`` in your template rendering, pass an optional third
+ argument to ``render_to_response()``: a ``RequestContext``
+ instance. Your code might look like this::
+
+ def some_view(request):
+ # ...
+ return render_to_response('my_template'html',
+ my_data_dictionary,
+ context_instance=RequestContext(request))
+
Here's what each of the default processors does:
.. _HttpRequest object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
@@ -314,13 +339,22 @@ If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
* ``user`` -- An ``auth.User`` instance representing the currently
logged-in user (or an ``AnonymousUser`` instance, if the client isn't
logged in). See the `user authentication docs`.
- * ``messages`` -- A list of ``auth.Message`` objects for the currently
- logged-in user.
- * ``perms`` -- An instance of ``django.core.context_processors.PermWrapper``,
- representing the permissions that the currently logged-in user has. See
- the `permissions docs`_.
+
+ * ``messages`` -- A list of messages (as strings) for the currently
+ logged-in user. Behind the scenes, this calls
+ ``request.user.get_and_delete_messages()`` for every request. That method
+ collects the user's messages and deletes them from the database.
+
+ Note that messages are set with ``user.add_message()``. See the
+ `message docs`_ for more.
+
+ * ``perms`` -- An instance of
+ ``django.core.context_processors.PermWrapper``, representing the
+ permissions that the currently logged-in user has. See the `permissions
+ docs`_.
.. _user authentication docs: http://www.djangoproject.com/documentation/authentication/#users
+.. _message docs: http://www.djangoproject.com/documentation/authentication/#messages
.. _permissions docs: http://www.djangoproject.com/documentation/authentication/#permissions
django.core.context_processors.debug
@@ -357,10 +391,22 @@ django.core.context_processors.request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
-``DjangoContext`` will contain a variable ``request``, which is the current
+``RequestContext`` will contain a variable ``request``, which is the current
`HttpRequest object`_. Note that this processor is not enabled by default;
you'll have to activate it.
+Writing your own context processors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A context processor has a very simple interface: It's just a Python function
+that takes one argument, an ``HttpRequest`` object, and returns a dictionary
+that gets added to the template context. Each context processor *must* return
+a dictionary.
+
+Custom context processors can live anywhere in your code base. All Django cares
+about is that your custom context processors are pointed-to by your
+``TEMPLATE_CONTEXT_PROCESSORS`` setting.
+
Loading templates
-----------------
@@ -758,17 +804,17 @@ will use the function's name as the tag name.
Shortcut for simple tags
~~~~~~~~~~~~~~~~~~~~~~~~
-Many template tags take a single argument -- a string or a template variable
-reference -- and return a string after doing some processing based solely on
+Many template tags take a number of arguments -- strings or a template variables
+-- and return a string after doing some processing based solely on
the input argument and some external information. For example, the
``current_time`` tag we wrote above is of this variety: we give it a format
string, it returns the time as a string.
To ease the creation of the types of tags, Django provides a helper function,
``simple_tag``. This function, which is a method of
-``django.template.Library``, takes a function that accepts one argument, wraps
-it in a ``render`` function and the other necessary bits mentioned above and
-registers it with the template system.
+``django.template.Library``, takes a function that accepts any number of
+arguments, wraps it in a ``render`` function and the other necessary bits
+mentioned above and registers it with the template system.
Our earlier ``current_time`` function could thus be written like this::
@@ -784,18 +830,23 @@ In Python 2.4, the decorator syntax also works::
...
A couple of things to note about the ``simple_tag`` helper function:
- * Only the (single) argument is passed into our function.
* Checking for the required number of arguments, etc, has already been
done by the time our function is called, so we don't need to do that.
* The quotes around the argument (if any) have already been stripped away,
so we just receive a plain string.
+ * If the argument was a template variable, our function is passed the
+ current value of the variable, not the variable itself.
+
+When your template tag does not need access to the current context, writing a
+function to work with the input values and using the ``simple_tag`` helper is
+the easiest way to create a new tag.
Inclusion tags
~~~~~~~~~~~~~~
Another common type of template tag is the type that displays some data by
rendering *another* template. For example, Django's admin interface uses custom
-template tags to display the buttons along the botton of the "add/change" form
+template tags to display the buttons along the bottom of the "add/change" form
pages. Those buttons always look the same, but the link targets change depending
on the object being edited -- so they're a perfect case for using a small
template that is filled with details from the current object. (In the admin's
@@ -1041,7 +1092,7 @@ Configuring the template system in standalone mode
.. note::
This section is only of interest to people trying to use the template
- system as an output component in another application. If you are using the
+ system as an output component in another application. If you're using the
template system as part of a Django application, nothing here applies to
you.
@@ -1058,7 +1109,7 @@ described in the `settings file`_ documentation. Simply import the appropriate
pieces of the templating system and then, *before* you call any of the
templating functions, call ``django.conf.settings.configure()`` with any
settings you wish to specify. You might want to consider setting at least
-``TEMPLATE_DIRS`` (if you are going to use template loaders),
+``TEMPLATE_DIRS`` (if you're going to use template loaders),
``DEFAULT_CHARSET`` (although the default of ``utf-8`` is probably fine) and
``TEMPLATE_DEBUG``. All available settings are described in the
`settings documentation`_, and any setting starting with *TEMPLATE_*
diff --git a/docs/testing.txt b/docs/testing.txt
new file mode 100644
index 0000000000..19eef9f071
--- /dev/null
+++ b/docs/testing.txt
@@ -0,0 +1,453 @@
+===========================
+Testing Django applications
+===========================
+
+**New in Django development version**.
+
+Automated testing is an extremely useful weapon in the bug-killing arsenal
+of the modern developer. When initially writing code, a test suite can be
+used to validate that code behaves as expected. When refactoring or
+modifying code, tests serve as a guide to ensure that behavior hasn't
+changed unexpectedly as a result of the refactor.
+
+Testing an web application is a complex task, as there are many
+components of a web application that must be validated and tested. To
+help you test your application, Django provides a test execution
+framework, and range of utilities that can be used to stimulate and
+inspect various facets of a web application.
+
+ This testing framework is currently under development, and may change
+ slightly before the next official Django release.
+
+ (That's *no* excuse not to write tests, though!)
+
+Writing tests
+=============
+
+Tests in Django come in two forms: doctests and unit tests.
+
+Writing doctests
+----------------
+
+Doctests use Python's standard doctest_ module, which searches for tests in
+your docstrings. Django's test runner looks for doctests in your ``models.py``
+file, and executes any that it finds. Django will also search for a file
+called ``tests.py`` in the application directory (i.e., the directory that
+holds ``models.py``). If a ``tests.py`` is found, it will also be searched
+for doctests.
+
+.. admonition:: What's a **docstring**?
+
+ A good explanation of docstrings (and some guidlines for using them
+ effectively) can be found in :PEP:`257`:
+
+ A docstring is a string literal that occurs as the first statement in
+ a module, function, class, or method definition. Such a docstring
+ becomes the ``__doc__`` special attribute of that object.
+
+ Since tests often make great documentation, doctest lets you put your
+ tests directly in your docstrings.
+
+You can put doctest strings on any object in your ``models.py``, but it's
+common practice to put application-level doctests in the module docstring, and
+model-level doctests in the docstring for each model.
+
+For example::
+
+ from django.db import model
+
+ class Animal(models.Model):
+ """
+ An animal that knows how to make noise
+
+ # Create some animals
+ >>> lion = Animal.objects.create(name="lion", sound="roar")
+ >>> cat = Animal.objects.create(name="cat", sound="meow")
+
+ # Make 'em speak
+ >>> lion.speak()
+ 'The lion says "roar"'
+ >>> cat.speak()
+ 'The cat says "meow"'
+ """
+
+ name = models.CharField(maxlength=20)
+ sound = models.CharField(maxlength=20)
+
+ def speak(self):
+ return 'The %s says "%s"' % (self.name, self.sound)
+
+When you `run your tests`_, the test utility will find this docstring, notice
+that portions of it look like an interactive Python session, and execute those
+lines while checking that the results match.
+
+For more details about how doctest works, see the `standard library
+documentation for doctest`_
+
+.. _doctest: http://docs.python.org/lib/module-doctest.html
+.. _standard library documentation for doctest: doctest_
+
+Writing unittests
+-----------------
+
+Like doctests, Django's unit tests use a standard library module: unittest_.
+As with doctests, Django's test runner looks for any unit test cases defined
+in ``models.py``, or in a ``tests.py`` file stored in the application
+directory.
+
+An equivalent unittest test case for the above example would look like::
+
+ import unittest
+ from myapp.models import Animal
+
+ class AnimalTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.lion = Animal.objects.create(name="lion", sound="roar")
+ self.cat = Animal.objects.create(name="cat", sound="meow")
+
+ def testSpeaking(self):
+ self.assertEquals(self.lion.speak(), 'The lion says "roar"')
+ self.assertEquals(self.cat.speak(), 'The cat says "meow"')
+
+When you `run your tests`_, the test utility will find all the test cases
+(that is, subclasses of ``unittest.TestCase``) in ``models.py`` and
+``tests.py``, automatically build a test suite out of those test cases,
+and run that suite.
+
+For more details about ``unittest``, see the `standard library unittest
+documentation`_.
+
+.. _unittest: http://docs.python.org/lib/module-unittest.html
+.. _standard library unittest documentation: unittest_
+.. _run your tests: `Running tests`_
+
+Which should I use?
+-------------------
+
+Choosing a test framework is often contentious, so Django simply supports
+both of the standard Python test frameworks. Choosing one is up to each
+developer's personal tastes; each is supported equally. Since each test
+system has different benefits, the best approach is probably to use both
+together, picking the test system to match the type of tests you need to
+write.
+
+For developers new to testing, however, this choice can seem
+confusing, so here are a few key differences to help you decide weather
+doctests or unit tests are right for you.
+
+If you've been using Python for a while, ``doctest`` will probably feel more
+"pythonic". It's designed to make writing tests as easy as possible, so
+there's no overhead of writing classes or methods; you simply put tests in
+docstrings. This gives the added advantage of given your modules automatic
+documentation -- well-written doctests can kill both the documentation and the
+testing bird with a single stone.
+
+For developers just getting started with testing, using doctests will probably
+get you started faster.
+
+The ``unittest`` framework will probably feel very familiar to developers
+coming from Java. Since ``unittest`` is inspired by Java's JUnit, if
+you've used testing frameworks in other languages that similarly were
+inspired by JUnit, ``unittest`` should also feel pretty familiar.
+
+Since ``unittest`` is organized around classes and methods, if you need
+to write a bunch of tests that all share similar code, you can easily use
+subclass to abstract common tasks; this makes test code shorter and cleaner.
+There's also support for explicit setup and/or cleanup routines, which give
+you a high level of control over the environment your test cases run in.
+
+Again, remember that you can use both systems side-by-side (even in the same
+app). In the end, most projects will eventually end up using both; each shines
+in different circumstances.
+
+Testing Tools
+=============
+
+To assist in testing various features of your application, Django provides
+tools that can be used to establish tests and test conditions.
+
+* `Test Client`_
+* Fixtures_
+
+Test Client
+-----------
+
+The Test Client is a simple dummy browser. It allows you to simulate
+GET and POST requests on a URL, and observe the response that is received.
+This allows you to test that the correct view is executed for a given URL,
+and that the view constructs the correct response.
+
+As the response is generated, the Test Client gathers details on the
+Template and Context objects that were used to generate the response. These
+Templates and Contexts are then provided as part of the response, and can be
+used as test conditions.
+
+.. admonition:: Test Client vs Browser Automation?
+
+ The Test Client is not intended as a replacement for Twill_, Selenium_,
+ or other browser automation frameworks - it is intended to allow
+ testing of the contexts and templates produced by a view,
+ rather than the HTML rendered to the end-user.
+
+ A comprehensive test suite should use a combination of both: Test Client
+ tests to establish that the correct view is being called and that
+ the view is collecting the correct context data, and Browser Automation
+ tests to check that user interface behaves as expected.
+
+.. _Twill: http://twill.idyll.org/
+.. _Selenium: http://www.openqa.org/selenium/
+
+The Test Client is stateful; if a cookie is returned as part of a response,
+that cookie is provided as part of the next request issued to that Client
+instance. Expiry policies for these cookies are not followed; if you want
+a cookie to expire, either delete it manually from ``client.cookies``, or
+create a new Client instance (which will effectively delete all cookies).
+
+Making requests
+~~~~~~~~~~~~~~~
+
+Creating an instance of ``Client`` (``django.test.client.Client``) requires
+no arguments at time of construction. Once constructed, the following methods
+can be invoked on the ``Client`` instance.
+
+``get(path, data={})``
+ Make a GET request on the provided ``path``. The key-value pairs in the
+ data dictionary will be used to create a GET data payload. For example::
+
+ c = Client()
+ c.get('/customers/details/', {'name':'fred', 'age':7})
+
+ will result in the evaluation of a GET request equivalent to::
+
+ http://yoursite.com/customers/details/?name='fred'&age=7
+
+``post(path, data={})``
+ Make a POST request on the provided ``path``. The key-value pairs in the
+ data dictionary will be used to create the POST data payload. This payload
+ will be transmitted with the mimetype ``multipart/form-data``.
+
+ However submitting files is a special case. To POST a file, you need only
+ provide the file field name as a key, and a file handle to the file you wish to
+ upload as a value. The Test Client will populate the two POST fields (i.e.,
+ ``field`` and ``field_file``) required by FileField. For example::
+
+ c = Client()
+ f = open('wishlist.doc')
+ c.post('/customers/wishes/', {'name':'fred', 'attachment':f})
+ f.close()
+
+ will result in the evaluation of a POST request on ``/customers/wishes/``,
+ with a POST dictionary that contains `name`, `attachment` (containing the
+ file name), and `attachment_file` (containing the file data). Note that you
+ need to manually close the file after it has been provided to the POST.
+
+``login(path, username, password)``
+ In a production site, it is likely that some views will be protected with
+ the @login_required URL provided by ``django.contrib.auth``. Interacting
+ with a URL that has been login protected is a slightly complex operation,
+ so the Test Client provides a simple URL to automate the login process. A
+ call to ``login()`` stimulates the series of GET and POST calls required
+ to log a user into a @login_required protected URL.
+
+ If login is possible, the final return value of ``login()`` is the response
+ that is generated by issuing a GET request on the protected URL. If login
+ is not possible, ``login()`` returns False.
+
+ Note that since the test suite will be executed using the test database,
+ which contains no users by default. As a result, logins for your production
+ site will not work. You will need to create users as part of the test suite
+ to be able to test logins to your application.
+
+Testing Responses
+~~~~~~~~~~~~~~~~~
+
+The ``get()``, ``post()`` and ``login()`` methods all return a Response
+object. This Response object has the following properties that can be used
+for testing purposes:
+
+ =============== ==========================================================
+ Property Description
+ =============== ==========================================================
+ ``status_code`` The HTTP status of the response. See RFC2616_ for a
+ full list of HTTP status codes.
+
+ ``content`` The body of the response. The is the final page
+ content as rendered by the view, or any error message
+ (such as the URL for a 302 redirect).
+
+ ``template`` The Template instance that was used to render the final
+ content. Testing ``template.name`` can be particularly
+ useful; if the template was loaded from a file,
+ ``template.name`` will be the file name that was loaded.
+
+ If multiple templates were rendered, (e.g., if one
+ template includes another template),``template`` will
+ be a list of Template objects, in the order in which
+ they were rendered.
+
+ ``context`` The Context that was used to render the template that
+ produced the response content.
+
+ As with ``template``, if multiple templates were rendered
+ ``context`` will be a list of Context objects, stored in
+ the order in which they were rendered.
+ =============== ==========================================================
+
+.. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+
+The following is a simple unit test using the Test Client::
+
+ import unittest
+ from django.test.client import Client
+
+ class SimpleTest(unittest.TestCase):
+ def setUp(self):
+ # Every test needs a client
+ self.client = Client()
+ def test_details(self):
+ # Issue a GET request
+ response = self.client.get('/customer/details/')
+
+ # Check that the respose is 200 OK
+ self.failUnlessEqual(response.status_code, 200)
+ # Check that the rendered context contains 5 customers
+ self.failUnlessEqual(len(response.context['customers']), 5)
+
+Fixtures
+--------
+
+Feature still to come...
+
+Running tests
+=============
+
+Run your tests using your project's ``manage.py`` utility::
+
+ $ ./manage.py test
+
+If you only want to run tests for a particular application, add the
+application name to the command line. For example, if your
+``INSTALLED_APPS`` contains ``myproject.polls`` and ``myproject.animals``,
+but you only want to run the animals unit tests, run::
+
+ $ ./manage.py test animals
+
+When you run your tests, you'll see a bunch of text flow by as the test
+database is created and models are initialized. This test database is
+created from scratch every time you run your tests.
+
+By default, the test database gets its name by prepending ``test_`` to
+the database name specified by the ``DATABASE_NAME`` setting; all other
+database settings will the same as they would be for the project normally.
+If you wish to use a name other than the default for the test database,
+you can use the ``TEST_DATABASE_NAME`` setting to provide a name.
+
+Once the test database has been established, Django will run your tests.
+If everything goes well, at the end you'll see::
+
+ ----------------------------------------------------------------------
+ Ran 22 tests in 0.221s
+
+ OK
+
+If there are test failures, however, you'll see full details about what tests
+failed::
+
+ ======================================================================
+ FAIL: Doctest: ellington.core.throttle.models
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ File "/dev/django/test/doctest.py", line 2153, in runTest
+ raise self.failureException(self.format_failure(new.getvalue()))
+ AssertionError: Failed doctest test for myapp.models
+ File "/dev/myapp/models.py", line 0, in models
+
+ ----------------------------------------------------------------------
+ File "/dev/myapp/models.py", line 14, in myapp.models
+ Failed example:
+ throttle.check("actor A", "action one", limit=2, hours=1)
+ Expected:
+ True
+ Got:
+ False
+
+ ----------------------------------------------------------------------
+ Ran 2 tests in 0.048s
+
+ FAILED (failures=1)
+
+When the tests have all been executed, the test database is destroyed.
+
+Using a different testing framework
+===================================
+
+Doctest and Unittest are not the only Python testing frameworks. While
+Django doesn't provide explicit support these alternative frameworks,
+it does provide a mechanism to allow you to invoke tests constructed for
+an alternative framework as if they were normal Django tests.
+
+When you run ``./manage.py test``, Django looks at the ``TEST_RUNNER``
+setting to determine what to do. By default, ``TEST_RUNNER`` points to ``django.test.simple.run_tests``. This method defines the default Django
+testing behavior. This behavior involves:
+
+#. Performing global pre-test setup
+#. Creating the test database
+#. Running ``syncdb`` to install models and initial data into the test database
+#. Looking for Unit Tests and Doctests in ``models.py`` and ``tests.py`` file for each installed application
+#. Running the Unit Tests and Doctests that are found
+#. Destroying the test database.
+#. Performing global post-test teardown
+
+If you define your own test runner method and point ``TEST_RUNNER``
+at that method, Django will execute your test runner whenever you run
+``./manage.py test``. In this way, it is possible to use any test
+framework that can be executed from Python code.
+
+Defining a test runner
+----------------------
+By convention, a test runner should be called ``run_tests``; however, you
+can call it anything you want. The only requirement is that it accept two
+arguments:
+
+``run_tests(module_list, verbosity=1)``
+ The module list is the list of Python modules that contain the models to be
+ tested. This is the same format returned by ``django.db.models.get_apps()``
+
+ Verbosity determines the amount of notification and debug information that
+ will be printed to the console; '0' is no output, '1' is normal output,
+ and `2` is verbose output.
+
+Testing utilities
+-----------------
+
+To assist in the creation of your own test runner, Django provides
+a number of utility methods in the ``django.test.utils`` module.
+
+``setup_test_environment()``
+ Performs any global pre-test setup, such as the installing the
+ instrumentation of the template rendering system.
+
+``teardown_test_environment()``
+ Performs any global post-test teardown, such as removing the instrumentation
+ of the template rendering system.
+
+``create_test_db(verbosity=1, autoclobber=False)``
+ Creates a new test database, and run ``syncdb`` against it.
+
+ ``verbosity`` has the same behavior as in the test runner.
+
+ ``Autoclobber`` describes the behavior that will occur if a database with
+ the same name as the test database is discovered. If ``autoclobber`` is False,
+ the user will be asked to approve destroying the existing database. ``sys.exit``
+ is called if the user does not approve. If autoclobber is ``True``, the database
+ will be destroyed without consulting the user.
+
+ ``create_test_db()`` has the side effect of modifying
+ ``settings.DATABASE_NAME`` to match the name of the test database.
+
+``destroy_test_db(old_database_name, verbosity=1)``
+ Destroys the database with the name ``settings.DATABASE_NAME`` matching,
+ and restores the value of ``settings.DATABASE_NAME`` to the provided name.
+
+ ``verbosity`` has the same behavior as in the test runner.
diff --git a/docs/transactions.txt b/docs/transactions.txt
index c1cd5aa984..2b0755a257 100644
--- a/docs/transactions.txt
+++ b/docs/transactions.txt
@@ -2,7 +2,8 @@
Managing database transactions
==============================
-Django gives you a few ways to control how database transactions are managed.
+Django gives you a few ways to control how database transactions are managed,
+if you're using a database that supports transactions.
Django's default transaction behavior
=====================================
@@ -144,3 +145,19 @@ Thus, this is best used in situations where you want to run your own
transaction-controlling middleware or do something really strange. In almost
all situations, you'll be better off using the default behavior, or the
transaction middleware, and only modify selected functions as needed.
+
+Transactions in MySQL
+=====================
+
+If you're using MySQL, your tables may or may not support transactions; it
+depends on your MySQL version and the table types you're using. (By
+"table types," we mean something like "InnoDB" or "MyISAM".) MySQL transaction
+peculiarities are outside the scope of this article, but the MySQL site has
+`information on MySQL transactions`_.
+
+If your MySQL setup does *not* support transactions, then Django will function
+in auto-commit mode: Statements will be executed and committed as soon as
+they're called. If your MySQL setup *does* support transactions, Django will
+handle transactions as explained in this document.
+
+.. _information on MySQL transactions: http://dev.mysql.com/books/mysqlpress/mysql-tutorial/ch10.html
diff --git a/docs/tutorial01.txt b/docs/tutorial01.txt
index c353e1ab4b..1113b603da 100644
--- a/docs/tutorial01.txt
+++ b/docs/tutorial01.txt
@@ -81,7 +81,7 @@ the following output on the command line::
Validating models...
0 errors found.
- Django version 0.95 (post-magic-removal), using settings 'mysite.settings'
+ Django version 0.95, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).
@@ -346,6 +346,8 @@ Note the following:
the SQL to the database.
If you're interested, also run the following commands:
+ * ``python manage.py validate polls`` -- Checks for any errors in the
+ construction of your models.
* ``python manage.py sqlinitialdata polls`` -- Outputs any initial data
required for Django's admin framework and your models.
diff --git a/docs/tutorial02.txt b/docs/tutorial02.txt
index 84eae3eb83..f6d4045fa3 100644
--- a/docs/tutorial02.txt
+++ b/docs/tutorial02.txt
@@ -54,7 +54,8 @@ http://127.0.0.1:8000/admin/. You should see the admin's login screen:
Enter the admin site
====================
-Now, try logging in. You should see the Django admin index page:
+Now, try logging in. (You created a superuser account in the first part of this
+tutorial, remember?) You should see the Django admin index page:
.. image:: http://media.djangoproject.com/img/doc/tutorial/admin02t.png
:alt: Django admin index page
@@ -376,16 +377,16 @@ By default, ``TEMPLATE_DIRS`` is empty. So, let's add a line to it, to tell
Django where our templates live::
TEMPLATE_DIRS = (
- "/home/mytemplates", # Change this to your own directory.
+ "/home/my_username/mytemplates", # Change this to your own directory.
)
Now copy the template ``admin/base_site.html`` from within the default Django
admin template directory (``django/contrib/admin/templates``) into an ``admin``
subdirectory of whichever directory you're using in ``TEMPLATE_DIRS``. For
-example, if your ``TEMPLATE_DIRS`` includes ``"/home/mytemplates"``, as above,
-then copy ``django/contrib/admin/templates/admin/base_site.html`` to
-``/home/mytemplates/admin/base_site.html``. Don't forget that ``admin``
-subdirectory.
+example, if your ``TEMPLATE_DIRS`` includes ``"/home/my_username/mytemplates"``,
+as above, then copy ``django/contrib/admin/templates/admin/base_site.html`` to
+``/home/my_username/mytemplates/admin/base_site.html``. Don't forget that
+``admin`` subdirectory.
Then, just edit the file and replace the generic Django text with your own
site's name and URL as you see fit.
diff --git a/docs/tutorial03.txt b/docs/tutorial03.txt
index 3a830eb76f..c4c1b4c546 100644
--- a/docs/tutorial03.txt
+++ b/docs/tutorial03.txt
@@ -91,7 +91,7 @@ Finally, it calls that ``detail()`` function like so::
The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using parenthesis around a
pattern "captures" the text matched by that pattern and sends it as an argument
to the view function; the ``?P<poll_id>`` defines the name that will be used to
-identify the matched pattern; and ``\d+`` is a regular experession to match a sequence of
+identify the matched pattern; and ``\d+`` is a regular expression to match a sequence of
digits (i.e., a number).
Because the URL patterns are regular expressions, there really is no limit on
@@ -189,7 +189,7 @@ publication date::
from django.http import HttpResponse
def index(request):
- latest_poll_list = Poll.objects.all().order_by('-pub_date')
+ latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
output = ', '.join([p.question for p in latest_poll_list])
return HttpResponse(output)
@@ -202,7 +202,7 @@ So let's use Django's template system to separate the design from Python::
from django.http import HttpResponse
def index(request):
- latest_poll_list = Poll.objects.all().order_by('-pub_date')
+ latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
t = loader.get_template('polls/index.html')
c = Context({
'latest_poll_list': latest_poll_list,
@@ -257,7 +257,7 @@ provides a shortcut. Here's the full ``index()`` view, rewritten::
from mysite.polls.models import Poll
def index(request):
- latest_poll_list = Poll.objects.all().order_by('-pub_date')
+ latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list})
Note that we no longer need to import ``loader``, ``Context`` or
@@ -288,7 +288,7 @@ exception if a poll with the requested ID doesn't exist.
A shortcut: get_object_or_404()
-------------------------------
-It's a very common idiom to use ``get_object()`` and raise ``Http404`` if the
+It's a very common idiom to use ``get()`` and raise ``Http404`` if the
object doesn't exist. Django provides a shortcut. Here's the ``detail()`` view,
rewritten::
@@ -313,8 +313,8 @@ exist.
foremost design goals of Django is to maintain loose coupling.
There's also a ``get_list_or_404()`` function, which works just as
-``get_object_or_404()`` -- except using ``get_list()`` instead of
-``get_object()``. It raises ``Http404`` if the list is empty.
+``get_object_or_404()`` -- except using ``filter()`` instead of
+``get()``. It raises ``Http404`` if the list is empty.
Write a 404 (page not found) view
=================================
diff --git a/docs/tutorial04.txt b/docs/tutorial04.txt
index 8ef4a03c6d..c5e2ea3cea 100644
--- a/docs/tutorial04.txt
+++ b/docs/tutorial04.txt
@@ -198,7 +198,7 @@ By default, the ``object_detail`` generic view uses a template called
``vote()``.
Similarly, the ``object_list`` generic view uses a template called
-``<app name>/<module name>_list.html``. Thus, rename ``poll/index.html`` to
+``<app name>/<module name>_list.html``. Thus, rename ``polls/index.html`` to
``polls/poll_list.html``.
Because we have more than one entry in the URLconf that uses ``object_detail``
@@ -206,8 +206,8 @@ for the polls app, we manually specify a template name for the results view:
``template_name='polls/results.html'``. Otherwise, both views would use the same
template. Note that we use ``dict()`` to return an altered dictionary in place.
-In previous versions of the tutorial, the templates have been provided with a context
-that contains the ``poll` and ``latest_poll_list`` context variables. However,
+In previous parts of the tutorial, the templates have been provided with a context
+that contains the ``poll`` and ``latest_poll_list`` context variables. However,
the generic views provide the variables ``object`` and ``object_list`` as context.
Therefore, you need to change your templates to match the new context variables.
Go through your templates, and modify any reference to ``latest_poll_list`` to
diff --git a/docs/url_dispatch.txt b/docs/url_dispatch.txt
index 498a906d5e..00a7af027a 100644
--- a/docs/url_dispatch.txt
+++ b/docs/url_dispatch.txt
@@ -263,12 +263,12 @@ Here's the example URLconf from the `Django overview`_::
from django.conf.urls.defaults import *
urlpatterns = patterns('',
- (r'^articles/(\d{4})/$', 'myproject.news.views.year_archive'),
- (r'^articles/(\d{4})/(\d{2})/$', 'myproject.news.views.month_archive'),
- (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'myproject.news.views.article_detail'),
+ (r'^articles/(\d{4})/$', 'mysite.news.views.year_archive'),
+ (r'^articles/(\d{4})/(\d{2})/$', 'mysite.news.views.month_archive'),
+ (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.news.views.article_detail'),
)
-In this example, each view has a common prefix -- ``'myproject.news.views'``.
+In this example, each view has a common prefix -- ``'mysite.news.views'``.
Instead of typing that out for each entry in ``urlpatterns``, you can use the
first argument to the ``patterns()`` function to specify a prefix to apply to
each view function.
@@ -277,7 +277,7 @@ With this in mind, the above example can be written more concisely as::
from django.conf.urls.defaults import *
- urlpatterns = patterns('myproject.news.views',
+ urlpatterns = patterns('mysite.news.views',
(r'^articles/(\d{4})/$', 'year_archive'),
(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
@@ -389,3 +389,90 @@ to pass metadata and options to views.
.. _generic views: http://www.djangoproject.com/documentation/generic_views/
.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
+
+Passing extra options to ``include()``
+--------------------------------------
+
+**New in the Django development version.**
+
+Similarly, you can pass extra options to ``include()``. When you pass extra
+options to ``include()``, *each* line in the included URLconf will be passed
+the extra options.
+
+For example, these two URLconf sets are functionally identical:
+
+Set one::
+
+ # main.py
+ urlpatterns = patterns('',
+ (r'^blog/', include('inner'), {'blogid': 3}),
+ )
+
+ # inner.py
+ urlpatterns = patterns('',
+ (r'^archive/$', 'mysite.views.archive'),
+ (r'^about/$', 'mysite.views.about'),
+ )
+
+Set two::
+
+ # main.py
+ urlpatterns = patterns('',
+ (r'^blog/', include('inner')),
+ )
+
+ # inner.py
+ urlpatterns = patterns('',
+ (r'^archive/$', 'mysite.views.archive', {'blogid': 3}),
+ (r'^about/$', 'mysite.views.about', {'blogid': 3}),
+ )
+
+Note that extra options will *always* be passed to *every* line in the included
+URLconf, regardless of whether the line's view actually accepts those options
+as valid. For this reason, this technique is only useful if you're certain that
+every view in the the included URLconf accepts the extra options you're passing.
+
+Passing callable objects instead of strings
+===========================================
+
+**New in the Django development version.**
+
+Some developers find it more natural to pass the actual Python function object
+rather than a string containing the path to its module. This alternative is
+supported -- you can pass any callable object as the view.
+
+For example, given this URLconf in "string" notation::
+
+ urlpatterns = patterns('',
+ (r'^archive/$', 'mysite.views.archive'),
+ (r'^about/$', 'mysite.views.about'),
+ (r'^contact/$', 'mysite.views.contact'),
+ )
+
+You can accomplish the same thing by passing objects rather than strings. Just
+be sure to import the objects::
+
+ from mysite.views import archive, about, contact
+
+ urlpatterns = patterns('',
+ (r'^archive/$', archive),
+ (r'^about/$', about),
+ (r'^contact/$', contact),
+ )
+
+The following example is functionally identical. It's just a bit more compact
+because it imports the module that contains the views, rather than importing
+each view individually::
+
+ from mysite import views
+
+ urlpatterns = patterns('',
+ (r'^archive/$', views.archive),
+ (r'^about/$', views.about),
+ (r'^contact/$', views.contact),
+ )
+
+The style you use is up to you.
+
+Note that if you use this technique -- passing objects rather than strings --
+the view prefix (as explained in "The view prefix" above) will have no effect.
diff --git a/ez_setup.py b/ez_setup.py
deleted file mode 100644
index fe3983fef0..0000000000
--- a/ez_setup.py
+++ /dev/null
@@ -1,231 +0,0 @@
-#!python
-"""Bootstrap setuptools installation
-
-If you want to use setuptools in your package's setup.py, just include this
-file in the same directory with it, and add this to the top of your setup.py::
-
- from ez_setup import use_setuptools
- use_setuptools()
-
-If you want to require a specific version of setuptools, set a download
-mirror, or use an alternate download directory, you can do so by supplying
-the appropriate options to ``use_setuptools()``.
-
-This file can also be run as a script to install or upgrade setuptools.
-"""
-import sys
-DEFAULT_VERSION = "0.6a10"
-DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3]
-
-md5_data = {
- 'setuptools-0.5a13-py2.3.egg': '85edcf0ef39bab66e130d3f38f578c86',
- 'setuptools-0.5a13-py2.4.egg': 'ede4be600e3890e06d4ee5e0148e092a',
- 'setuptools-0.6a1-py2.3.egg': 'ee819a13b924d9696b0d6ca6d1c5833d',
- 'setuptools-0.6a1-py2.4.egg': '8256b5f1cd9e348ea6877b5ddd56257d',
- 'setuptools-0.6a10-py2.3.egg': '162d8357f1aff2b0349c6c247ee62987',
- 'setuptools-0.6a10-py2.4.egg': '803a2d8db501c1ac3b5b6fb4e907f788',
- 'setuptools-0.6a10dev_r42346-py2.3.egg': 'a7899272cfceb6aa60094ae8928b8077',
- 'setuptools-0.6a10dev_r42346-py2.4.egg': '5d42a64adca9aedb409f83ecf22156a5',
- 'setuptools-0.6a2-py2.3.egg': 'b98da449da411267c37a738f0ab625ba',
- 'setuptools-0.6a2-py2.4.egg': 'be5b88bc30aed63fdefd2683be135c3b',
- 'setuptools-0.6a3-py2.3.egg': 'ee0e325de78f23aab79d33106dc2a8c8',
- 'setuptools-0.6a3-py2.4.egg': 'd95453d525a456d6c23e7a5eea89a063',
- 'setuptools-0.6a4-py2.3.egg': 'e958cbed4623bbf47dd1f268b99d7784',
- 'setuptools-0.6a4-py2.4.egg': '7f33c3ac2ef1296f0ab4fac1de4767d8',
- 'setuptools-0.6a5-py2.3.egg': '748408389c49bcd2d84f6ae0b01695b1',
- 'setuptools-0.6a5-py2.4.egg': '999bacde623f4284bfb3ea77941d2627',
- 'setuptools-0.6a6-py2.3.egg': '7858139f06ed0600b0d9383f36aca24c',
- 'setuptools-0.6a6-py2.4.egg': 'c10d20d29acebce0dc76219dc578d058',
- 'setuptools-0.6a7-py2.3.egg': 'cfc4125ddb95c07f9500adc5d6abef6f',
- 'setuptools-0.6a7-py2.4.egg': 'c6d62dab4461f71aed943caea89e6f20',
- 'setuptools-0.6a8-py2.3.egg': '2f18eaaa3f544f5543ead4a68f3b2e1a',
- 'setuptools-0.6a8-py2.4.egg': '799018f2894f14c9f8bcb2b34e69b391',
- 'setuptools-0.6a9-py2.3.egg': '8e438ad70438b07b0d8f82cae42b278f',
- 'setuptools-0.6a9-py2.4.egg': '8f6e01fc12fb1cd006dc0d6c04327ec1',
-}
-
-import sys, os
-
-def _validate_md5(egg_name, data):
- if egg_name in md5_data:
- from md5 import md5
- digest = md5(data).hexdigest()
- if digest != md5_data[egg_name]:
- print >>sys.stderr, (
- "md5 validation of %s failed! (Possible download problem?)"
- % egg_name
- )
- sys.exit(2)
- return data
-
-
-def use_setuptools(
- version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
- download_delay=15
-):
- """Automatically find/download setuptools and make it available on sys.path
-
- `version` should be a valid setuptools version number that is available
- as an egg for download under the `download_base` URL (which should end with
- a '/'). `to_dir` is the directory where setuptools will be downloaded, if
- it is not already available. If `download_delay` is specified, it should
- be the number of seconds that will be paused before initiating a download,
- should one be required. If an older version of setuptools is installed,
- this routine will print a message to ``sys.stderr`` and raise SystemExit in
- an attempt to abort the calling script.
- """
- try:
- import setuptools
- if setuptools.__version__ == '0.0.1':
- print >>sys.stderr, (
- "You have an obsolete version of setuptools installed. Please\n"
- "remove it from your system entirely before rerunning this script."
- )
- sys.exit(2)
- except ImportError:
- egg = download_setuptools(version, download_base, to_dir, download_delay)
- sys.path.insert(0, egg)
- import setuptools; setuptools.bootstrap_install_from = egg
-
- import pkg_resources
- try:
- pkg_resources.require("setuptools>="+version)
-
- except pkg_resources.VersionConflict:
- # XXX could we install in a subprocess here?
- print >>sys.stderr, (
- "The required version of setuptools (>=%s) is not available, and\n"
- "can't be installed while this script is running. Please install\n"
- " a more recent version first."
- ) % version
- sys.exit(2)
-
-def download_setuptools(
- version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
- delay = 15
-):
- """Download setuptools from a specified location and return its filename
-
- `version` should be a valid setuptools version number that is available
- as an egg for download under the `download_base` URL (which should end
- with a '/'). `to_dir` is the directory where the egg will be downloaded.
- `delay` is the number of seconds to pause before an actual download attempt.
- """
- import urllib2, shutil
- egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
- url = download_base + egg_name
- saveto = os.path.join(to_dir, egg_name)
- src = dst = None
- if not os.path.exists(saveto): # Avoid repeated downloads
- try:
- from distutils import log
- if delay:
- log.warn("""
----------------------------------------------------------------------------
-This script requires setuptools version %s to run (even to display
-help). I will attempt to download it for you (from
-%s), but
-you may need to enable firewall access for this script first.
-I will start the download in %d seconds.
-
-(Note: if this machine does not have network access, please obtain the file
-
- %s
-
-and place it in this directory before rerunning this script.)
----------------------------------------------------------------------------""",
- version, download_base, delay, url
- ); from time import sleep; sleep(delay)
- log.warn("Downloading %s", url)
- src = urllib2.urlopen(url)
- # Read/write all in one block, so we don't create a corrupt file
- # if the download is interrupted.
- data = _validate_md5(egg_name, src.read())
- dst = open(saveto,"wb"); dst.write(data)
- finally:
- if src: src.close()
- if dst: dst.close()
- return os.path.realpath(saveto)
-
-def main(argv, version=DEFAULT_VERSION):
- """Install or upgrade setuptools and EasyInstall"""
-
- try:
- import setuptools
- except ImportError:
- import tempfile, shutil
- tmpdir = tempfile.mkdtemp(prefix="easy_install-")
- try:
- egg = download_setuptools(version, to_dir=tmpdir, delay=0)
- sys.path.insert(0,egg)
- from setuptools.command.easy_install import main
- main(list(argv)+[egg])
- finally:
- shutil.rmtree(tmpdir)
- else:
- if setuptools.__version__ == '0.0.1':
- # tell the user to uninstall obsolete version
- use_setuptools(version)
-
- req = "setuptools>="+version
- import pkg_resources
- try:
- pkg_resources.require(req)
- except pkg_resources.VersionConflict:
- try:
- from setuptools.command.easy_install import main
- except ImportError:
- from easy_install import main
- main(list(argv)+[download_setuptools(delay=0)])
- sys.exit(0) # try to force an exit
- else:
- if argv:
- from setuptools.command.easy_install import main
- main(argv)
- else:
- print "Setuptools version",version,"or greater has been installed."
- print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
-
-
-
-def update_md5(filenames):
- """Update our built-in md5 registry"""
-
- import re
- from md5 import md5
-
- for name in filenames:
- base = os.path.basename(name)
- f = open(name,'rb')
- md5_data[base] = md5(f.read()).hexdigest()
- f.close()
-
- data = [" %r: %r,\n" % it for it in md5_data.items()]
- data.sort()
- repl = "".join(data)
-
- import inspect
- srcfile = inspect.getsourcefile(sys.modules[__name__])
- f = open(srcfile, 'rb'); src = f.read(); f.close()
-
- match = re.search("\nmd5_data = {\n([^}]+)}", src)
- if not match:
- print >>sys.stderr, "Internal error!"
- sys.exit(2)
-
- src = src[:match.start(1)] + repl + src[match.end(1):]
- f = open(srcfile,'w')
- f.write(src)
- f.close()
-
-
-if __name__=='__main__':
- if len(sys.argv)>2 and sys.argv[1]=='--md5update':
- update_md5(sys.argv[2:])
- else:
- main(sys.argv[1:])
-
-
-
-
-
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000000..d3d908abf5
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,3 @@
+[bdist_rpm]
+doc_files = docs/*.txt
+
diff --git a/setup.py b/setup.py
index bdb5271294..9dd5fd9144 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,25 @@
-import ez_setup # From http://peak.telecommunity.com/DevCenter/setuptools
-ez_setup.use_setuptools()
+from distutils.core import setup
+from distutils.command.install import INSTALL_SCHEMES
+import os
-from setuptools import setup, find_packages
+# Tell distutils to put the data_files in platform-specific installation
+# locations. See here for an explanation:
+# http://groups.google.com/group/comp.lang.python/browse_thread/thread/35ec7b2fed36eaec/2105ee4d9e8042cb
+for scheme in INSTALL_SCHEMES.values():
+ scheme['data'] = scheme['purelib']
+
+# Compile the list of packages available, because distutils doesn't have
+# an easy way to do this.
+packages, data_files = [], []
+root_dir = os.path.join(os.path.dirname(__file__), 'django')
+for dirpath, dirnames, filenames in os.walk(root_dir):
+ # Ignore dirnames that start with '.'
+ for i, dirname in enumerate(dirnames):
+ if dirname.startswith('.'): del dirnames[i]
+ if '__init__.py' in filenames:
+ packages.append(dirpath.replace('/', '.'))
+ else:
+ data_files.append((dirpath, [os.path.join(dirpath, f) for f in filenames]))
setup(
name = "Django",
@@ -10,51 +28,7 @@ setup(
author = 'Lawrence Journal-World',
author_email = 'holovaty@gmail.com',
description = 'A high-level Python Web framework that encourages rapid development and clean, pragmatic design.',
- license = 'BSD',
- packages = find_packages(exclude=['examples', 'examples.*']),
- package_data = {
- '': ['*.TXT'],
- 'django.conf': ['locale/ar/LC_MESSAGES/*',
- 'locale/bn/LC_MESSAGES/*',
- 'locale/cs/LC_MESSAGES/*',
- 'locale/cy/LC_MESSAGES/*',
- 'locale/da/LC_MESSAGES/*',
- 'locale/de/LC_MESSAGES/*',
- 'locale/el/LC_MESSAGES/*',
- 'locale/en/LC_MESSAGES/*',
- 'locale/es/LC_MESSAGES/*',
- 'locale/es_AR/LC_MESSAGES/*',
- 'locale/fr/LC_MESSAGES/*',
- 'locale/gl/LC_MESSAGES/*',
- 'locale/hu/LC_MESSAGES/*',
- 'locale/he/LC_MESSAGES/*',
- 'locale/is/LC_MESSAGES/*',
- 'locale/it/LC_MESSAGES/*',
- 'locale/ja/LC_MESSAGES/*',
- 'locale/nl/LC_MESSAGES/*',
- 'locale/no/LC_MESSAGES/*',
- 'locale/pl/LC_MESSAGES/*',
- 'locale/pt_BR/LC_MESSAGES/*',
- 'locale/ro/LC_MESSAGES/*',
- 'locale/ru/LC_MESSAGES/*',
- 'locale/sk/LC_MESSAGES/*',
- 'locale/sl/LC_MESSAGES/*',
- 'locale/sr/LC_MESSAGES/*',
- 'locale/sv/LC_MESSAGES/*',
- 'locale/uk/LC_MESSAGES/*',
- 'locale/zh_CN/LC_MESSAGES/*',
- 'locale/zh_TW/LC_MESSAGES/*'],
- 'django.contrib.admin': ['templates/admin/*.html',
- 'templates/admin_doc/*.html',
- 'templates/registration/*.html',
- 'templates/widget/*.html',
- 'media/css/*.css',
- 'media/img/admin/*.gif',
- 'media/img/admin/*.png',
- 'media/js/*.js',
- 'media/js/admin/*js'],
- 'django.contrib.comments': ['templates/comments/*.html'],
- },
+ packages = packages,
+ data_files = data_files,
scripts = ['django/bin/django-admin.py'],
- zip_safe = False,
)
diff --git a/tests/modeltests/basic/models.py b/tests/modeltests/basic/models.py
index 78d943eb97..5638865f31 100644
--- a/tests/modeltests/basic/models.py
+++ b/tests/modeltests/basic/models.py
@@ -13,8 +13,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
-
+__test__ = {'API_TESTS': """
# No articles are in the system yet.
>>> Article.objects.all()
[]
@@ -87,6 +86,10 @@ DoesNotExist: Article matching query does not exist.
>>> Article.objects.get(pk=1)
<Article: Area woman programs in Python>
+# pk can be used as a shortcut for the primary key name in any query
+>>> Article.objects.filter(pk__in=[1])
+[<Article: Area woman programs in Python>]
+
# Model instances of the same type and same ID are considered equal.
>>> a = Article.objects.get(pk=1)
>>> b = Article.objects.get(pk=1)
@@ -314,14 +317,14 @@ AttributeError: Manager isn't accessible via Article instances
>>> Article.objects.all()
[<Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
-"""
+"""}
from django.conf import settings
building_docs = getattr(settings, 'BUILDING_DOCS', False)
if building_docs or settings.DATABASE_ENGINE == 'postgresql':
- API_TESTS += """
+ __test__['API_TESTS'] += """
# In PostgreSQL, microsecond-level precision is available.
>>> a9 = Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
@@ -330,7 +333,7 @@ datetime.datetime(2005, 7, 31, 12, 30, 45, 180)
"""
if building_docs or settings.DATABASE_ENGINE == 'mysql':
- API_TESTS += """
+ __test__['API_TESTS'] += """
# In MySQL, microsecond-level precision isn't available. You'll lose
# microsecond-level precision once the data is saved.
>>> a9 = Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
@@ -339,7 +342,7 @@ if building_docs or settings.DATABASE_ENGINE == 'mysql':
datetime.datetime(2005, 7, 31, 12, 30, 45)
"""
-API_TESTS += """
+__test__['API_TESTS'] += """
# You can manually specify the primary key when creating a new object.
>>> a101 = Article(id=101, headline='Article 101', pub_date=datetime(2005, 7, 31, 12, 30, 45))
diff --git a/tests/modeltests/choices/models.py b/tests/modeltests/choices/models.py
index 881fb29fd2..37d36fe1d8 100644
--- a/tests/modeltests/choices/models.py
+++ b/tests/modeltests/choices/models.py
@@ -23,7 +23,7 @@ class Person(models.Model):
def __str__(self):
return self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> a = Person(name='Adrian', gender='M')
>>> a.save()
>>> s = Person(name='Sara', gender='F')
@@ -36,4 +36,4 @@ API_TESTS = """
'Male'
>>> s.get_gender_display()
'Female'
-"""
+"""}
diff --git a/tests/modeltests/custom_columns/models.py b/tests/modeltests/custom_columns/models.py
index 7d8c52d137..e88fa80da2 100644
--- a/tests/modeltests/custom_columns/models.py
+++ b/tests/modeltests/custom_columns/models.py
@@ -15,7 +15,7 @@ class Person(models.Model):
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create a Person.
>>> p = Person(first_name='John', last_name='Smith')
>>> p.save()
@@ -50,4 +50,4 @@ AttributeError: 'Person' object has no attribute 'firstname'
Traceback (most recent call last):
...
AttributeError: 'Person' object has no attribute 'last'
-"""
+"""}
diff --git a/tests/modeltests/custom_managers/models.py b/tests/modeltests/custom_managers/models.py
index 1c4e91b526..99df875275 100644
--- a/tests/modeltests/custom_managers/models.py
+++ b/tests/modeltests/custom_managers/models.py
@@ -58,7 +58,7 @@ class Car(models.Model):
def __str__(self):
return self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> p1 = Person(first_name='Bugs', last_name='Bunny', fun=True)
>>> p1.save()
>>> p2 = Person(first_name='Droopy', last_name='Dog', fun=False)
@@ -104,4 +104,4 @@ True
# to the first manager defined in the class. In this case, it's "cars".
>>> Car._default_manager.order_by('name')
[<Car: Corvette>, <Car: Neon>]
-"""
+"""}
diff --git a/tests/modeltests/custom_methods/models.py b/tests/modeltests/custom_methods/models.py
index e314d97264..e8fb751d54 100644
--- a/tests/modeltests/custom_methods/models.py
+++ b/tests/modeltests/custom_methods/models.py
@@ -36,7 +36,7 @@ class Article(models.Model):
# positional arguments to Article().
return [self.__class__(*row) for row in cursor.fetchall()]
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create a couple of Articles.
>>> from datetime import date
>>> a = Article(id=None, headline='Area man programs in Python', pub_date=date(2005, 7, 27))
@@ -55,4 +55,4 @@ False
[<Article: Area man programs in Python>]
>>> b.articles_from_same_day_2()
[<Article: Area man programs in Python>]
-"""
+"""}
diff --git a/tests/modeltests/custom_pk/models.py b/tests/modeltests/custom_pk/models.py
index f7b790ca21..fd0901da3c 100644
--- a/tests/modeltests/custom_pk/models.py
+++ b/tests/modeltests/custom_pk/models.py
@@ -27,7 +27,7 @@ class Business(models.Model):
def __str__(self):
return self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> dan = Employee(employee_code='ABC123', first_name='Dan', last_name='Jones')
>>> dan.save()
>>> Employee.objects.all()
@@ -51,6 +51,10 @@ DoesNotExist: Employee matching query does not exist.
>>> Employee.objects.get(employee_code__exact='ABC123')
<Employee: Dan Jones>
+# pk can be used as a substitute for the primary key.
+>>> Employee.objects.filter(pk__in=['ABC123','XYZ456'])
+[<Employee: Fran Bones>, <Employee: Dan Jones>]
+
# Fran got married and changed her last name.
>>> fran = Employee.objects.get(pk='XYZ456')
>>> fran.last_name = 'Jones'
@@ -88,4 +92,4 @@ DoesNotExist: Employee matching query does not exist.
>>> Business.objects.filter(employees__first_name__startswith='Fran')
[<Business: Sears>]
-"""
+"""}
diff --git a/tests/modeltests/empty/models.py b/tests/modeltests/empty/models.py
index c50878398d..0e5d572504 100644
--- a/tests/modeltests/empty/models.py
+++ b/tests/modeltests/empty/models.py
@@ -10,7 +10,7 @@ from django.db import models
class Empty(models.Model):
pass
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> m = Empty()
>>> m.id
>>> m.save()
@@ -20,5 +20,7 @@ API_TESTS = """
2
>>> m.id is not None
True
+>>> existing = Empty(m.id)
+>>> existing.save()
-"""
+"""}
diff --git a/tests/modeltests/field_defaults/models.py b/tests/modeltests/field_defaults/models.py
index 0d69ffd8be..da4cd38974 100644
--- a/tests/modeltests/field_defaults/models.py
+++ b/tests/modeltests/field_defaults/models.py
@@ -19,7 +19,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> from datetime import datetime
# No articles are in the system yet.
@@ -48,4 +48,4 @@ API_TESTS = """
>>> d = now - a.pub_date
>>> d.seconds < 5
True
-"""
+"""}
diff --git a/tests/modeltests/generic_relations/models.py b/tests/modeltests/generic_relations/models.py
index e9a81a19e8..eb64d7ec3d 100644
--- a/tests/modeltests/generic_relations/models.py
+++ b/tests/modeltests/generic_relations/models.py
@@ -53,7 +53,7 @@ class Mineral(models.Model):
def __str__(self):
return self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create the world in 7 lines of code...
>>> lion = Animal(common_name="Lion", latin_name="Panthera leo")
>>> platypus = Animal(common_name="Platypus", latin_name="Ornithorhynchus anatinus")
@@ -105,4 +105,4 @@ API_TESTS = """
[<TaggedItem: shiny>]
>>> TaggedItem.objects.filter(content_type__pk=ctype.id, object_id=quartz.id)
[<TaggedItem: clearish>]
-"""
+"""}
diff --git a/tests/modeltests/get_latest/models.py b/tests/modeltests/get_latest/models.py
index 42e7a14ec7..84c6273818 100644
--- a/tests/modeltests/get_latest/models.py
+++ b/tests/modeltests/get_latest/models.py
@@ -3,9 +3,9 @@
Models can have a ``get_latest_by`` attribute, which should be set to the name
of a DateField or DateTimeField. If ``get_latest_by`` exists, the model's
-module will get a ``get_latest()`` function, which will return the latest
-object in the database according to that field. "Latest" means "having the
-date farthest into the future."
+manager will get a ``latest()`` method, which will return the latest object in
+the database according to that field. "Latest" means "having the date farthest
+into the future."
"""
from django.db import models
@@ -29,8 +29,8 @@ class Person(models.Model):
def __str__(self):
return self.name
-API_TESTS = """
-# Because no Articles exist yet, get_latest() raises ArticleDoesNotExist.
+__test__ = {'API_TESTS':"""
+# Because no Articles exist yet, latest() raises ArticleDoesNotExist.
>>> Article.objects.latest()
Traceback (most recent call last):
...
@@ -76,4 +76,4 @@ AssertionError: latest() requires either a field_name parameter or 'get_latest_b
>>> Person.objects.latest('birthday')
<Person: Stephanie>
-"""
+"""}
diff --git a/tests/modeltests/get_or_create/models.py b/tests/modeltests/get_or_create/models.py
index 10a8721afc..b4f39ceded 100644
--- a/tests/modeltests/get_or_create/models.py
+++ b/tests/modeltests/get_or_create/models.py
@@ -15,7 +15,7 @@ class Person(models.Model):
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Acting as a divine being, create an Person.
>>> from datetime import date
>>> p = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
@@ -49,4 +49,4 @@ True
False
>>> Person.objects.count()
2
-"""
+"""}
diff --git a/tests/modeltests/invalid_models/models.py b/tests/modeltests/invalid_models/models.py
index eb305b4e92..2299cd85e6 100644
--- a/tests/modeltests/invalid_models/models.py
+++ b/tests/modeltests/invalid_models/models.py
@@ -68,17 +68,36 @@ class SelfClashForeign(models.Model):
foreign_1 = models.ForeignKey("SelfClashForeign", related_name='id')
foreign_2 = models.ForeignKey("SelfClashForeign", related_name='src_safe')
+class ValidM2M(models.Model):
+ src_safe = models.CharField(maxlength=10)
+ validm2m = models.CharField(maxlength=10)
+
+ # M2M fields are symmetrical by default. Symmetrical M2M fields
+ # on self don't require a related accessor, so many potential
+ # clashes are avoided.
+ validm2m_set = models.ManyToManyField("ValidM2M")
+
+ m2m_1 = models.ManyToManyField("ValidM2M", related_name='id')
+ m2m_2 = models.ManyToManyField("ValidM2M", related_name='src_safe')
+
+ m2m_3 = models.ManyToManyField('self')
+ m2m_4 = models.ManyToManyField('self')
+
class SelfClashM2M(models.Model):
src_safe = models.CharField(maxlength=10)
selfclashm2m = models.CharField(maxlength=10)
- selfclashm2m_set = models.ManyToManyField("SelfClashM2M")
- m2m_1 = models.ManyToManyField("SelfClashM2M", related_name='id')
- m2m_2 = models.ManyToManyField("SelfClashM2M", related_name='src_safe')
-
+ # Non-symmetrical M2M fields _do_ have related accessors, so
+ # there is potential for clashes.
+ selfclashm2m_set = models.ManyToManyField("SelfClashM2M", symmetrical=False)
+
+ m2m_1 = models.ManyToManyField("SelfClashM2M", related_name='id', symmetrical=False)
+ m2m_2 = models.ManyToManyField("SelfClashM2M", related_name='src_safe', symmetrical=False)
+ m2m_3 = models.ManyToManyField('self', symmetrical=False)
+ m2m_4 = models.ManyToManyField('self', symmetrical=False)
-error_log = """invalid_models.fielderrors: "charfield": CharFields require a "maxlength" attribute.
+model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "maxlength" attribute.
invalid_models.fielderrors: "floatfield": FloatFields require a "decimal_places" attribute.
invalid_models.fielderrors: "floatfield": FloatFields require a "max_digits" attribute.
invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute.
@@ -147,9 +166,17 @@ invalid_models.selfclashforeign: Accessor for field 'foreign_2' clashes with fie
invalid_models.selfclashforeign: Reverse query name for field 'foreign_2' clashes with field 'SelfClashForeign.src_safe'. Add a related_name argument to the definition for 'foreign_2'.
invalid_models.selfclashm2m: Accessor for m2m field 'selfclashm2m_set' clashes with m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'selfclashm2m_set'.
invalid_models.selfclashm2m: Reverse query name for m2m field 'selfclashm2m_set' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'selfclashm2m_set'.
+invalid_models.selfclashm2m: Accessor for m2m field 'selfclashm2m_set' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'selfclashm2m_set'.
invalid_models.selfclashm2m: Accessor for m2m field 'm2m_1' clashes with field 'SelfClashM2M.id'. Add a related_name argument to the definition for 'm2m_1'.
invalid_models.selfclashm2m: Accessor for m2m field 'm2m_2' clashes with field 'SelfClashM2M.src_safe'. Add a related_name argument to the definition for 'm2m_2'.
invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_1' clashes with field 'SelfClashM2M.id'. Add a related_name argument to the definition for 'm2m_1'.
invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_2' clashes with field 'SelfClashM2M.src_safe'. Add a related_name argument to the definition for 'm2m_2'.
+invalid_models.selfclashm2m: Accessor for m2m field 'm2m_3' clashes with m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_3'.
+invalid_models.selfclashm2m: Accessor for m2m field 'm2m_3' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_3'.
+invalid_models.selfclashm2m: Accessor for m2m field 'm2m_3' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_3'.
+invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_4'.
+invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_4'.
+invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_4'.
+invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_3' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'm2m_3'.
+invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_4' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'm2m_4'.
"""
-
diff --git a/tests/modeltests/lookup/models.py b/tests/modeltests/lookup/models.py
index a2c0a14158..09c3aa7aa8 100644
--- a/tests/modeltests/lookup/models.py
+++ b/tests/modeltests/lookup/models.py
@@ -15,7 +15,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
+__test__ = {'API_TESTS':r"""
# Create a couple of Articles.
>>> from datetime import datetime
>>> a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26))
@@ -161,13 +161,14 @@ DoesNotExist: Article matching query does not exist.
<Article: Article 1>
# Underscores and percent signs have special meaning in the underlying
-# database library, but Django handles the quoting of them automatically.
+# SQL code, but Django handles the quoting of them automatically.
>>> a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
>>> a8.save()
>>> Article.objects.filter(headline__startswith='Article')
[<Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
>>> Article.objects.filter(headline__startswith='Article_')
[<Article: Article_ with underscore>]
+
>>> a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
>>> a9.save()
>>> Article.objects.filter(headline__startswith='Article')
@@ -182,4 +183,12 @@ DoesNotExist: Article matching query does not exist.
[<Article: Article% with percent sign>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
>>> Article.objects.exclude(headline="Article 7")
[<Article: Article% with percent sign>, <Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 1>]
-"""
+
+# Backslashes also have special meaning in the underlying SQL code, but Django
+# automatically quotes them appropriately.
+>>> a10 = Article(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22))
+>>> a10.save()
+>>> Article.objects.filter(headline__contains='\\')
+[<Article: Article with \ backslash>]
+
+"""}
diff --git a/tests/modeltests/m2m_and_m2o/models.py b/tests/modeltests/m2m_and_m2o/models.py
index f43fb12d9e..7fc66ed5a0 100644
--- a/tests/modeltests/m2m_and_m2o/models.py
+++ b/tests/modeltests/m2m_and_m2o/models.py
@@ -21,7 +21,7 @@ class Issue(models.Model):
ordering = ('num',)
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> Issue.objects.all()
[]
>>> r = User(username='russell')
@@ -62,4 +62,4 @@ API_TESTS = """
[<Issue: 1>, <Issue: 2>, <Issue: 3>]
>>> Issue.objects.filter(Q(client=r.id) | Q(cc__id__exact=r.id))
[<Issue: 1>, <Issue: 2>, <Issue: 3>]
-"""
+"""}
diff --git a/tests/modeltests/m2m_intermediary/models.py b/tests/modeltests/m2m_intermediary/models.py
index 848d035c39..b917db6189 100644
--- a/tests/modeltests/m2m_intermediary/models.py
+++ b/tests/modeltests/m2m_intermediary/models.py
@@ -34,7 +34,7 @@ class Writer(models.Model):
def __str__(self):
return '%s (%s)' % (self.reporter, self.position)
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create a few Reporters.
>>> r1 = Reporter(first_name='John', last_name='Smith')
>>> r1.save()
@@ -65,4 +65,4 @@ API_TESTS = """
<Article: This is a test>
>>> r1.writer_set.all()
[<Writer: John Smith (Main writer)>]
-"""
+"""}
diff --git a/tests/modeltests/m2m_multiple/models.py b/tests/modeltests/m2m_multiple/models.py
index e4fef75f19..5a1aa122a9 100644
--- a/tests/modeltests/m2m_multiple/models.py
+++ b/tests/modeltests/m2m_multiple/models.py
@@ -28,7 +28,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> from datetime import datetime
>>> c1 = Category(name='Sports')
@@ -76,4 +76,4 @@ API_TESTS = """
[]
>>> c4.secondary_article_set.all()
[<Article: Area man steals>, <Article: Area man runs>]
-"""
+"""}
diff --git a/tests/modeltests/m2m_recursive/models.py b/tests/modeltests/m2m_recursive/models.py
index dace32d565..9f31cf92c0 100644
--- a/tests/modeltests/m2m_recursive/models.py
+++ b/tests/modeltests/m2m_recursive/models.py
@@ -22,7 +22,7 @@ class Person(models.Model):
def __str__(self):
return self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> a = Person(name='Anne')
>>> a.save()
>>> b = Person(name='Bill')
@@ -189,4 +189,4 @@ API_TESTS = """
>>> d.stalkers.all()
[<Person: Chuck>]
-"""
+"""}
diff --git a/tests/modeltests/m2o_recursive/models.py b/tests/modeltests/m2o_recursive/models.py
index 44881b5a2f..0b528faf9e 100644
--- a/tests/modeltests/m2o_recursive/models.py
+++ b/tests/modeltests/m2o_recursive/models.py
@@ -19,7 +19,7 @@ class Category(models.Model):
def __str__(self):
return self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create a few Category objects.
>>> r = Category(id=None, name='Root category', parent=None)
>>> r.save()
@@ -37,4 +37,4 @@ None
[]
>>> c.parent
<Category: Root category>
-"""
+"""}
diff --git a/tests/modeltests/m2o_recursive2/models.py b/tests/modeltests/m2o_recursive2/models.py
index 93185c6a4c..5b7c5447ad 100644
--- a/tests/modeltests/m2o_recursive2/models.py
+++ b/tests/modeltests/m2o_recursive2/models.py
@@ -17,7 +17,7 @@ class Person(models.Model):
def __str__(self):
return self.full_name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create two Person objects -- the mom and dad in our family.
>>> dad = Person(full_name='John Smith Senior', mother=None, father=None)
>>> dad.save()
@@ -40,4 +40,4 @@ API_TESTS = """
[]
>>> kid.fathers_child_set.all()
[]
-"""
+"""}
diff --git a/tests/modeltests/manipulators/models.py b/tests/modeltests/manipulators/models.py
index f7b20d52ac..e5b8be55b5 100644
--- a/tests/modeltests/manipulators/models.py
+++ b/tests/modeltests/manipulators/models.py
@@ -21,7 +21,7 @@ class Album(models.Model):
def __str__(self):
return self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> from django.utils.datastructures import MultiValueDict
# Create a Musician object via the default AddManipulator.
@@ -88,4 +88,4 @@ True
<Album: Ultimate Ella>
>>> a2.release_date
datetime.date(2005, 2, 13)
-"""
+"""}
diff --git a/tests/modeltests/many_to_many/models.py b/tests/modeltests/many_to_many/models.py
index 0e989a0fbe..357f3ca629 100644
--- a/tests/modeltests/many_to_many/models.py
+++ b/tests/modeltests/many_to_many/models.py
@@ -28,7 +28,7 @@ class Article(models.Model):
class Meta:
ordering = ('headline',)
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create a couple of Publications.
>>> p1 = Publication(id=None, title='The Python Journal')
>>> p1.save()
@@ -231,4 +231,4 @@ API_TESTS = """
>>> p1.article_set.all()
[<Article: NASA uses Python>]
-"""
+"""}
diff --git a/tests/modeltests/many_to_one/models.py b/tests/modeltests/many_to_one/models.py
index d202975128..82eb3257d0 100644
--- a/tests/modeltests/many_to_one/models.py
+++ b/tests/modeltests/many_to_one/models.py
@@ -25,7 +25,7 @@ class Article(models.Model):
class Meta:
ordering = ('headline',)
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create a few Reporters.
>>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> r.save()
@@ -263,4 +263,4 @@ TypeError: Cannot resolve keyword 'reporter_id' into field
>>> Article.objects.all()
[]
-"""
+"""}
diff --git a/tests/modeltests/many_to_one_null/models.py b/tests/modeltests/many_to_one_null/models.py
index b1936b9861..fb0f6ac3b7 100644
--- a/tests/modeltests/many_to_one_null/models.py
+++ b/tests/modeltests/many_to_one_null/models.py
@@ -23,7 +23,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create a Reporter.
>>> r = Reporter(name='John Smith')
>>> r.save()
@@ -121,4 +121,4 @@ DoesNotExist: <Article: Fourth> is not related to <Reporter: John Smith>.
>>> Article.objects.filter(reporter__isnull=True)
[<Article: First>, <Article: Fourth>]
-"""
+"""}
diff --git a/tests/modeltests/model_inheritance/models.py b/tests/modeltests/model_inheritance/models.py
index 473cf24a9f..babef73e0a 100644
--- a/tests/modeltests/model_inheritance/models.py
+++ b/tests/modeltests/model_inheritance/models.py
@@ -26,7 +26,7 @@ class ItalianRestaurant(Restaurant):
def __str__(self):
return "%s the italian restaurant" % self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Make sure Restaurant has the right fields in the right order.
>>> [f.name for f in Restaurant._meta.fields]
['id', 'name', 'address', 'serves_hot_dogs', 'serves_pizza']
@@ -50,4 +50,4 @@ API_TESTS = """
>>> ir.save()
-"""
+"""}
diff --git a/tests/modeltests/mutually_referential/models.py b/tests/modeltests/mutually_referential/models.py
index 07b52effbc..5a3897d21a 100644
--- a/tests/modeltests/mutually_referential/models.py
+++ b/tests/modeltests/mutually_referential/models.py
@@ -14,7 +14,7 @@ class Child(Model):
name = CharField(maxlength=100)
parent = ForeignKey(Parent)
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create a Parent
>>> q = Parent(name='Elizabeth')
>>> q.save()
@@ -29,4 +29,4 @@ API_TESTS = """
>>> q.delete()
-""" \ No newline at end of file
+"""} \ No newline at end of file
diff --git a/tests/modeltests/one_to_one/models.py b/tests/modeltests/one_to_one/models.py
index f95556c08d..7488204ff1 100644
--- a/tests/modeltests/one_to_one/models.py
+++ b/tests/modeltests/one_to_one/models.py
@@ -30,7 +30,15 @@ class Waiter(models.Model):
def __str__(self):
return "%s the waiter at %s" % (self.name, self.restaurant)
-API_TESTS = """
+class ManualPrimaryKey(models.Model):
+ primary_key = models.CharField(maxlength=10, primary_key=True)
+ name = models.CharField(maxlength = 50)
+
+class RelatedModel(models.Model):
+ link = models.OneToOneField(ManualPrimaryKey)
+ name = models.CharField(maxlength = 50)
+
+__test__ = {'API_TESTS':"""
# Create a couple of Places.
>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
>>> p1.save()
@@ -151,4 +159,10 @@ DoesNotExist: Restaurant matching query does not exist.
# Delete the restaurant; the waiter should also be removed
>>> r = Restaurant.objects.get(pk=1)
>>> r.delete()
-"""
+
+# One-to-one fields still work if you create your own primary key
+>>> o1 = ManualPrimaryKey(primary_key="abc123", name="primary")
+>>> o1.save()
+>>> o2 = RelatedModel(link=o1, name="secondary")
+>>> o2.save()
+"""}
diff --git a/tests/modeltests/or_lookups/models.py b/tests/modeltests/or_lookups/models.py
index 80dc35f2b1..2de18edc1f 100644
--- a/tests/modeltests/or_lookups/models.py
+++ b/tests/modeltests/or_lookups/models.py
@@ -23,7 +23,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> from datetime import datetime
>>> from django.db.models import Q
@@ -101,4 +101,4 @@ API_TESTS = """
[<Article: Hello>]
>>> Article.objects.complex_filter(Q(pk=1) | Q(pk=2))
[<Article: Hello>, <Article: Goodbye>]
-"""
+"""}
diff --git a/tests/modeltests/ordering/models.py b/tests/modeltests/ordering/models.py
index b22568c900..110ae3d7fc 100644
--- a/tests/modeltests/ordering/models.py
+++ b/tests/modeltests/ordering/models.py
@@ -24,7 +24,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create a couple of Articles.
>>> from datetime import datetime
>>> a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26))
@@ -64,4 +64,4 @@ API_TESTS = """
# don't know what order the output will be in.
>>> Article.objects.order_by('?')
[...]
-"""
+"""}
diff --git a/tests/modeltests/pagination/models.py b/tests/modeltests/pagination/models.py
index 165b251d35..ea2385dc79 100644
--- a/tests/modeltests/pagination/models.py
+++ b/tests/modeltests/pagination/models.py
@@ -15,7 +15,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# prepare a list of objects for pagination
>>> from datetime import datetime
>>> for x in range(1, 10):
@@ -64,4 +64,4 @@ True
>>> paginator.last_on_page(1)
9
-"""
+"""}
diff --git a/tests/modeltests/properties/models.py b/tests/modeltests/properties/models.py
index 3b0133bf8a..4ba6b1a808 100644
--- a/tests/modeltests/properties/models.py
+++ b/tests/modeltests/properties/models.py
@@ -20,7 +20,7 @@ class Person(models.Model):
full_name_2 = property(_get_full_name, _set_full_name)
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> a = Person(first_name='John', last_name='Lennon')
>>> a.save()
>>> a.full_name
@@ -37,4 +37,4 @@ AttributeError: can't set attribute
>>> a2.save()
>>> a2.first_name
'Paul'
-"""
+"""}
diff --git a/tests/modeltests/reserved_names/models.py b/tests/modeltests/reserved_names/models.py
index db9196bebe..affe3f649d 100644
--- a/tests/modeltests/reserved_names/models.py
+++ b/tests/modeltests/reserved_names/models.py
@@ -24,7 +24,7 @@ class Thing(models.Model):
def __str__(self):
return self.when
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> import datetime
>>> day1 = datetime.date(2005, 1, 1)
>>> day2 = datetime.date(2006, 2, 2)
@@ -53,4 +53,4 @@ b
>>> Thing.objects.filter(where__month=1)
[<Thing: a>]
-"""
+"""}
diff --git a/tests/modeltests/reverse_lookup/models.py b/tests/modeltests/reverse_lookup/models.py
index b8c4466021..7e6712676f 100644
--- a/tests/modeltests/reverse_lookup/models.py
+++ b/tests/modeltests/reverse_lookup/models.py
@@ -27,7 +27,7 @@ class Choice(models.Model):
def __str(self):
return self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> john = User(name="John Doe")
>>> john.save()
>>> jim = User(name="Jim Bo")
@@ -56,4 +56,4 @@ API_TESTS = """
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'choice' into field
-"""
+"""}
diff --git a/tests/modeltests/save_delete_hooks/models.py b/tests/modeltests/save_delete_hooks/models.py
index f01a2932d3..6e24c308ba 100644
--- a/tests/modeltests/save_delete_hooks/models.py
+++ b/tests/modeltests/save_delete_hooks/models.py
@@ -24,7 +24,7 @@ class Person(models.Model):
super(Person, self).delete() # Call the "real" delete() method
print "After deletion"
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> p1 = Person(first_name='John', last_name='Smith')
>>> p1.save()
Before save
@@ -39,4 +39,4 @@ After deletion
>>> Person.objects.all()
[]
-"""
+"""}
diff --git a/tests/modeltests/serializers/models.py b/tests/modeltests/serializers/models.py
index ccf565c365..d1d10b43c0 100644
--- a/tests/modeltests/serializers/models.py
+++ b/tests/modeltests/serializers/models.py
@@ -37,7 +37,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create some data:
>>> from datetime import datetime
>>> sports = Category(name="Sports")
@@ -118,4 +118,4 @@ API_TESTS = """
>>> Article.objects.all()
[<Article: Just kidding; I love TV poker>, <Article: Time to reform copyright>]
-"""
+"""}
diff --git a/tests/modeltests/str/models.py b/tests/modeltests/str/models.py
index 4e4228ac89..81230d538c 100644
--- a/tests/modeltests/str/models.py
+++ b/tests/modeltests/str/models.py
@@ -17,7 +17,7 @@ class Article(models.Model):
def __str__(self):
return self.headline
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Create an Article.
>>> from datetime import datetime
>>> a = Article(headline='Area man programs in Python', pub_date=datetime(2005, 7, 28))
@@ -28,4 +28,4 @@ API_TESTS = """
>>> a
<Article: Area man programs in Python>
-"""
+"""}
diff --git a/tests/modeltests/test_client/__init__.py b/tests/modeltests/test_client/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/modeltests/test_client/__init__.py
diff --git a/tests/modeltests/test_client/management.py b/tests/modeltests/test_client/management.py
new file mode 100644
index 0000000000..9b5a5c498e
--- /dev/null
+++ b/tests/modeltests/test_client/management.py
@@ -0,0 +1,10 @@
+from django.dispatch import dispatcher
+from django.db.models import signals
+import models as test_client_app
+from django.contrib.auth.models import User
+
+def setup_test(app, created_models, verbosity):
+ # Create a user account for the login-based tests
+ User.objects.create_user('testclient','testclient@example.com', 'password')
+
+dispatcher.connect(setup_test, sender=test_client_app, signal=signals.post_syncdb)
diff --git a/tests/modeltests/test_client/models.py b/tests/modeltests/test_client/models.py
new file mode 100644
index 0000000000..c5b1a241ca
--- /dev/null
+++ b/tests/modeltests/test_client/models.py
@@ -0,0 +1,101 @@
+"""
+39. Testing using the Test Client
+
+The test client is a class that can act like a simple
+browser for testing purposes.
+
+It allows the user to compose GET and POST requests, and
+obtain the response that the server gave to those requests.
+The server Response objects are annotated with the details
+of the contexts and templates that were rendered during the
+process of serving the request.
+
+Client objects are stateful - they will retain cookie (and
+thus session) details for the lifetime of the Client instance.
+
+This is not intended as a replacement for Twill,Selenium, or
+other browser automation frameworks - it is here to allow
+testing against the contexts and templates produced by a view,
+rather than the HTML rendered to the end-user.
+
+"""
+from django.test.client import Client
+import unittest
+
+class ClientTest(unittest.TestCase):
+ def setUp(self):
+ "Set up test environment"
+ self.client = Client()
+
+ def test_get_view(self):
+ "GET a view"
+ response = self.client.get('/test_client/get_view/')
+
+ # Check some response details
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['var'], 42)
+ self.assertEqual(response.template.name, 'GET Template')
+ self.failUnless('This is a test.' in response.content)
+
+ def test_get_post_view(self):
+ "GET a view that normally expects POSTs"
+ response = self.client.get('/test_client/post_view/', {})
+
+ # Check some response details
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.template.name, 'Empty POST Template')
+
+ def test_empty_post(self):
+ "POST an empty dictionary to a view"
+ response = self.client.post('/test_client/post_view/', {})
+
+ # Check some response details
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.template.name, 'Empty POST Template')
+
+ def test_post_view(self):
+ "POST some data to a view"
+ post_data = {
+ 'value': 37
+ }
+ response = self.client.post('/test_client/post_view/', post_data)
+
+ # Check some response details
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['data'], '37')
+ self.assertEqual(response.template.name, 'POST Template')
+ self.failUnless('Data received' in response.content)
+
+ def test_redirect(self):
+ "GET a URL that redirects elsewhere"
+ response = self.client.get('/test_client/redirect_view/')
+
+ # Check that the response was a 302 (redirect)
+ self.assertEqual(response.status_code, 302)
+
+ def test_unknown_page(self):
+ "GET an invalid URL"
+ response = self.client.get('/test_client/unknown_view/')
+
+ # Check that the response was a 404
+ self.assertEqual(response.status_code, 404)
+
+ def test_view_with_login(self):
+ "Request a page that is protected with @login_required"
+
+ # Get the page without logging in. Should result in 302.
+ response = self.client.get('/test_client/login_protected_view/')
+ self.assertEqual(response.status_code, 302)
+
+ # Request a page that requires a login
+ response = self.client.login('/test_client/login_protected_view/', 'testclient', 'password')
+ self.assertTrue(response)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['user'].username, 'testclient')
+ self.assertEqual(response.template.name, 'Login Template')
+
+ def test_view_with_bad_login(self):
+ "Request a page that is protected with @login, but use bad credentials"
+
+ response = self.client.login('/test_client/login_protected_view/', 'otheruser', 'nopassword')
+ self.assertFalse(response)
diff --git a/tests/modeltests/test_client/urls.py b/tests/modeltests/test_client/urls.py
new file mode 100644
index 0000000000..09bba5c007
--- /dev/null
+++ b/tests/modeltests/test_client/urls.py
@@ -0,0 +1,9 @@
+from django.conf.urls.defaults import *
+import views
+
+urlpatterns = patterns('',
+ (r'^get_view/$', views.get_view),
+ (r'^post_view/$', views.post_view),
+ (r'^redirect_view/$', views.redirect_view),
+ (r'^login_protected_view/$', views.login_protected_view),
+)
diff --git a/tests/modeltests/test_client/views.py b/tests/modeltests/test_client/views.py
new file mode 100644
index 0000000000..bf131032eb
--- /dev/null
+++ b/tests/modeltests/test_client/views.py
@@ -0,0 +1,35 @@
+from django.template import Context, Template
+from django.http import HttpResponse, HttpResponseRedirect
+from django.contrib.auth.decorators import login_required
+
+def get_view(request):
+ "A simple view that expects a GET request, and returns a rendered template"
+ t = Template('This is a test. {{ var }} is the value.', name='GET Template')
+ c = Context({'var': 42})
+
+ return HttpResponse(t.render(c))
+
+def post_view(request):
+ """A view that expects a POST, and returns a different template depending
+ on whether any POST data is available
+ """
+ if request.POST:
+ t = Template('Data received: {{ data }} is the value.', name='POST Template')
+ c = Context({'data': request.POST['value']})
+ else:
+ t = Template('Viewing POST page.', name='Empty POST Template')
+ c = Context()
+
+ return HttpResponse(t.render(c))
+
+def redirect_view(request):
+ "A view that redirects all requests to the GET view"
+ return HttpResponseRedirect('/test_client/get_view/')
+
+@login_required
+def login_protected_view(request):
+ "A simple view that is login protected."
+ t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
+ c = Context({'user': request.user})
+
+ return HttpResponse(t.render(c))
diff --git a/tests/modeltests/transactions/models.py b/tests/modeltests/transactions/models.py
index 92e0f38f47..e1fad8063e 100644
--- a/tests/modeltests/transactions/models.py
+++ b/tests/modeltests/transactions/models.py
@@ -17,16 +17,16 @@ class Reporter(models.Model):
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> from django.db import connection, transaction
-"""
+"""}
from django.conf import settings
building_docs = getattr(settings, 'BUILDING_DOCS', False)
if building_docs or settings.DATABASE_ENGINE != 'mysql':
- API_TESTS += """
+ __test__['API_TESTS'] += """
# the default behavior is to autocommit after each save() action
>>> def create_a_reporter_then_fail(first, last):
... a = Reporter(first_name=first, last_name=last)
diff --git a/tests/modeltests/validation/models.py b/tests/modeltests/validation/models.py
index 57811f25a5..a9a3d3f485 100644
--- a/tests/modeltests/validation/models.py
+++ b/tests/modeltests/validation/models.py
@@ -20,7 +20,7 @@ class Person(models.Model):
def __str__(self):
return self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
>>> import datetime
>>> valid_params = {
@@ -146,4 +146,4 @@ u'john@example.com'
>>> p.validate()
{'email': ['Enter a valid e-mail address.']}
-"""
+"""}
diff --git a/tests/othertests/cache.py b/tests/othertests/cache.py
deleted file mode 100644
index 81f2c20328..0000000000
--- a/tests/othertests/cache.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Unit tests for cache framework
-# Uses whatever cache backend is set in the test settings file.
-
-from django.core.cache import cache
-import time
-
-# functions/classes for complex data type tests
-def f():
- return 42
-class C:
- def m(n):
- return 24
-
-# simple set/get
-cache.set("key", "value")
-assert cache.get("key") == "value"
-
-# get with non-existent keys
-assert cache.get("does not exist") is None
-assert cache.get("does not exist", "bang!") == "bang!"
-
-# get_many
-cache.set('a', 'a')
-cache.set('b', 'b')
-cache.set('c', 'c')
-cache.set('d', 'd')
-assert cache.get_many(['a', 'c', 'd']) == {'a' : 'a', 'c' : 'c', 'd' : 'd'}
-assert cache.get_many(['a', 'b', 'e']) == {'a' : 'a', 'b' : 'b'}
-
-# delete
-cache.set("key1", "spam")
-cache.set("key2", "eggs")
-assert cache.get("key1") == "spam"
-cache.delete("key1")
-assert cache.get("key1") is None
-assert cache.get("key2") == "eggs"
-
-# has_key
-cache.set("hello", "goodbye")
-assert cache.has_key("hello") == True
-assert cache.has_key("goodbye") == False
-
-# test data types
-stuff = {
- 'string' : 'this is a string',
- 'int' : 42,
- 'list' : [1, 2, 3, 4],
- 'tuple' : (1, 2, 3, 4),
- 'dict' : {'A': 1, 'B' : 2},
- 'function' : f,
- 'class' : C,
-}
-for (key, value) in stuff.items():
- cache.set(key, value)
- assert cache.get(key) == value
-
-# expiration
-cache.set('expire', 'very quickly', 1)
-time.sleep(2)
-assert cache.get("expire") == None
diff --git a/tests/othertests/markup.py b/tests/othertests/markup.py
deleted file mode 100644
index 3fa5a3a883..0000000000
--- a/tests/othertests/markup.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Quick tests for the markup templatetags (django.contrib.markup)
-
-from django.template import Template, Context, add_to_builtins
-
-add_to_builtins('django.contrib.markup.templatetags.markup')
-
-# find out if markup modules are installed and tailor the test appropriately
-try:
- import textile
-except ImportError:
- textile = None
-
-try:
- import markdown
-except ImportError:
- markdown = None
-
-try:
- import docutils
-except ImportError:
- docutils = None
-
-# simple examples 'cause this isn't actually testing the markup, just
-# that the filters work as advertised
-
-### test textile
-
-textile_content = """Paragraph 1
-
-Paragraph 2 with "quotes" and @code@"""
-
-t = Template("{{ textile_content|textile }}")
-rendered = t.render(Context(locals())).strip()
-if textile:
- assert rendered == """<p>Paragraph 1</p>
-
-<p>Paragraph 2 with &#8220;quotes&#8221; and <code>code</code></p>"""
-else:
- assert rendered == textile_content
-
-### test markdown
-
-markdown_content = """Paragraph 1
-
-## An h2"""
-
-t = Template("{{ markdown_content|markdown }}")
-rendered = t.render(Context(locals())).strip()
-if markdown:
- assert rendered == """<p>Paragraph 1</p><h2>An h2</h2>"""
-else:
- assert rendered == markdown_content
-
-### test rest
-
-rest_content = """Paragraph 1
-
-Paragraph 2 with a link_
-
-.. _link: http://www.example.com/"""
-
-t = Template("{{ rest_content|restructuredtext }}")
-rendered = t.render(Context(locals())).strip()
-if docutils:
- assert rendered =="""<p>Paragraph 1</p>
-<p>Paragraph 2 with a <a class="reference" href="http://www.example.com/">link</a></p>"""
-else:
- assert rendered == rest_content
diff --git a/tests/othertests/templates.py b/tests/othertests/templates.py
deleted file mode 100644
index d3b09c5310..0000000000
--- a/tests/othertests/templates.py
+++ /dev/null
@@ -1,625 +0,0 @@
-from django.conf import settings
-
-
-from django import template
-from django.template import loader
-from django.utils.translation import activate, deactivate, install
-from django.utils.tzinfo import LocalTimezone
-from datetime import datetime, timedelta
-import traceback
-
-#################################
-# Custom template tag for tests #
-#################################
-
-register = template.Library()
-
-class EchoNode(template.Node):
- def __init__(self, contents):
- self.contents = contents
-
- def render(self, context):
- return " ".join(self.contents)
-
-def do_echo(parser, token):
- return EchoNode(token.contents.split()[1:])
-
-register.tag("echo", do_echo)
-
-template.libraries['django.templatetags.testtags'] = register
-
-#####################################
-# Helper objects for template tests #
-#####################################
-
-class SomeException(Exception):
- silent_variable_failure = True
-
-class SomeOtherException(Exception):
- pass
-
-class SomeClass:
- def __init__(self):
- self.otherclass = OtherClass()
-
- def method(self):
- return "SomeClass.method"
-
- def method2(self, o):
- return o
-
- def method3(self):
- raise SomeException
-
- def method4(self):
- raise SomeOtherException
-
-class OtherClass:
- def method(self):
- return "OtherClass.method"
-
-# NOW and NOW_tz are used by timesince tag tests.
-NOW = datetime.now()
-NOW_tz = datetime.now(LocalTimezone(datetime.now()))
-
-# SYNTAX --
-# 'template_name': ('template contents', 'context dict', 'expected string output' or Exception class)
-TEMPLATE_TESTS = {
-
- ### BASIC SYNTAX ##########################################################
-
- # Plain text should go through the template parser untouched
- 'basic-syntax01': ("something cool", {}, "something cool"),
-
- # Variables should be replaced with their value in the current context
- 'basic-syntax02': ("{{ headline }}", {'headline':'Success'}, "Success"),
-
- # More than one replacement variable is allowed in a template
- 'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"),
-
- # Fail silently when a variable is not found in the current context
- 'basic-syntax04': ("as{{ missing }}df", {}, "asINVALIDdf"),
-
- # A variable may not contain more than one word
- 'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError),
-
- # Raise TemplateSyntaxError for empty variable tags
- 'basic-syntax07': ("{{ }}", {}, template.TemplateSyntaxError),
- 'basic-syntax08': ("{{ }}", {}, template.TemplateSyntaxError),
-
- # Attribute syntax allows a template to call an object's attribute
- 'basic-syntax09': ("{{ var.method }}", {"var": SomeClass()}, "SomeClass.method"),
-
- # Multiple levels of attribute access are allowed
- 'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"),
-
- # Fail silently when a variable's attribute isn't found
- 'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, "INVALID"),
-
- # Raise TemplateSyntaxError when trying to access a variable beginning with an underscore
- 'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError),
-
- # Raise TemplateSyntaxError when trying to access a variable containing an illegal character
- 'basic-syntax13': ("{{ va>r }}", {}, template.TemplateSyntaxError),
- 'basic-syntax14': ("{{ (var.r) }}", {}, template.TemplateSyntaxError),
- 'basic-syntax15': ("{{ sp%am }}", {}, template.TemplateSyntaxError),
- 'basic-syntax16': ("{{ eggs! }}", {}, template.TemplateSyntaxError),
- 'basic-syntax17': ("{{ moo? }}", {}, template.TemplateSyntaxError),
-
- # Attribute syntax allows a template to call a dictionary key's value
- 'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"),
-
- # Fail silently when a variable's dictionary key isn't found
- 'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, "INVALID"),
-
- # Fail silently when accessing a non-simple method
- 'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, "INVALID"),
-
- # Basic filter usage
- 'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),
-
- # Chained filters
- 'basic-syntax22': ("{{ var|upper|lower }}", {"var": "Django is the greatest!"}, "django is the greatest!"),
-
- # Raise TemplateSyntaxError for space between a variable and filter pipe
- 'basic-syntax23': ("{{ var |upper }}", {}, template.TemplateSyntaxError),
-
- # Raise TemplateSyntaxError for space after a filter pipe
- 'basic-syntax24': ("{{ var| upper }}", {}, template.TemplateSyntaxError),
-
- # Raise TemplateSyntaxError for a nonexistent filter
- 'basic-syntax25': ("{{ var|does_not_exist }}", {}, template.TemplateSyntaxError),
-
- # Raise TemplateSyntaxError when trying to access a filter containing an illegal character
- 'basic-syntax26': ("{{ var|fil(ter) }}", {}, template.TemplateSyntaxError),
-
- # Raise TemplateSyntaxError for invalid block tags
- 'basic-syntax27': ("{% nothing_to_see_here %}", {}, template.TemplateSyntaxError),
-
- # Raise TemplateSyntaxError for empty block tags
- 'basic-syntax28': ("{% %}", {}, template.TemplateSyntaxError),
-
- # Chained filters, with an argument to the first one
- 'basic-syntax29': ('{{ var|removetags:"b i"|upper|lower }}', {"var": "<b><i>Yes</i></b>"}, "yes"),
-
- # Escaped string as argument
- 'basic-syntax30': (r'{{ var|default_if_none:" endquote\" hah" }}', {"var": None}, ' endquote" hah'),
-
- # Variable as argument
- 'basic-syntax31': (r'{{ var|default_if_none:var2 }}', {"var": None, "var2": "happy"}, 'happy'),
-
- # Default argument testing
- 'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),
-
- # Fail silently for methods that raise an exception with a "silent_variable_failure" attribute
- 'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, "1INVALID2"),
-
- # In methods that raise an exception without a "silent_variable_attribute" set to True,
- # the exception propogates
- 'basic-syntax34': (r'1{{ var.method4 }}2', {"var": SomeClass()}, SomeOtherException),
-
- # Escaped backslash in argument
- 'basic-syntax35': (r'{{ var|default_if_none:"foo\bar" }}', {"var": None}, r'foo\bar'),
-
- # Escaped backslash using known escape char
- 'basic-syntax35': (r'{{ var|default_if_none:"foo\now" }}', {"var": None}, r'foo\now'),
-
- ### COMMENT TAG ###########################################################
- 'comment-tag01': ("{% comment %}this is hidden{% endcomment %}hello", {}, "hello"),
- 'comment-tag02': ("{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}", {}, "hello"),
-
- # Comment tag can contain invalid stuff.
- 'comment-tag03': ("foo{% comment %} {% if %} {% endcomment %}", {}, "foo"),
- 'comment-tag04': ("foo{% comment %} {% endblock %} {% endcomment %}", {}, "foo"),
- 'comment-tag05': ("foo{% comment %} {% somerandomtag %} {% endcomment %}", {}, "foo"),
-
- ### CYCLE TAG #############################################################
- 'cycle01': ('{% cycle a %}', {}, template.TemplateSyntaxError),
- 'cycle02': ('{% cycle a,b,c as abc %}{% cycle abc %}', {}, 'ab'),
- 'cycle03': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}', {}, 'abc'),
- 'cycle04': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}', {}, 'abca'),
- 'cycle05': ('{% cycle %}', {}, template.TemplateSyntaxError),
- 'cycle06': ('{% cycle a %}', {}, template.TemplateSyntaxError),
- 'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
-
- ### EXCEPTIONS ############################################################
-
- # Raise exception for invalid template name
- 'exception01': ("{% extends 'nonexistent' %}", {}, template.TemplateSyntaxError),
-
- # Raise exception for invalid template name (in variable)
- 'exception02': ("{% extends nonexistent %}", {}, template.TemplateSyntaxError),
-
- # Raise exception for extra {% extends %} tags
- 'exception03': ("{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% extends 'inheritance16' %}", {}, template.TemplateSyntaxError),
-
- # Raise exception for custom tags used in child with {% load %} tag in parent, not in child
- 'exception04': ("{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}", {}, template.TemplateSyntaxError),
-
- ### FILTER TAG ############################################################
- 'filter01': ('{% filter upper %}{% endfilter %}', {}, ''),
- 'filter02': ('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'),
- 'filter03': ('{% filter upper|lower %}django{% endfilter %}', {}, 'django'),
-
- ### FIRSTOF TAG ###########################################################
- 'firstof01': ('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''),
- 'firstof02': ('{% firstof a b c %}', {'a':1,'b':0,'c':0}, '1'),
- 'firstof03': ('{% firstof a b c %}', {'a':0,'b':2,'c':0}, '2'),
- 'firstof04': ('{% firstof a b c %}', {'a':0,'b':0,'c':3}, '3'),
- 'firstof05': ('{% firstof a b c %}', {'a':1,'b':2,'c':3}, '1'),
- 'firstof06': ('{% firstof %}', {}, template.TemplateSyntaxError),
-
- ### FOR TAG ###############################################################
- 'for-tag01': ("{% for val in values %}{{ val }}{% endfor %}", {"values": [1, 2, 3]}, "123"),
- 'for-tag02': ("{% for val in values reversed %}{{ val }}{% endfor %}", {"values": [1, 2, 3]}, "321"),
- 'for-tag-vars01': ("{% for val in values %}{{ forloop.counter }}{% endfor %}", {"values": [6, 6, 6]}, "123"),
- 'for-tag-vars02': ("{% for val in values %}{{ forloop.counter0 }}{% endfor %}", {"values": [6, 6, 6]}, "012"),
- 'for-tag-vars03': ("{% for val in values %}{{ forloop.revcounter }}{% endfor %}", {"values": [6, 6, 6]}, "321"),
- 'for-tag-vars04': ("{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}", {"values": [6, 6, 6]}, "210"),
-
- ### IF TAG ################################################################
- 'if-tag01': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": True}, "yes"),
- 'if-tag02': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": False}, "no"),
- 'if-tag03': ("{% if foo %}yes{% else %}no{% endif %}", {}, "no"),
-
- # AND
- 'if-tag-and01': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
- 'if-tag-and02': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
- 'if-tag-and03': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
- 'if-tag-and04': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
- 'if-tag-and05': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'),
- 'if-tag-and06': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'),
- 'if-tag-and07': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True}, 'no'),
- 'if-tag-and08': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': True}, 'no'),
-
- # OR
- 'if-tag-or01': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
- 'if-tag-or02': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
- 'if-tag-or03': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
- 'if-tag-or04': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
- 'if-tag-or05': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'),
- 'if-tag-or06': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'),
- 'if-tag-or07': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True}, 'yes'),
- 'if-tag-or08': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': True}, 'yes'),
-
- # TODO: multiple ORs
-
- # NOT
- 'if-tag-not01': ("{% if not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'yes'),
- 'if-tag-not02': ("{% if not %}yes{% else %}no{% endif %}", {'foo': True}, 'no'),
- 'if-tag-not03': ("{% if not %}yes{% else %}no{% endif %}", {'not': True}, 'yes'),
- 'if-tag-not04': ("{% if not not %}no{% else %}yes{% endif %}", {'not': True}, 'yes'),
- 'if-tag-not05': ("{% if not not %}no{% else %}yes{% endif %}", {}, 'no'),
-
- 'if-tag-not06': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {}, 'no'),
- 'if-tag-not07': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
- 'if-tag-not08': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
- 'if-tag-not09': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
- 'if-tag-not10': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
-
- 'if-tag-not11': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {}, 'no'),
- 'if-tag-not12': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
- 'if-tag-not13': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
- 'if-tag-not14': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
- 'if-tag-not15': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
-
- 'if-tag-not16': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'),
- 'if-tag-not17': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
- 'if-tag-not18': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
- 'if-tag-not19': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
- 'if-tag-not20': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
-
- 'if-tag-not21': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {}, 'yes'),
- 'if-tag-not22': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
- 'if-tag-not23': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
- 'if-tag-not24': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
- 'if-tag-not25': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
-
- 'if-tag-not26': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {}, 'yes'),
- 'if-tag-not27': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
- 'if-tag-not28': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
- 'if-tag-not29': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
- 'if-tag-not30': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
-
- 'if-tag-not31': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'),
- 'if-tag-not32': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
- 'if-tag-not33': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
- 'if-tag-not34': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
- 'if-tag-not35': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
-
- # AND and OR raises a TemplateSyntaxError
- 'if-tag-error01': ("{% if foo or bar and baz %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, template.TemplateSyntaxError),
- 'if-tag-error02': ("{% if foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
- 'if-tag-error03': ("{% if foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
- 'if-tag-error04': ("{% if not foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
- 'if-tag-error05': ("{% if not foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
-
- ### IFCHANGED TAG #########################################################
- 'ifchanged01': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,2,3) }, '123'),
- 'ifchanged02': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,3) }, '13'),
- 'ifchanged03': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,1) }, '1'),
-
- ### IFEQUAL TAG ###########################################################
- 'ifequal01': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""),
- 'ifequal02': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 1}, "yes"),
- 'ifequal03': ("{% ifequal a b %}yes{% else %}no{% endifequal %}", {"a": 1, "b": 2}, "no"),
- 'ifequal04': ("{% ifequal a b %}yes{% else %}no{% endifequal %}", {"a": 1, "b": 1}, "yes"),
- 'ifequal05': ("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}", {"a": "test"}, "yes"),
- 'ifequal06': ("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}", {"a": "no"}, "no"),
- 'ifequal07': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {"a": "test"}, "yes"),
- 'ifequal08': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {"a": "no"}, "no"),
- 'ifequal09': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {}, "no"),
- 'ifequal10': ('{% ifequal a b %}yes{% else %}no{% endifequal %}', {}, "yes"),
-
- # SMART SPLITTING
- 'ifequal-split01': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {}, "no"),
- 'ifequal-split02': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'foo'}, "no"),
- 'ifequal-split03': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'test man'}, "yes"),
- 'ifequal-split04': ("{% ifequal a 'test man' %}yes{% else %}no{% endifequal %}", {'a': 'test man'}, "yes"),
- 'ifequal-split05': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': ''}, "no"),
- 'ifequal-split06': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i "love" you'}, "yes"),
- 'ifequal-split07': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i love you'}, "no"),
- 'ifequal-split08': (r"{% ifequal a 'I\'m happy' %}yes{% else %}no{% endifequal %}", {'a': "I'm happy"}, "yes"),
- 'ifequal-split09': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slash\man"}, "yes"),
- 'ifequal-split10': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slashman"}, "no"),
-
- ### IFNOTEQUAL TAG ########################################################
- 'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
- 'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),
- 'ifnotequal03': ("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
- 'ifnotequal04': ("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 1}, "no"),
-
- ### INCLUDE TAG ###########################################################
- 'include01': ('{% include "basic-syntax01" %}', {}, "something cool"),
- 'include02': ('{% include "basic-syntax02" %}', {'headline': 'Included'}, "Included"),
- 'include03': ('{% include template_name %}', {'template_name': 'basic-syntax02', 'headline': 'Included'}, "Included"),
- 'include04': ('a{% include "nonexistent" %}b', {}, "ab"),
-
- ### INHERITANCE ###########################################################
-
- # Standard template with no inheritance
- 'inheritance01': ("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}", {}, '1_3_'),
-
- # Standard two-level inheritance
- 'inheritance02': ("{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {}, '1234'),
-
- # Three-level with no redefinitions on third level
- 'inheritance03': ("{% extends 'inheritance02' %}", {}, '1234'),
-
- # Two-level with no redefinitions on second level
- 'inheritance04': ("{% extends 'inheritance01' %}", {}, '1_3_'),
-
- # Two-level with double quotes instead of single quotes
- 'inheritance05': ('{% extends "inheritance02" %}', {}, '1234'),
-
- # Three-level with variable parent-template name
- 'inheritance06': ("{% extends foo %}", {'foo': 'inheritance02'}, '1234'),
-
- # Two-level with one block defined, one block not defined
- 'inheritance07': ("{% extends 'inheritance01' %}{% block second %}5{% endblock %}", {}, '1_35'),
-
- # Three-level with one block defined on this level, two blocks defined next level
- 'inheritance08': ("{% extends 'inheritance02' %}{% block second %}5{% endblock %}", {}, '1235'),
-
- # Three-level with second and third levels blank
- 'inheritance09': ("{% extends 'inheritance04' %}", {}, '1_3_'),
-
- # Three-level with space NOT in a block -- should be ignored
- 'inheritance10': ("{% extends 'inheritance04' %} ", {}, '1_3_'),
-
- # Three-level with both blocks defined on this level, but none on second level
- 'inheritance11': ("{% extends 'inheritance04' %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {}, '1234'),
-
- # Three-level with this level providing one and second level providing the other
- 'inheritance12': ("{% extends 'inheritance07' %}{% block first %}2{% endblock %}", {}, '1235'),
-
- # Three-level with this level overriding second level
- 'inheritance13': ("{% extends 'inheritance02' %}{% block first %}a{% endblock %}{% block second %}b{% endblock %}", {}, '1a3b'),
-
- # A block defined only in a child template shouldn't be displayed
- 'inheritance14': ("{% extends 'inheritance01' %}{% block newblock %}NO DISPLAY{% endblock %}", {}, '1_3_'),
-
- # A block within another block
- 'inheritance15': ("{% extends 'inheritance01' %}{% block first %}2{% block inner %}inner{% endblock %}{% endblock %}", {}, '12inner3_'),
-
- # A block within another block (level 2)
- 'inheritance16': ("{% extends 'inheritance15' %}{% block inner %}out{% endblock %}", {}, '12out3_'),
-
- # {% load %} tag (parent -- setup for exception04)
- 'inheritance17': ("{% load testtags %}{% block first %}1234{% endblock %}", {}, '1234'),
-
- # {% load %} tag (standard usage, without inheritance)
- 'inheritance18': ("{% load testtags %}{% echo this that theother %}5678", {}, 'this that theother5678'),
-
- # {% load %} tag (within a child template)
- 'inheritance19': ("{% extends 'inheritance01' %}{% block first %}{% load testtags %}{% echo 400 %}5678{% endblock %}", {}, '140056783_'),
-
- # Two-level inheritance with {{ block.super }}
- 'inheritance20': ("{% extends 'inheritance01' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '1_a3_'),
-
- # Three-level inheritance with {{ block.super }} from parent
- 'inheritance21': ("{% extends 'inheritance02' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '12a34'),
-
- # Three-level inheritance with {{ block.super }} from grandparent
- 'inheritance22': ("{% extends 'inheritance04' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '1_a3_'),
-
- # Three-level inheritance with {{ block.super }} from parent and grandparent
- 'inheritance23': ("{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}", {}, '1_ab3_'),
-
- ### I18N ##################################################################
-
- # {% spaceless %} tag
- 'spaceless01': ("{% spaceless %} <b> <i> text </i> </b> {% endspaceless %}", {}, "<b> <i> text </i> </b>"),
- 'spaceless02': ("{% spaceless %} <b> \n <i> text </i> \n </b> {% endspaceless %}", {}, "<b> <i> text </i> </b>"),
- 'spaceless03': ("{% spaceless %}<b><i>text</i></b>{% endspaceless %}", {}, "<b><i>text</i></b>"),
-
- # simple translation of a string delimited by '
- 'i18n01': ("{% load i18n %}{% trans 'xxxyyyxxx' %}", {}, "xxxyyyxxx"),
-
- # simple translation of a string delimited by "
- 'i18n02': ('{% load i18n %}{% trans "xxxyyyxxx" %}', {}, "xxxyyyxxx"),
-
- # simple translation of a variable
- 'i18n03': ('{% load i18n %}{% blocktrans %}{{ anton }}{% endblocktrans %}', {'anton': 'xxxyyyxxx'}, "xxxyyyxxx"),
-
- # simple translation of a variable and filter
- 'i18n04': ('{% load i18n %}{% blocktrans with anton|lower as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'XXXYYYXXX'}, "xxxyyyxxx"),
-
- # simple translation of a string with interpolation
- 'i18n05': ('{% load i18n %}{% blocktrans %}xxx{{ anton }}xxx{% endblocktrans %}', {'anton': 'yyy'}, "xxxyyyxxx"),
-
- # simple translation of a string to german
- 'i18n06': ('{% load i18n %}{% trans "Page not found" %}', {'LANGUAGE_CODE': 'de'}, "Seite nicht gefunden"),
-
- # translation of singular form
- 'i18n07': ('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}plural{% endblocktrans %}', {'number': 1}, "singular"),
-
- # translation of plural form
- 'i18n08': ('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}plural{% endblocktrans %}', {'number': 2}, "plural"),
-
- # simple non-translation (only marking) of a string to german
- 'i18n09': ('{% load i18n %}{% trans "Page not found" noop %}', {'LANGUAGE_CODE': 'de'}, "Page not found"),
-
- # translation of a variable with a translated filter
- 'i18n10': ('{{ bool|yesno:_("ja,nein") }}', {'bool': True}, 'ja'),
-
- # translation of a variable with a non-translated filter
- 'i18n11': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'),
-
- # usage of the get_available_languages tag
- 'i18n12': ('{% load i18n %}{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.0 }}{% endifequal %}{% endfor %}', {}, 'de'),
-
- # translation of a constant string
- 'i18n13': ('{{ _("Page not found") }}', {'LANGUAGE_CODE': 'de'}, 'Seite nicht gefunden'),
-
- ### MULTILINE #############################################################
-
- 'multiline01': ("""
- Hello,
- boys.
- How
- are
- you
- gentlemen.
- """,
- {},
- """
- Hello,
- boys.
- How
- are
- you
- gentlemen.
- """),
-
- ### REGROUP TAG ###########################################################
- 'regroup01': ('{% regroup data by bar as grouped %}' + \
- '{% for group in grouped %}' + \
- '{{ group.grouper }}:' + \
- '{% for item in group.list %}' + \
- '{{ item.foo }}' + \
- '{% endfor %},' + \
- '{% endfor %}',
- {'data': [ {'foo':'c', 'bar':1},
- {'foo':'d', 'bar':1},
- {'foo':'a', 'bar':2},
- {'foo':'b', 'bar':2},
- {'foo':'x', 'bar':3} ]},
- '1:cd,2:ab,3:x,'),
-
- # Test for silent failure when target variable isn't found
- 'regroup02': ('{% regroup data by bar as grouped %}' + \
- '{% for group in grouped %}' + \
- '{{ group.grouper }}:' + \
- '{% for item in group.list %}' + \
- '{{ item.foo }}' + \
- '{% endfor %},' + \
- '{% endfor %}',
- {}, 'INVALID:INVALIDINVALIDINVALIDINVALIDINVALIDINVALIDINVALID,'),
-
- ### TEMPLATETAG TAG #######################################################
- 'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
- 'templatetag02': ('{% templatetag closeblock %}', {}, '%}'),
- 'templatetag03': ('{% templatetag openvariable %}', {}, '{{'),
- 'templatetag04': ('{% templatetag closevariable %}', {}, '}}'),
- 'templatetag05': ('{% templatetag %}', {}, template.TemplateSyntaxError),
- 'templatetag06': ('{% templatetag foo %}', {}, template.TemplateSyntaxError),
- 'templatetag07': ('{% templatetag openbrace %}', {}, '{'),
- 'templatetag08': ('{% templatetag closebrace %}', {}, '}'),
- 'templatetag09': ('{% templatetag openbrace %}{% templatetag openbrace %}', {}, '{{'),
- 'templatetag10': ('{% templatetag closebrace %}{% templatetag closebrace %}', {}, '}}'),
-
- ### WIDTHRATIO TAG ########################################################
- 'widthratio01': ('{% widthratio a b 0 %}', {'a':50,'b':100}, '0'),
- 'widthratio02': ('{% widthratio a b 100 %}', {'a':0,'b':0}, ''),
- 'widthratio03': ('{% widthratio a b 100 %}', {'a':0,'b':100}, '0'),
- 'widthratio04': ('{% widthratio a b 100 %}', {'a':50,'b':100}, '50'),
- 'widthratio05': ('{% widthratio a b 100 %}', {'a':100,'b':100}, '100'),
-
- # 62.5 should round to 63
- 'widthratio06': ('{% widthratio a b 100 %}', {'a':50,'b':80}, '63'),
-
- # 71.4 should round to 71
- 'widthratio07': ('{% widthratio a b 100 %}', {'a':50,'b':70}, '71'),
-
- # Raise exception if we don't have 3 args, last one an integer
- 'widthratio08': ('{% widthratio %}', {}, template.TemplateSyntaxError),
- 'widthratio09': ('{% widthratio a b %}', {'a':50,'b':100}, template.TemplateSyntaxError),
- 'widthratio10': ('{% widthratio a b 100.0 %}', {'a':50,'b':100}, template.TemplateSyntaxError),
-
- ### NOW TAG ########################################################
- # Simple case
- 'now01' : ('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)),
-
- # Check parsing of escaped and special characters
- 'now02' : ('{% now "j "n" Y"%}', {}, template.TemplateSyntaxError),
-# 'now03' : ('{% now "j \"n\" Y"%}', {}, str(datetime.now().day) + '"' + str(datetime.now().month) + '"' + str(datetime.now().year)),
-# 'now04' : ('{% now "j \nn\n Y"%}', {}, str(datetime.now().day) + '\n' + str(datetime.now().month) + '\n' + str(datetime.now().year))
-
- ### TIMESINCE TAG ##################################################
- # Default compare with datetime.now()
- 'timesince01' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=-1)}, '1 minute'),
- 'timesince02' : ('{{ a|timesince }}', {'a':(datetime.now() - timedelta(days=1))}, '1 day'),
- 'timesince03' : ('{{ a|timesince }}', {'a':(datetime.now() -
- timedelta(hours=1, minutes=25))}, '1 hour, 25 minutes'),
-
- # Compare to a given parameter
- 'timesince04' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2), 'b':NOW + timedelta(days=1)}, '1 day'),
- 'timesince05' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2, minutes=1), 'b':NOW + timedelta(days=2)}, '1 minute'),
-
- # Check that timezone is respected
- 'timesince06' : ('{{ a|timesince:b }}', {'a':NOW_tz + timedelta(hours=8), 'b':NOW_tz}, '8 hours'),
-
- ### TIMEUNTIL TAG ##################################################
- # Default compare with datetime.now()
- 'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2)}, '2 minutes'),
- 'timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1))}, '1 day'),
- 'timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10))}, '8 hours, 10 minutes'),
-
- # Compare to a given parameter
- 'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=1), 'b':NOW - timedelta(days=2)}, '1 day'),
- 'timeuntil05' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=2), 'b':NOW - timedelta(days=2, minutes=1)}, '1 minute'),
-}
-
-def test_template_loader(template_name, template_dirs=None):
- "A custom template loader that loads the unit-test templates."
- try:
- return (TEMPLATE_TESTS[template_name][0] , "test:%s" % template_name)
- except KeyError:
- raise template.TemplateDoesNotExist, template_name
-
-def run_tests(verbosity=0, standalone=False):
- # Register our custom template loader.
- old_template_loaders = loader.template_source_loaders
- loader.template_source_loaders = [test_template_loader]
-
- failed_tests = []
- tests = TEMPLATE_TESTS.items()
- tests.sort()
-
- # Turn TEMPLATE_DEBUG off, because tests assume that.
- old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
- # Set TEMPLATE_STRING_IF_INVALID to a known string
- old_invalid, settings.TEMPLATE_STRING_IF_INVALID = settings.TEMPLATE_STRING_IF_INVALID, 'INVALID'
-
- for name, vals in tests:
- install()
- if 'LANGUAGE_CODE' in vals[1]:
- activate(vals[1]['LANGUAGE_CODE'])
- else:
- activate('en-us')
- try:
- output = loader.get_template(name).render(template.Context(vals[1]))
- except Exception, e:
- if e.__class__ == vals[2]:
- if verbosity:
- print "Template test: %s -- Passed" % name
- else:
- if verbosity:
- traceback.print_exc()
- print "Template test: %s -- FAILED. Got %s, exception: %s" % (name, e.__class__, e)
- failed_tests.append(name)
- continue
- if 'LANGUAGE_CODE' in vals[1]:
- deactivate()
- if output == vals[2]:
- if verbosity:
- print "Template test: %s -- Passed" % name
- else:
- if verbosity:
- print "Template test: %s -- FAILED. Expected %r, got %r" % (name, vals[2], output)
- failed_tests.append(name)
- loader.template_source_loaders = old_template_loaders
- deactivate()
- settings.TEMPLATE_DEBUG = old_td
- settings.TEMPLATE_STRING_IF_INVALID = old_invalid
-
- if failed_tests and not standalone:
- msg = "Template tests %s failed." % failed_tests
- if not verbosity:
- msg += " Re-run tests with -v1 to see actual failures"
- raise Exception, msg
-
-if __name__ == "__main__":
- settings.configure()
- run_tests(1, True)
diff --git a/tests/regressiontests/cache/__init__.py b/tests/regressiontests/cache/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/cache/__init__.py
diff --git a/tests/regressiontests/cache/models.py b/tests/regressiontests/cache/models.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/cache/models.py
diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py
new file mode 100644
index 0000000000..cf58ab321a
--- /dev/null
+++ b/tests/regressiontests/cache/tests.py
@@ -0,0 +1,71 @@
+# Unit tests for cache framework
+# Uses whatever cache backend is set in the test settings file.
+
+from django.core.cache import cache
+import time, unittest
+
+# functions/classes for complex data type tests
+def f():
+ return 42
+class C:
+ def m(n):
+ return 24
+
+class Cache(unittest.TestCase):
+ def test_simple(self):
+ # simple set/get
+ cache.set("key", "value")
+ self.assertEqual(cache.get("key"), "value")
+
+ def test_non_existent(self):
+ # get with non-existent keys
+ self.assertEqual(cache.get("does not exist"), None)
+ self.assertEqual(cache.get("does not exist", "bang!"), "bang!")
+
+ def test_get_many(self):
+ # get_many
+ cache.set('a', 'a')
+ cache.set('b', 'b')
+ cache.set('c', 'c')
+ cache.set('d', 'd')
+ self.assertEqual(cache.get_many(['a', 'c', 'd']), {'a' : 'a', 'c' : 'c', 'd' : 'd'})
+ self.assertEqual(cache.get_many(['a', 'b', 'e']), {'a' : 'a', 'b' : 'b'})
+
+ def test_delete(self):
+ # delete
+ cache.set("key1", "spam")
+ cache.set("key2", "eggs")
+ self.assertEqual(cache.get("key1"), "spam")
+ cache.delete("key1")
+ self.assertEqual(cache.get("key1"), None)
+ self.assertEqual(cache.get("key2"), "eggs")
+
+ def test_has_key(self):
+ # has_key
+ cache.set("hello", "goodbye")
+ self.assertEqual(cache.has_key("hello"), True)
+ self.assertEqual(cache.has_key("goodbye"), False)
+
+ def test_data_types(self):
+ # test data types
+ stuff = {
+ 'string' : 'this is a string',
+ 'int' : 42,
+ 'list' : [1, 2, 3, 4],
+ 'tuple' : (1, 2, 3, 4),
+ 'dict' : {'A': 1, 'B' : 2},
+ 'function' : f,
+ 'class' : C,
+ }
+ for (key, value) in stuff.items():
+ cache.set(key, value)
+ self.assertEqual(cache.get(key), value)
+
+ def test_expiration(self):
+ # expiration
+ cache.set('expire', 'very quickly', 1)
+ time.sleep(2)
+ self.assertEqual(cache.get("expire"), None)
+
+if __name__ == '__main__':
+ unittest.main() \ No newline at end of file
diff --git a/tests/regressiontests/dateformat/__init__.py b/tests/regressiontests/dateformat/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/dateformat/__init__.py
diff --git a/tests/regressiontests/dateformat/models.py b/tests/regressiontests/dateformat/models.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/dateformat/models.py
diff --git a/tests/othertests/dateformat.py b/tests/regressiontests/dateformat/tests.py
index 0287587b4a..6e28759a92 100644
--- a/tests/othertests/dateformat.py
+++ b/tests/regressiontests/dateformat/tests.py
@@ -21,22 +21,22 @@ r"""
'7'
>>> format(my_birthday, 'N')
'July'
->>> format(my_birthday, 'O')
-'+0100'
+>>> no_tz or format(my_birthday, 'O') == '+0100'
+True
>>> format(my_birthday, 'P')
'10 p.m.'
->>> format(my_birthday, 'r')
-'Sun, 8 Jul 1979 22:00:00 +0100'
+>>> no_tz or format(my_birthday, 'r') == 'Sun, 8 Jul 1979 22:00:00 +0100'
+True
>>> format(my_birthday, 's')
'00'
>>> format(my_birthday, 'S')
'th'
>>> format(my_birthday, 't')
'31'
->>> format(my_birthday, 'T')
-'CET'
->>> format(my_birthday, 'U')
-'300531600'
+>>> no_tz or format(my_birthday, 'T') == 'CET'
+True
+>>> no_tz or format(my_birthday, 'U') == '300531600'
+True
>>> format(my_birthday, 'w')
'0'
>>> format(my_birthday, 'W')
@@ -47,17 +47,17 @@ r"""
'1979'
>>> format(my_birthday, 'z')
'189'
->>> format(my_birthday, 'Z')
-'3600'
+>>> no_tz or format(my_birthday, 'Z') == '3600'
+True
->>> format(summertime, 'I')
-'1'
->>> format(summertime, 'O')
-'+0200'
->>> format(wintertime, 'I')
-'0'
->>> format(wintertime, 'O')
-'+0100'
+>>> no_tz or format(summertime, 'I') == '1'
+True
+>>> no_tz or format(summertime, 'O') == '+0200'
+True
+>>> no_tz or format(wintertime, 'I') == '0'
+True
+>>> no_tz or format(wintertime, 'O') == '+0100'
+True
>>> format(my_birthday, r'Y z \C\E\T')
'1979 189 CET'
@@ -73,7 +73,11 @@ format = dateformat.format
os.environ['TZ'] = 'Europe/Copenhagen'
translation.activate('en-us')
-time.tzset()
+try:
+ time.tzset()
+ no_tz = False
+except AttributeError:
+ no_tz = True
my_birthday = datetime.datetime(1979, 7, 8, 22, 00)
summertime = datetime.datetime(2005, 10, 30, 1, 00)
diff --git a/tests/regressiontests/db_typecasts/__init__.py b/tests/regressiontests/db_typecasts/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/db_typecasts/__init__.py
diff --git a/tests/regressiontests/db_typecasts/models.py b/tests/regressiontests/db_typecasts/models.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/db_typecasts/models.py
diff --git a/tests/othertests/db_typecasts.py b/tests/regressiontests/db_typecasts/tests.py
index ffc9b34aec..f4b77fe3a6 100644
--- a/tests/othertests/db_typecasts.py
+++ b/tests/regressiontests/db_typecasts/tests.py
@@ -1,7 +1,7 @@
# Unit tests for typecast functions in django.db.backends.util
from django.db.backends import util as typecasts
-import datetime
+import datetime, unittest
TEST_CASES = {
'typecast_date': (
@@ -45,7 +45,12 @@ TEST_CASES = {
),
}
-for k, v in TEST_CASES.items():
- for inpt, expected in v:
- got = getattr(typecasts, k)(inpt)
- assert got == expected, "In %s: %r doesn't match %r. Got %r instead." % (k, inpt, expected, got)
+class DBTypeCasts(unittest.TestCase):
+ def test_typeCasts(self):
+ for k, v in TEST_CASES.items():
+ for inpt, expected in v:
+ got = getattr(typecasts, k)(inpt)
+ assert got == expected, "In %s: %r doesn't match %r. Got %r instead." % (k, inpt, expected, got)
+
+if __name__ == '__main__':
+ unittest.main() \ No newline at end of file
diff --git a/tests/regressiontests/defaultfilters/__init__.py b/tests/regressiontests/defaultfilters/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/defaultfilters/__init__.py
diff --git a/tests/regressiontests/defaultfilters/models.py b/tests/regressiontests/defaultfilters/models.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/defaultfilters/models.py
diff --git a/tests/othertests/defaultfilters.py b/tests/regressiontests/defaultfilters/tests.py
index 1636b948d0..32d6ef5202 100644
--- a/tests/othertests/defaultfilters.py
+++ b/tests/regressiontests/defaultfilters/tests.py
@@ -15,6 +15,9 @@ r"""
>>> addslashes('"double quotes" and \'single quotes\'')
'\\"double quotes\\" and \\\'single quotes\\\''
+>>> addslashes(r'\ : backslashes, too')
+'\\\\ : backslashes, too'
+
>>> capfirst('hello world')
'Hello world'
@@ -231,6 +234,9 @@ False
>>> time(datetime.time(13), "h")
'01'
+>>> time(datetime.time(0), "h")
+'12'
+
# real testing is done in timesince.py, where we can provide our own 'now'
>>> timesince(datetime.datetime.now() - datetime.timedelta(1))
'1 day'
diff --git a/tests/regressiontests/httpwrappers/__init__.py b/tests/regressiontests/httpwrappers/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/httpwrappers/__init__.py
diff --git a/tests/regressiontests/httpwrappers/models.py b/tests/regressiontests/httpwrappers/models.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/httpwrappers/models.py
diff --git a/tests/othertests/httpwrappers.py b/tests/regressiontests/httpwrappers/tests.py
index 385c3048d9..385c3048d9 100644
--- a/tests/othertests/httpwrappers.py
+++ b/tests/regressiontests/httpwrappers/tests.py
diff --git a/tests/regressiontests/initial_sql_regress/models.py b/tests/regressiontests/initial_sql_regress/models.py
index c4cf12bdf7..dedbba8e5c 100644
--- a/tests/regressiontests/initial_sql_regress/models.py
+++ b/tests/regressiontests/initial_sql_regress/models.py
@@ -7,7 +7,7 @@ from django.db import models
class Simple(models.Model):
name = models.CharField(maxlength = 50)
-API_TESTS = ""
+__test__ = {'API_TESTS':""}
# NOTE: The format of the included SQL file for this test suite is important.
# It must end with a trailing newline in order to test the fix for #2161.
diff --git a/tests/regressiontests/initial_sql_regress/sql/simple.sql b/tests/regressiontests/initial_sql_regress/sql/simple.sql
index ddb08bc91f..ca9bd40dab 100644
--- a/tests/regressiontests/initial_sql_regress/sql/simple.sql
+++ b/tests/regressiontests/initial_sql_regress/sql/simple.sql
@@ -4,4 +4,5 @@ INSERT INTO initial_sql_regress_simple (name) VALUES ('Ringo');
INSERT INTO initial_sql_regress_simple (name) VALUES ('George');
INSERT INTO initial_sql_regress_simple (name) VALUES ('Miles O''Brien');
INSERT INTO initial_sql_regress_simple (name) VALUES ('Semicolon;Man');
+INSERT INTO initial_sql_regress_simple (name) VALUES ('This line has a Windows line ending');
diff --git a/tests/regressiontests/many_to_one_regress/models.py b/tests/regressiontests/many_to_one_regress/models.py
index 485e928777..6c067446b1 100644
--- a/tests/regressiontests/many_to_one_regress/models.py
+++ b/tests/regressiontests/many_to_one_regress/models.py
@@ -10,4 +10,4 @@ class Second(models.Model):
# created (the field names being lower-cased versions of their opposite
# classes is important here).
-API_TESTS = ""
+__test__ = {'API_TESTS':""}
diff --git a/tests/regressiontests/markup/__init__.py b/tests/regressiontests/markup/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/markup/__init__.py
diff --git a/tests/regressiontests/markup/models.py b/tests/regressiontests/markup/models.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/markup/models.py
diff --git a/tests/regressiontests/markup/tests.py b/tests/regressiontests/markup/tests.py
new file mode 100644
index 0000000000..bd3f52b9dd
--- /dev/null
+++ b/tests/regressiontests/markup/tests.py
@@ -0,0 +1,69 @@
+# Quick tests for the markup templatetags (django.contrib.markup)
+
+from django.template import Template, Context, add_to_builtins
+import re
+import unittest
+
+add_to_builtins('django.contrib.markup.templatetags.markup')
+
+class Templates(unittest.TestCase):
+ def test_textile(self):
+ try:
+ import textile
+ except ImportError:
+ textile = None
+
+ textile_content = """Paragraph 1
+
+Paragraph 2 with "quotes" and @code@"""
+
+ t = Template("{{ textile_content|textile }}")
+ rendered = t.render(Context(locals())).strip()
+ if textile:
+ self.assertEqual(rendered, """<p>Paragraph 1</p>
+
+<p>Paragraph 2 with &#8220;quotes&#8221; and <code>code</code></p>""")
+ else:
+ self.assertEqual(rendered, textile_content)
+
+ def test_markdown(self):
+ try:
+ import markdown
+ except ImportError:
+ markdown = None
+
+ markdown_content = """Paragraph 1
+
+## An h2"""
+
+ t = Template("{{ markdown_content|markdown }}")
+ rendered = t.render(Context(locals())).strip()
+ if markdown:
+ pattern = re.compile("""<p>Paragraph 1\s*</p>\s*<h2>\s*An h2</h2>""")
+ self.assert_(pattern.match(rendered))
+ else:
+ self.assertEqual(rendered, markdown_content)
+
+ def test_docutils(self):
+ try:
+ import docutils
+ except ImportError:
+ docutils = None
+
+ rest_content = """Paragraph 1
+
+Paragraph 2 with a link_
+
+.. _link: http://www.example.com/"""
+
+ t = Template("{{ rest_content|restructuredtext }}")
+ rendered = t.render(Context(locals())).strip()
+ if docutils:
+ self.assertEqual(rendered, """<p>Paragraph 1</p>
+<p>Paragraph 2 with a <a class="reference" href="http://www.example.com/">link</a></p>""")
+ else:
+ self.assertEqual(rendered, rest_content)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/regressiontests/null_queries/__init__.py b/tests/regressiontests/null_queries/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/null_queries/__init__.py
diff --git a/tests/regressiontests/null_queries/models.py b/tests/regressiontests/null_queries/models.py
new file mode 100644
index 0000000000..09024f18c2
--- /dev/null
+++ b/tests/regressiontests/null_queries/models.py
@@ -0,0 +1,54 @@
+from django.db import models
+
+class Poll(models.Model):
+ question = models.CharField(maxlength=200)
+
+ def __str__(self):
+ return "Q: %s " % self.question
+
+class Choice(models.Model):
+ poll = models.ForeignKey(Poll)
+ choice = models.CharField(maxlength=200)
+
+ def __str__(self):
+ return "Choice: %s in poll %s" % (self.choice, self.poll)
+
+__test__ = {'API_TESTS':"""
+# Regression test for the use of None as a query value. None is interpreted as
+# an SQL NULL, but only in __exact queries.
+# Set up some initial polls and choices
+>>> p1 = Poll(question='Why?')
+>>> p1.save()
+>>> c1 = Choice(poll=p1, choice='Because.')
+>>> c1.save()
+>>> c2 = Choice(poll=p1, choice='Why Not?')
+>>> c2.save()
+
+# Exact query with value None returns nothing (=NULL in sql)
+>>> Choice.objects.filter(id__exact=None)
+[]
+
+# Valid query, but fails because foo isn't a keyword
+>>> Choice.objects.filter(foo__exact=None)
+Traceback (most recent call last):
+...
+TypeError: Cannot resolve keyword 'foo' into field
+
+# Can't use None on anything other than __exact
+>>> Choice.objects.filter(id__gt=None)
+Traceback (most recent call last):
+...
+ValueError: Cannot use None as a query value
+
+# Can't use None on anything other than __exact
+>>> Choice.objects.filter(foo__gt=None)
+Traceback (most recent call last):
+...
+ValueError: Cannot use None as a query value
+
+# Related managers use __exact=None implicitly if the object hasn't been saved.
+>>> p2 = Poll(question="How?")
+>>> p2.choice_set.all()
+[]
+
+"""}
diff --git a/tests/regressiontests/one_to_one_regress/models.py b/tests/regressiontests/one_to_one_regress/models.py
index 6cc1df4e5c..b81f4266e1 100644
--- a/tests/regressiontests/one_to_one_regress/models.py
+++ b/tests/regressiontests/one_to_one_regress/models.py
@@ -22,7 +22,7 @@ class Favorites(models.Model):
def __str__(self):
return "Favorites for %s" % self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Regression test for #1064 and #1506: Check that we create models via the m2m
# relation if the remote model has a OneToOneField.
>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
@@ -34,4 +34,4 @@ API_TESTS = """
>>> f.restaurants = [r]
>>> f.restaurants.all()
[<Restaurant: Demon Dogs the restaurant>]
-"""
+"""}
diff --git a/tests/regressiontests/string_lookup/models.py b/tests/regressiontests/string_lookup/models.py
index a4582ca4e9..441bb3f8a3 100644
--- a/tests/regressiontests/string_lookup/models.py
+++ b/tests/regressiontests/string_lookup/models.py
@@ -34,7 +34,7 @@ class Base(models.Model):
def __str__(self):
return "Base %s" % self.name
-API_TESTS = """
+__test__ = {'API_TESTS':"""
# Regression test for #1661 and #1662: Check that string form referencing of models works,
# both as pre and post reference, on all RelatedField types.
@@ -66,4 +66,4 @@ API_TESTS = """
>>> child1.parent
<Base: Base Base1>
-"""
+"""}
diff --git a/tests/regressiontests/templates/__init__.py b/tests/regressiontests/templates/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/templates/__init__.py
diff --git a/tests/regressiontests/templates/models.py b/tests/regressiontests/templates/models.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/templates/models.py
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
new file mode 100644
index 0000000000..ef31b853ca
--- /dev/null
+++ b/tests/regressiontests/templates/tests.py
@@ -0,0 +1,667 @@
+from django.conf import settings
+
+if __name__ == '__main__':
+ # When running this file in isolation, we need to set up the configuration
+ # before importing 'template'.
+ settings.configure()
+
+from django import template
+from django.template import loader
+from django.utils.translation import activate, deactivate, install
+from django.utils.tzinfo import LocalTimezone
+from datetime import datetime, timedelta
+import unittest
+
+#################################
+# Custom template tag for tests #
+#################################
+
+register = template.Library()
+
+class EchoNode(template.Node):
+ def __init__(self, contents):
+ self.contents = contents
+
+ def render(self, context):
+ return " ".join(self.contents)
+
+def do_echo(parser, token):
+ return EchoNode(token.contents.split()[1:])
+
+register.tag("echo", do_echo)
+
+template.libraries['django.templatetags.testtags'] = register
+
+#####################################
+# Helper objects for template tests #
+#####################################
+
+class SomeException(Exception):
+ silent_variable_failure = True
+
+class SomeOtherException(Exception):
+ pass
+
+class SomeClass:
+ def __init__(self):
+ self.otherclass = OtherClass()
+
+ def method(self):
+ return "SomeClass.method"
+
+ def method2(self, o):
+ return o
+
+ def method3(self):
+ raise SomeException
+
+ def method4(self):
+ raise SomeOtherException
+
+class OtherClass:
+ def method(self):
+ return "OtherClass.method"
+
+class Templates(unittest.TestCase):
+ def test_templates(self):
+ # NOW and NOW_tz are used by timesince tag tests.
+ NOW = datetime.now()
+ NOW_tz = datetime.now(LocalTimezone(datetime.now()))
+
+ # SYNTAX --
+ # 'template_name': ('template contents', 'context dict', 'expected string output' or Exception class)
+ TEMPLATE_TESTS = {
+
+ ### BASIC SYNTAX ##########################################################
+
+ # Plain text should go through the template parser untouched
+ 'basic-syntax01': ("something cool", {}, "something cool"),
+
+ # Variables should be replaced with their value in the current context
+ 'basic-syntax02': ("{{ headline }}", {'headline':'Success'}, "Success"),
+
+ # More than one replacement variable is allowed in a template
+ 'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"),
+
+ # Fail silently when a variable is not found in the current context
+ 'basic-syntax04': ("as{{ missing }}df", {}, ("asdf","asINVALIDdf")),
+
+ # A variable may not contain more than one word
+ 'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError),
+
+ # Raise TemplateSyntaxError for empty variable tags
+ 'basic-syntax07': ("{{ }}", {}, template.TemplateSyntaxError),
+ 'basic-syntax08': ("{{ }}", {}, template.TemplateSyntaxError),
+
+ # Attribute syntax allows a template to call an object's attribute
+ 'basic-syntax09': ("{{ var.method }}", {"var": SomeClass()}, "SomeClass.method"),
+
+ # Multiple levels of attribute access are allowed
+ 'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"),
+
+ # Fail silently when a variable's attribute isn't found
+ 'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, ("","INVALID")),
+
+ # Raise TemplateSyntaxError when trying to access a variable beginning with an underscore
+ 'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError),
+
+ # Raise TemplateSyntaxError when trying to access a variable containing an illegal character
+ 'basic-syntax13': ("{{ va>r }}", {}, template.TemplateSyntaxError),
+ 'basic-syntax14': ("{{ (var.r) }}", {}, template.TemplateSyntaxError),
+ 'basic-syntax15': ("{{ sp%am }}", {}, template.TemplateSyntaxError),
+ 'basic-syntax16': ("{{ eggs! }}", {}, template.TemplateSyntaxError),
+ 'basic-syntax17': ("{{ moo? }}", {}, template.TemplateSyntaxError),
+
+ # Attribute syntax allows a template to call a dictionary key's value
+ 'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"),
+
+ # Fail silently when a variable's dictionary key isn't found
+ 'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, ("","INVALID")),
+
+ # Fail silently when accessing a non-simple method
+ 'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, ("","INVALID")),
+
+ # Basic filter usage
+ 'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),
+
+ # Chained filters
+ 'basic-syntax22': ("{{ var|upper|lower }}", {"var": "Django is the greatest!"}, "django is the greatest!"),
+
+ # Raise TemplateSyntaxError for space between a variable and filter pipe
+ 'basic-syntax23': ("{{ var |upper }}", {}, template.TemplateSyntaxError),
+
+ # Raise TemplateSyntaxError for space after a filter pipe
+ 'basic-syntax24': ("{{ var| upper }}", {}, template.TemplateSyntaxError),
+
+ # Raise TemplateSyntaxError for a nonexistent filter
+ 'basic-syntax25': ("{{ var|does_not_exist }}", {}, template.TemplateSyntaxError),
+
+ # Raise TemplateSyntaxError when trying to access a filter containing an illegal character
+ 'basic-syntax26': ("{{ var|fil(ter) }}", {}, template.TemplateSyntaxError),
+
+ # Raise TemplateSyntaxError for invalid block tags
+ 'basic-syntax27': ("{% nothing_to_see_here %}", {}, template.TemplateSyntaxError),
+
+ # Raise TemplateSyntaxError for empty block tags
+ 'basic-syntax28': ("{% %}", {}, template.TemplateSyntaxError),
+
+ # Chained filters, with an argument to the first one
+ 'basic-syntax29': ('{{ var|removetags:"b i"|upper|lower }}', {"var": "<b><i>Yes</i></b>"}, "yes"),
+
+ # Escaped string as argument
+ 'basic-syntax30': (r'{{ var|default_if_none:" endquote\" hah" }}', {"var": None}, ' endquote" hah'),
+
+ # Variable as argument
+ 'basic-syntax31': (r'{{ var|default_if_none:var2 }}', {"var": None, "var2": "happy"}, 'happy'),
+
+ # Default argument testing
+ 'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),
+
+ # Fail silently for methods that raise an exception with a "silent_variable_failure" attribute
+ 'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, ("12", "1INVALID2")),
+
+ # In methods that raise an exception without a "silent_variable_attribute" set to True,
+ # the exception propogates
+ 'basic-syntax34': (r'1{{ var.method4 }}2', {"var": SomeClass()}, SomeOtherException),
+
+ # Escaped backslash in argument
+ 'basic-syntax35': (r'{{ var|default_if_none:"foo\bar" }}', {"var": None}, r'foo\bar'),
+
+ # Escaped backslash using known escape char
+ 'basic-syntax35': (r'{{ var|default_if_none:"foo\now" }}', {"var": None}, r'foo\now'),
+
+ # Empty strings can be passed as arguments to filters
+ 'basic-syntax36': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'),
+
+ ### COMMENT SYNTAX ########################################################
+ 'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),
+ 'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"),
+
+ # Comments can contain invalid stuff.
+ 'comment-syntax03': ("foo{# {% if %} #}", {}, "foo"),
+ 'comment-syntax04': ("foo{# {% endblock %} #}", {}, "foo"),
+ 'comment-syntax05': ("foo{# {% somerandomtag %} #}", {}, "foo"),
+ 'comment-syntax06': ("foo{# {% #}", {}, "foo"),
+ 'comment-syntax07': ("foo{# %} #}", {}, "foo"),
+ 'comment-syntax08': ("foo{# %} #}bar", {}, "foobar"),
+ 'comment-syntax09': ("foo{# {{ #}", {}, "foo"),
+ 'comment-syntax10': ("foo{# }} #}", {}, "foo"),
+ 'comment-syntax11': ("foo{# { #}", {}, "foo"),
+ 'comment-syntax12': ("foo{# } #}", {}, "foo"),
+
+ ### COMMENT TAG ###########################################################
+ 'comment-tag01': ("{% comment %}this is hidden{% endcomment %}hello", {}, "hello"),
+ 'comment-tag02': ("{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}", {}, "hello"),
+
+ # Comment tag can contain invalid stuff.
+ 'comment-tag03': ("foo{% comment %} {% if %} {% endcomment %}", {}, "foo"),
+ 'comment-tag04': ("foo{% comment %} {% endblock %} {% endcomment %}", {}, "foo"),
+ 'comment-tag05': ("foo{% comment %} {% somerandomtag %} {% endcomment %}", {}, "foo"),
+
+ ### CYCLE TAG #############################################################
+ 'cycle01': ('{% cycle a %}', {}, template.TemplateSyntaxError),
+ 'cycle02': ('{% cycle a,b,c as abc %}{% cycle abc %}', {}, 'ab'),
+ 'cycle03': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}', {}, 'abc'),
+ 'cycle04': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}', {}, 'abca'),
+ 'cycle05': ('{% cycle %}', {}, template.TemplateSyntaxError),
+ 'cycle06': ('{% cycle a %}', {}, template.TemplateSyntaxError),
+ 'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
+ 'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'),
+
+ ### EXCEPTIONS ############################################################
+
+ # Raise exception for invalid template name
+ 'exception01': ("{% extends 'nonexistent' %}", {}, template.TemplateSyntaxError),
+
+ # Raise exception for invalid template name (in variable)
+ 'exception02': ("{% extends nonexistent %}", {}, template.TemplateSyntaxError),
+
+ # Raise exception for extra {% extends %} tags
+ 'exception03': ("{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% extends 'inheritance16' %}", {}, template.TemplateSyntaxError),
+
+ # Raise exception for custom tags used in child with {% load %} tag in parent, not in child
+ 'exception04': ("{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}", {}, template.TemplateSyntaxError),
+
+ ### FILTER TAG ############################################################
+ 'filter01': ('{% filter upper %}{% endfilter %}', {}, ''),
+ 'filter02': ('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'),
+ 'filter03': ('{% filter upper|lower %}django{% endfilter %}', {}, 'django'),
+
+ ### FIRSTOF TAG ###########################################################
+ 'firstof01': ('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''),
+ 'firstof02': ('{% firstof a b c %}', {'a':1,'b':0,'c':0}, '1'),
+ 'firstof03': ('{% firstof a b c %}', {'a':0,'b':2,'c':0}, '2'),
+ 'firstof04': ('{% firstof a b c %}', {'a':0,'b':0,'c':3}, '3'),
+ 'firstof05': ('{% firstof a b c %}', {'a':1,'b':2,'c':3}, '1'),
+ 'firstof06': ('{% firstof %}', {}, template.TemplateSyntaxError),
+
+ ### FOR TAG ###############################################################
+ 'for-tag01': ("{% for val in values %}{{ val }}{% endfor %}", {"values": [1, 2, 3]}, "123"),
+ 'for-tag02': ("{% for val in values reversed %}{{ val }}{% endfor %}", {"values": [1, 2, 3]}, "321"),
+ 'for-tag-vars01': ("{% for val in values %}{{ forloop.counter }}{% endfor %}", {"values": [6, 6, 6]}, "123"),
+ 'for-tag-vars02': ("{% for val in values %}{{ forloop.counter0 }}{% endfor %}", {"values": [6, 6, 6]}, "012"),
+ 'for-tag-vars03': ("{% for val in values %}{{ forloop.revcounter }}{% endfor %}", {"values": [6, 6, 6]}, "321"),
+ 'for-tag-vars04': ("{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}", {"values": [6, 6, 6]}, "210"),
+
+ ### IF TAG ################################################################
+ 'if-tag01': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": True}, "yes"),
+ 'if-tag02': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": False}, "no"),
+ 'if-tag03': ("{% if foo %}yes{% else %}no{% endif %}", {}, "no"),
+
+ # AND
+ 'if-tag-and01': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
+ 'if-tag-and02': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
+ 'if-tag-and03': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
+ 'if-tag-and04': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
+ 'if-tag-and05': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'),
+ 'if-tag-and06': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'),
+ 'if-tag-and07': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True}, 'no'),
+ 'if-tag-and08': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': True}, 'no'),
+
+ # OR
+ 'if-tag-or01': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
+ 'if-tag-or02': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
+ 'if-tag-or03': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
+ 'if-tag-or04': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
+ 'if-tag-or05': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'),
+ 'if-tag-or06': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'),
+ 'if-tag-or07': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True}, 'yes'),
+ 'if-tag-or08': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': True}, 'yes'),
+
+ # TODO: multiple ORs
+
+ # NOT
+ 'if-tag-not01': ("{% if not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'yes'),
+ 'if-tag-not02': ("{% if not %}yes{% else %}no{% endif %}", {'foo': True}, 'no'),
+ 'if-tag-not03': ("{% if not %}yes{% else %}no{% endif %}", {'not': True}, 'yes'),
+ 'if-tag-not04': ("{% if not not %}no{% else %}yes{% endif %}", {'not': True}, 'yes'),
+ 'if-tag-not05': ("{% if not not %}no{% else %}yes{% endif %}", {}, 'no'),
+
+ 'if-tag-not06': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {}, 'no'),
+ 'if-tag-not07': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
+ 'if-tag-not08': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
+ 'if-tag-not09': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
+ 'if-tag-not10': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
+
+ 'if-tag-not11': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {}, 'no'),
+ 'if-tag-not12': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
+ 'if-tag-not13': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
+ 'if-tag-not14': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
+ 'if-tag-not15': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
+
+ 'if-tag-not16': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'),
+ 'if-tag-not17': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
+ 'if-tag-not18': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
+ 'if-tag-not19': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
+ 'if-tag-not20': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
+
+ 'if-tag-not21': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {}, 'yes'),
+ 'if-tag-not22': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
+ 'if-tag-not23': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
+ 'if-tag-not24': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
+ 'if-tag-not25': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
+
+ 'if-tag-not26': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {}, 'yes'),
+ 'if-tag-not27': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
+ 'if-tag-not28': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
+ 'if-tag-not29': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
+ 'if-tag-not30': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
+
+ 'if-tag-not31': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'),
+ 'if-tag-not32': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
+ 'if-tag-not33': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
+ 'if-tag-not34': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
+ 'if-tag-not35': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
+
+ # AND and OR raises a TemplateSyntaxError
+ 'if-tag-error01': ("{% if foo or bar and baz %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, template.TemplateSyntaxError),
+ 'if-tag-error02': ("{% if foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
+ 'if-tag-error03': ("{% if foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
+ 'if-tag-error04': ("{% if not foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
+ 'if-tag-error05': ("{% if not foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
+
+ ### IFCHANGED TAG #########################################################
+ 'ifchanged01': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,2,3) }, '123'),
+ 'ifchanged02': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,3) }, '13'),
+ 'ifchanged03': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,1) }, '1'),
+ 'ifchanged04': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 2, 3), 'numx': (2, 2, 2)}, '122232'),
+ 'ifchanged05': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'),
+ 'ifchanged06': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'),
+ 'ifchanged07': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'),
+
+ ### IFEQUAL TAG ###########################################################
+ 'ifequal01': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""),
+ 'ifequal02': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 1}, "yes"),
+ 'ifequal03': ("{% ifequal a b %}yes{% else %}no{% endifequal %}", {"a": 1, "b": 2}, "no"),
+ 'ifequal04': ("{% ifequal a b %}yes{% else %}no{% endifequal %}", {"a": 1, "b": 1}, "yes"),
+ 'ifequal05': ("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}", {"a": "test"}, "yes"),
+ 'ifequal06': ("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}", {"a": "no"}, "no"),
+ 'ifequal07': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {"a": "test"}, "yes"),
+ 'ifequal08': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {"a": "no"}, "no"),
+ 'ifequal09': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {}, "no"),
+ 'ifequal10': ('{% ifequal a b %}yes{% else %}no{% endifequal %}', {}, "yes"),
+
+ # SMART SPLITTING
+ 'ifequal-split01': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {}, "no"),
+ 'ifequal-split02': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'foo'}, "no"),
+ 'ifequal-split03': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'test man'}, "yes"),
+ 'ifequal-split04': ("{% ifequal a 'test man' %}yes{% else %}no{% endifequal %}", {'a': 'test man'}, "yes"),
+ 'ifequal-split05': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': ''}, "no"),
+ 'ifequal-split06': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i "love" you'}, "yes"),
+ 'ifequal-split07': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i love you'}, "no"),
+ 'ifequal-split08': (r"{% ifequal a 'I\'m happy' %}yes{% else %}no{% endifequal %}", {'a': "I'm happy"}, "yes"),
+ 'ifequal-split09': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slash\man"}, "yes"),
+ 'ifequal-split10': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slashman"}, "no"),
+
+ ### IFNOTEQUAL TAG ########################################################
+ 'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
+ 'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),
+ 'ifnotequal03': ("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
+ 'ifnotequal04': ("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 1}, "no"),
+
+ ### INCLUDE TAG ###########################################################
+ 'include01': ('{% include "basic-syntax01" %}', {}, "something cool"),
+ 'include02': ('{% include "basic-syntax02" %}', {'headline': 'Included'}, "Included"),
+ 'include03': ('{% include template_name %}', {'template_name': 'basic-syntax02', 'headline': 'Included'}, "Included"),
+ 'include04': ('a{% include "nonexistent" %}b', {}, "ab"),
+
+ ### INHERITANCE ###########################################################
+
+ # Standard template with no inheritance
+ 'inheritance01': ("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}", {}, '1_3_'),
+
+ # Standard two-level inheritance
+ 'inheritance02': ("{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {}, '1234'),
+
+ # Three-level with no redefinitions on third level
+ 'inheritance03': ("{% extends 'inheritance02' %}", {}, '1234'),
+
+ # Two-level with no redefinitions on second level
+ 'inheritance04': ("{% extends 'inheritance01' %}", {}, '1_3_'),
+
+ # Two-level with double quotes instead of single quotes
+ 'inheritance05': ('{% extends "inheritance02" %}', {}, '1234'),
+
+ # Three-level with variable parent-template name
+ 'inheritance06': ("{% extends foo %}", {'foo': 'inheritance02'}, '1234'),
+
+ # Two-level with one block defined, one block not defined
+ 'inheritance07': ("{% extends 'inheritance01' %}{% block second %}5{% endblock %}", {}, '1_35'),
+
+ # Three-level with one block defined on this level, two blocks defined next level
+ 'inheritance08': ("{% extends 'inheritance02' %}{% block second %}5{% endblock %}", {}, '1235'),
+
+ # Three-level with second and third levels blank
+ 'inheritance09': ("{% extends 'inheritance04' %}", {}, '1_3_'),
+
+ # Three-level with space NOT in a block -- should be ignored
+ 'inheritance10': ("{% extends 'inheritance04' %} ", {}, '1_3_'),
+
+ # Three-level with both blocks defined on this level, but none on second level
+ 'inheritance11': ("{% extends 'inheritance04' %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {}, '1234'),
+
+ # Three-level with this level providing one and second level providing the other
+ 'inheritance12': ("{% extends 'inheritance07' %}{% block first %}2{% endblock %}", {}, '1235'),
+
+ # Three-level with this level overriding second level
+ 'inheritance13': ("{% extends 'inheritance02' %}{% block first %}a{% endblock %}{% block second %}b{% endblock %}", {}, '1a3b'),
+
+ # A block defined only in a child template shouldn't be displayed
+ 'inheritance14': ("{% extends 'inheritance01' %}{% block newblock %}NO DISPLAY{% endblock %}", {}, '1_3_'),
+
+ # A block within another block
+ 'inheritance15': ("{% extends 'inheritance01' %}{% block first %}2{% block inner %}inner{% endblock %}{% endblock %}", {}, '12inner3_'),
+
+ # A block within another block (level 2)
+ 'inheritance16': ("{% extends 'inheritance15' %}{% block inner %}out{% endblock %}", {}, '12out3_'),
+
+ # {% load %} tag (parent -- setup for exception04)
+ 'inheritance17': ("{% load testtags %}{% block first %}1234{% endblock %}", {}, '1234'),
+
+ # {% load %} tag (standard usage, without inheritance)
+ 'inheritance18': ("{% load testtags %}{% echo this that theother %}5678", {}, 'this that theother5678'),
+
+ # {% load %} tag (within a child template)
+ 'inheritance19': ("{% extends 'inheritance01' %}{% block first %}{% load testtags %}{% echo 400 %}5678{% endblock %}", {}, '140056783_'),
+
+ # Two-level inheritance with {{ block.super }}
+ 'inheritance20': ("{% extends 'inheritance01' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '1_a3_'),
+
+ # Three-level inheritance with {{ block.super }} from parent
+ 'inheritance21': ("{% extends 'inheritance02' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '12a34'),
+
+ # Three-level inheritance with {{ block.super }} from grandparent
+ 'inheritance22': ("{% extends 'inheritance04' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '1_a3_'),
+
+ # Three-level inheritance with {{ block.super }} from parent and grandparent
+ 'inheritance23': ("{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}", {}, '1_ab3_'),
+
+ # Inheritance from local context without use of template loader
+ 'inheritance24': ("{% extends context_template %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")}, '1234'),
+
+ # Inheritance from local context with variable parent template
+ 'inheritance25': ("{% extends context_template.1 %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': [template.Template("Wrong"), template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")]}, '1234'),
+
+ ### I18N ##################################################################
+
+ # {% spaceless %} tag
+ 'spaceless01': ("{% spaceless %} <b> <i> text </i> </b> {% endspaceless %}", {}, "<b> <i> text </i> </b>"),
+ 'spaceless02': ("{% spaceless %} <b> \n <i> text </i> \n </b> {% endspaceless %}", {}, "<b> <i> text </i> </b>"),
+ 'spaceless03': ("{% spaceless %}<b><i>text</i></b>{% endspaceless %}", {}, "<b><i>text</i></b>"),
+
+ # simple translation of a string delimited by '
+ 'i18n01': ("{% load i18n %}{% trans 'xxxyyyxxx' %}", {}, "xxxyyyxxx"),
+
+ # simple translation of a string delimited by "
+ 'i18n02': ('{% load i18n %}{% trans "xxxyyyxxx" %}', {}, "xxxyyyxxx"),
+
+ # simple translation of a variable
+ 'i18n03': ('{% load i18n %}{% blocktrans %}{{ anton }}{% endblocktrans %}', {'anton': 'xxxyyyxxx'}, "xxxyyyxxx"),
+
+ # simple translation of a variable and filter
+ 'i18n04': ('{% load i18n %}{% blocktrans with anton|lower as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'XXXYYYXXX'}, "xxxyyyxxx"),
+
+ # simple translation of a string with interpolation
+ 'i18n05': ('{% load i18n %}{% blocktrans %}xxx{{ anton }}xxx{% endblocktrans %}', {'anton': 'yyy'}, "xxxyyyxxx"),
+
+ # simple translation of a string to german
+ 'i18n06': ('{% load i18n %}{% trans "Page not found" %}', {'LANGUAGE_CODE': 'de'}, "Seite nicht gefunden"),
+
+ # translation of singular form
+ 'i18n07': ('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}plural{% endblocktrans %}', {'number': 1}, "singular"),
+
+ # translation of plural form
+ 'i18n08': ('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}plural{% endblocktrans %}', {'number': 2}, "plural"),
+
+ # simple non-translation (only marking) of a string to german
+ 'i18n09': ('{% load i18n %}{% trans "Page not found" noop %}', {'LANGUAGE_CODE': 'de'}, "Page not found"),
+
+ # translation of a variable with a translated filter
+ 'i18n10': ('{{ bool|yesno:_("ja,nein") }}', {'bool': True}, 'ja'),
+
+ # translation of a variable with a non-translated filter
+ 'i18n11': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'),
+
+ # usage of the get_available_languages tag
+ 'i18n12': ('{% load i18n %}{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.0 }}{% endifequal %}{% endfor %}', {}, 'de'),
+
+ # translation of a constant string
+ 'i18n13': ('{{ _("Page not found") }}', {'LANGUAGE_CODE': 'de'}, 'Seite nicht gefunden'),
+
+ ### HANDLING OF TEMPLATE_TAG_IF_INVALID ###################################
+
+ 'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')),
+ 'invalidstr02': ('{{ var|default_if_none:"Foo" }}', {}, ('','INVALID')),
+ 'invalidstr03': ('{% for v in var %}({{ v }}){% endfor %}', {}, ''),
+ 'invalidstr04': ('{% if var %}Yes{% else %}No{% endif %}', {}, 'No'),
+ 'invalidstr04': ('{% if var|default:"Foo" %}Yes{% else %}No{% endif %}', {}, 'Yes'),
+
+ ### MULTILINE #############################################################
+
+ 'multiline01': ("""
+ Hello,
+ boys.
+ How
+ are
+ you
+ gentlemen.
+ """,
+ {},
+ """
+ Hello,
+ boys.
+ How
+ are
+ you
+ gentlemen.
+ """),
+
+ ### REGROUP TAG ###########################################################
+ 'regroup01': ('{% regroup data by bar as grouped %}' + \
+ '{% for group in grouped %}' + \
+ '{{ group.grouper }}:' + \
+ '{% for item in group.list %}' + \
+ '{{ item.foo }}' + \
+ '{% endfor %},' + \
+ '{% endfor %}',
+ {'data': [ {'foo':'c', 'bar':1},
+ {'foo':'d', 'bar':1},
+ {'foo':'a', 'bar':2},
+ {'foo':'b', 'bar':2},
+ {'foo':'x', 'bar':3} ]},
+ '1:cd,2:ab,3:x,'),
+
+ # Test for silent failure when target variable isn't found
+ 'regroup02': ('{% regroup data by bar as grouped %}' + \
+ '{% for group in grouped %}' + \
+ '{{ group.grouper }}:' + \
+ '{% for item in group.list %}' + \
+ '{{ item.foo }}' + \
+ '{% endfor %},' + \
+ '{% endfor %}',
+ {}, ''),
+
+ ### TEMPLATETAG TAG #######################################################
+ 'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
+ 'templatetag02': ('{% templatetag closeblock %}', {}, '%}'),
+ 'templatetag03': ('{% templatetag openvariable %}', {}, '{{'),
+ 'templatetag04': ('{% templatetag closevariable %}', {}, '}}'),
+ 'templatetag05': ('{% templatetag %}', {}, template.TemplateSyntaxError),
+ 'templatetag06': ('{% templatetag foo %}', {}, template.TemplateSyntaxError),
+ 'templatetag07': ('{% templatetag openbrace %}', {}, '{'),
+ 'templatetag08': ('{% templatetag closebrace %}', {}, '}'),
+ 'templatetag09': ('{% templatetag openbrace %}{% templatetag openbrace %}', {}, '{{'),
+ 'templatetag10': ('{% templatetag closebrace %}{% templatetag closebrace %}', {}, '}}'),
+
+ ### WIDTHRATIO TAG ########################################################
+ 'widthratio01': ('{% widthratio a b 0 %}', {'a':50,'b':100}, '0'),
+ 'widthratio02': ('{% widthratio a b 100 %}', {'a':0,'b':0}, ''),
+ 'widthratio03': ('{% widthratio a b 100 %}', {'a':0,'b':100}, '0'),
+ 'widthratio04': ('{% widthratio a b 100 %}', {'a':50,'b':100}, '50'),
+ 'widthratio05': ('{% widthratio a b 100 %}', {'a':100,'b':100}, '100'),
+
+ # 62.5 should round to 63
+ 'widthratio06': ('{% widthratio a b 100 %}', {'a':50,'b':80}, '63'),
+
+ # 71.4 should round to 71
+ 'widthratio07': ('{% widthratio a b 100 %}', {'a':50,'b':70}, '71'),
+
+ # Raise exception if we don't have 3 args, last one an integer
+ 'widthratio08': ('{% widthratio %}', {}, template.TemplateSyntaxError),
+ 'widthratio09': ('{% widthratio a b %}', {'a':50,'b':100}, template.TemplateSyntaxError),
+ 'widthratio10': ('{% widthratio a b 100.0 %}', {'a':50,'b':100}, template.TemplateSyntaxError),
+
+ ### NOW TAG ########################################################
+ # Simple case
+ 'now01' : ('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)),
+
+ # Check parsing of escaped and special characters
+ 'now02' : ('{% now "j "n" Y"%}', {}, template.TemplateSyntaxError),
+ # 'now03' : ('{% now "j \"n\" Y"%}', {}, str(datetime.now().day) + '"' + str(datetime.now().month) + '"' + str(datetime.now().year)),
+ # 'now04' : ('{% now "j \nn\n Y"%}', {}, str(datetime.now().day) + '\n' + str(datetime.now().month) + '\n' + str(datetime.now().year))
+
+ ### TIMESINCE TAG ##################################################
+ # Default compare with datetime.now()
+ 'timesince01' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=-1, seconds = -10)}, '1 minute'),
+ 'timesince02' : ('{{ a|timesince }}', {'a':(datetime.now() - timedelta(days=1, minutes = 1))}, '1 day'),
+ 'timesince03' : ('{{ a|timesince }}', {'a':(datetime.now() -
+ timedelta(hours=1, minutes=25, seconds = 10))}, '1 hour, 25 minutes'),
+
+ # Compare to a given parameter
+ 'timesince04' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2), 'b':NOW + timedelta(days=1)}, '1 day'),
+ 'timesince05' : ('{{ a|timesince:b }}', {'a':NOW + timedelta(days=2, minutes=1), 'b':NOW + timedelta(days=2)}, '1 minute'),
+
+ # Check that timezone is respected
+ 'timesince06' : ('{{ a|timesince:b }}', {'a':NOW_tz + timedelta(hours=8), 'b':NOW_tz}, '8 hours'),
+
+ ### TIMEUNTIL TAG ##################################################
+ # Default compare with datetime.now()
+ 'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'),
+ 'timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1, seconds = 10))}, '1 day'),
+ 'timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10, seconds = 10))}, '8 hours, 10 minutes'),
+
+ # Compare to a given parameter
+ 'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=1), 'b':NOW - timedelta(days=2)}, '1 day'),
+ 'timeuntil05' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=2), 'b':NOW - timedelta(days=2, minutes=1)}, '1 minute'),
+ }
+
+ # Register our custom template loader.
+ def test_template_loader(template_name, template_dirs=None):
+ "A custom template loader that loads the unit-test templates."
+ try:
+ return (TEMPLATE_TESTS[template_name][0] , "test:%s" % template_name)
+ except KeyError:
+ raise template.TemplateDoesNotExist, template_name
+
+ old_template_loaders = loader.template_source_loaders
+ loader.template_source_loaders = [test_template_loader]
+
+ failures = []
+ tests = TEMPLATE_TESTS.items()
+ tests.sort()
+
+ # Turn TEMPLATE_DEBUG off, because tests assume that.
+ old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
+
+ # Set TEMPLATE_STRING_IF_INVALID to a known string
+ old_invalid = settings.TEMPLATE_STRING_IF_INVALID
+
+ for name, vals in tests:
+ install()
+
+ if isinstance(vals[2], tuple):
+ normal_string_result = vals[2][0]
+ invalid_string_result = vals[2][1]
+ else:
+ normal_string_result = vals[2]
+ invalid_string_result = vals[2]
+
+ if 'LANGUAGE_CODE' in vals[1]:
+ activate(vals[1]['LANGUAGE_CODE'])
+ else:
+ activate('en-us')
+
+ for invalid_str, result in [('', normal_string_result),
+ ('INVALID', invalid_string_result)]:
+ settings.TEMPLATE_STRING_IF_INVALID = invalid_str
+ try:
+ output = loader.get_template(name).render(template.Context(vals[1]))
+ except Exception, e:
+ if e.__class__ != result:
+ failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s" % (invalid_str, name, e.__class__, e))
+ continue
+ if output != result:
+ failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (invalid_str, name, result, output))
+
+ if 'LANGUAGE_CODE' in vals[1]:
+ deactivate()
+
+ loader.template_source_loaders = old_template_loaders
+ deactivate()
+ settings.TEMPLATE_DEBUG = old_td
+ settings.TEMPLATE_STRING_IF_INVALID = old_invalid
+
+ self.assertEqual(failures, [], '\n'.join(failures))
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/regressiontests/urlpatterns_reverse/__init__.py b/tests/regressiontests/urlpatterns_reverse/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/urlpatterns_reverse/__init__.py
diff --git a/tests/regressiontests/urlpatterns_reverse/models.py b/tests/regressiontests/urlpatterns_reverse/models.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/urlpatterns_reverse/models.py
diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py
new file mode 100644
index 0000000000..8f571ac66c
--- /dev/null
+++ b/tests/regressiontests/urlpatterns_reverse/tests.py
@@ -0,0 +1,39 @@
+"Unit tests for reverse URL lookup"
+
+from django.core.urlresolvers import reverse_helper, NoReverseMatch
+import re, unittest
+
+test_data = (
+ ('^places/(\d+)/$', 'places/3/', [3], {}),
+ ('^places/(\d+)/$', 'places/3/', ['3'], {}),
+ ('^places/(\d+)/$', NoReverseMatch, ['a'], {}),
+ ('^places/(\d+)/$', NoReverseMatch, [], {}),
+ ('^places/(?P<id>\d+)/$', 'places/3/', [], {'id': 3}),
+ ('^people/(?P<name>\w+)/$', 'people/adrian/', ['adrian'], {}),
+ ('^people/(?P<name>\w+)/$', 'people/adrian/', [], {'name': 'adrian'}),
+ ('^people/(?P<name>\w+)/$', NoReverseMatch, ['name with spaces'], {}),
+ ('^people/(?P<name>\w+)/$', NoReverseMatch, [], {'name': 'name with spaces'}),
+ ('^people/(?P<name>\w+)/$', NoReverseMatch, [], {}),
+ ('^hardcoded/$', 'hardcoded/', [], {}),
+ ('^hardcoded/$', 'hardcoded/', ['any arg'], {}),
+ ('^hardcoded/$', 'hardcoded/', [], {'kwarg': 'foo'}),
+ ('^people/(?P<state>\w\w)/(?P<name>\w+)/$', 'people/il/adrian/', [], {'state': 'il', 'name': 'adrian'}),
+ ('^people/(?P<state>\w\w)/(?P<name>\d)/$', NoReverseMatch, [], {'state': 'il', 'name': 'adrian'}),
+ ('^people/(?P<state>\w\w)/(?P<name>\w+)/$', NoReverseMatch, [], {'state': 'il'}),
+ ('^people/(?P<state>\w\w)/(?P<name>\w+)/$', NoReverseMatch, [], {'name': 'adrian'}),
+ ('^people/(?P<state>\w\w)/(\w+)/$', NoReverseMatch, ['il'], {'name': 'adrian'}),
+ ('^people/(?P<state>\w\w)/(\w+)/$', 'people/il/adrian/', ['adrian'], {'state': 'il'}),
+)
+
+class URLPatternReverse(unittest.TestCase):
+ def test_urlpattern_reverse(self):
+ for regex, expected, args, kwargs in test_data:
+ try:
+ got = reverse_helper(re.compile(regex), *args, **kwargs)
+ except NoReverseMatch, e:
+ self.assertEqual(expected, NoReverseMatch)
+ else:
+ self.assertEquals(got, expected)
+
+if __name__ == "__main__":
+ run_tests(1)
diff --git a/tests/runtests.py b/tests/runtests.py
index b98a739249..359fca2bf5 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -1,23 +1,12 @@
#!/usr/bin/env python
-import os, re, sys, time, traceback
-
-# doctest is included in the same package as this module, because this testing
-# framework uses features only available in the Python 2.4 version of doctest,
-# and Django aims to work with Python 2.3+.
-import doctest
+import os, sys, traceback
+import unittest
MODEL_TESTS_DIR_NAME = 'modeltests'
-OTHER_TESTS_DIR = "othertests"
REGRESSION_TESTS_DIR_NAME = 'regressiontests'
TEST_DATABASE_NAME = 'django_test_db'
-
-error_list = []
-def log_error(model_name, title, description):
- error_list.append({
- 'title': "%r module: %s" % (model_name, title),
- 'description': description,
- })
+TEST_TEMPLATE_DIR = 'templates'
MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME)
REGRESSION_TEST_DIR = os.path.join(os.path.dirname(__file__), REGRESSION_TESTS_DIR_NAME)
@@ -37,258 +26,113 @@ def get_test_models():
models = []
for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR):
for f in os.listdir(dirpath):
- if f.startswith('__init__') or f.startswith('.') or f.startswith('sql'):
+ if f.startswith('__init__') or f.startswith('.') or f.startswith('sql') or f.startswith('invalid'):
continue
models.append((loc, f))
return models
-class DjangoDoctestRunner(doctest.DocTestRunner):
- def __init__(self, verbosity_level, *args, **kwargs):
- self.verbosity_level = verbosity_level
- doctest.DocTestRunner.__init__(self, *args, **kwargs)
- self._checker = DjangoDoctestOutputChecker()
- self.optionflags = doctest.ELLIPSIS
-
- def report_start(self, out, test, example):
- if self.verbosity_level > 1:
- out(" >>> %s\n" % example.source.strip())
-
- def report_failure(self, out, test, example, got):
- log_error(test.name, "API test failed",
- "Code: %r\nLine: %s\nExpected: %r\nGot: %r" % (example.source.strip(), example.lineno, example.want, got))
-
- def report_unexpected_exception(self, out, test, example, exc_info):
- from django.db import transaction
- tb = ''.join(traceback.format_exception(*exc_info)[1:])
- log_error(test.name, "API test raised an exception",
- "Code: %r\nLine: %s\nException: %s" % (example.source.strip(), example.lineno, tb))
- # Rollback, in case of database errors. Otherwise they'd have
- # side effects on other tests.
- transaction.rollback_unless_managed()
-
-normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)
-
-class DjangoDoctestOutputChecker(doctest.OutputChecker):
- def check_output(self, want, got, optionflags):
- ok = doctest.OutputChecker.check_output(self, want, got, optionflags)
-
- # Doctest does an exact string comparison of output, which means long
- # integers aren't equal to normal integers ("22L" vs. "22"). The
- # following code normalizes long integers so that they equal normal
- # integers.
- if not ok:
- return normalize_long_ints(want) == normalize_long_ints(got)
- return ok
-
-class TestRunner:
- def __init__(self, verbosity_level=0, which_tests=None):
- self.verbosity_level = verbosity_level
- self.which_tests = which_tests
-
- def output(self, required_level, message):
- if self.verbosity_level > required_level - 1:
- print message
-
- def run_tests(self):
- from django.conf import settings
-
- # An empty access of the settings to force the default options to be
- # installed prior to assigning to them.
- settings.INSTALLED_APPS
-
- # Manually set INSTALLED_APPS to point to the test models.
- settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS + ['.'.join(a) for a in get_test_models()]
-
- # Manually set DEBUG and USE_I18N.
- settings.DEBUG = False
- settings.USE_I18N = True
-
- from django.db import connection
+def get_invalid_models():
+ models = []
+ for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR):
+ for f in os.listdir(dirpath):
+ if f.startswith('__init__') or f.startswith('.') or f.startswith('sql'):
+ continue
+ if f.startswith('invalid'):
+ models.append((loc, f))
+ return models
+
+class InvalidModelTestCase(unittest.TestCase):
+ def __init__(self, model_label):
+ unittest.TestCase.__init__(self)
+ self.model_label = model_label
+
+ def runTest(self):
from django.core import management
- import django.db.models
-
- # Determine which models we're going to test.
- test_models = get_test_models()
- if 'othertests' in self.which_tests:
- self.which_tests.remove('othertests')
- run_othertests = True
- if not self.which_tests:
- test_models = []
- else:
- run_othertests = not self.which_tests
-
- if self.which_tests:
- # Only run the specified tests.
- bad_models = [m for m in self.which_tests if (MODEL_TESTS_DIR_NAME, m) not in test_models and (REGRESSION_TESTS_DIR_NAME, m) not in test_models]
- if bad_models:
- sys.stderr.write("Models not found: %s\n" % bad_models)
- sys.exit(1)
- else:
- all_tests = []
- for test in self.which_tests:
- for loc in MODEL_TESTS_DIR_NAME, REGRESSION_TESTS_DIR_NAME:
- if (loc, test) in test_models:
- all_tests.append((loc, test))
- test_models = all_tests
-
- self.output(0, "Running tests with database %r" % settings.DATABASE_ENGINE)
-
- # If we're using SQLite, it's more convenient to test against an
- # in-memory database.
- if settings.DATABASE_ENGINE == "sqlite3":
- global TEST_DATABASE_NAME
- TEST_DATABASE_NAME = ":memory:"
- else:
- # Create the test database and connect to it. We need to autocommit
- # if the database supports it because PostgreSQL doesn't allow
- # CREATE/DROP DATABASE statements within transactions.
- cursor = connection.cursor()
- self._set_autocommit(connection)
- self.output(1, "Creating test database")
- try:
- cursor.execute("CREATE DATABASE %s" % TEST_DATABASE_NAME)
- except Exception, e:
- sys.stderr.write("Got an error creating the test database: %s\n" % e)
- confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME)
- if confirm == 'yes':
- cursor.execute("DROP DATABASE %s" % TEST_DATABASE_NAME)
- cursor.execute("CREATE DATABASE %s" % TEST_DATABASE_NAME)
- else:
- print "Tests cancelled."
- return
- connection.close()
- old_database_name = settings.DATABASE_NAME
- settings.DATABASE_NAME = TEST_DATABASE_NAME
-
- # Initialize the test database.
- cursor = connection.cursor()
-
from django.db.models.loading import load_app
- # Install the core always installed apps
- for app in ALWAYS_INSTALLED_APPS:
- self.output(1, "Installing contrib app %s" % app)
- mod = load_app(app)
- management.install(mod)
-
- # Run the tests for each test model.
- self.output(1, "Running app tests")
- for model_dir, model_name in test_models:
- self.output(1, "%s model: Importing" % model_name)
- try:
- mod = load_app(model_dir + '.' + model_name)
- except Exception, e:
- log_error(model_name, "Error while importing", ''.join(traceback.format_exception(*sys.exc_info())[1:]))
- continue
-
- if not getattr(mod, 'error_log', None):
- # Model is not marked as an invalid model
- self.output(1, "%s.%s model: Installing" % (model_dir, model_name))
- management.install(mod)
-
- # Run the API tests.
- p = doctest.DocTestParser()
- test_namespace = dict([(m._meta.object_name, m) \
- for m in django.db.models.get_models(mod)])
- dtest = p.get_doctest(mod.API_TESTS, test_namespace, model_name, None, None)
- # Manually set verbose=False, because "-v" command-line parameter
- # has side effects on doctest TestRunner class.
- runner = DjangoDoctestRunner(verbosity_level=verbosity_level, verbose=False)
- self.output(1, "%s.%s model: Running tests" % (model_dir, model_name))
- runner.run(dtest, clear_globs=True, out=sys.stdout.write)
- else:
- # Check that model known to be invalid is invalid for the right reasons.
- self.output(1, "%s.%s model: Validating" % (model_dir, model_name))
-
- from cStringIO import StringIO
- s = StringIO()
- count = management.get_validation_errors(s, mod)
- s.seek(0)
- error_log = s.read()
- actual = error_log.split('\n')
- expected = mod.error_log.split('\n')
-
- unexpected = [err for err in actual if err not in expected]
- missing = [err for err in expected if err not in actual]
+ from cStringIO import StringIO
- if unexpected or missing:
- unexpected_log = '\n'.join(unexpected)
- missing_log = '\n'.join(missing)
- log_error(model_name,
- "Validator found %d validation errors, %d expected" % (count, len(expected) - 1),
- "Missing errors:\n%s\n\nUnexpected errors:\n%s" % (missing_log, unexpected_log))
+ try:
+ module = load_app(self.model_label)
+ except Exception, e:
+ self.fail('Unable to load invalid model module')
+
+ s = StringIO()
+ count = management.get_validation_errors(s, module)
+ s.seek(0)
+ error_log = s.read()
+ actual = error_log.split('\n')
+ expected = module.model_errors.split('\n')
- if run_othertests:
- # Run the non-model tests in the other tests dir
- self.output(1, "Running other tests")
- other_tests_dir = os.path.join(os.path.dirname(__file__), OTHER_TESTS_DIR)
- test_modules = [f[:-3] for f in os.listdir(other_tests_dir) if f.endswith('.py') and not f.startswith('__init__')]
- for module in test_modules:
- self.output(1, "%s module: Importing" % module)
- try:
- mod = __import__("othertests." + module, '', '', [''])
- except Exception, e:
- log_error(module, "Error while importing", ''.join(traceback.format_exception(*sys.exc_info())[1:]))
- continue
- if mod.__doc__:
- p = doctest.DocTestParser()
- dtest = p.get_doctest(mod.__doc__, mod.__dict__, module, None, None)
- runner = DjangoDoctestRunner(verbosity_level=verbosity_level, verbose=False)
- self.output(1, "%s module: running tests" % module)
- runner.run(dtest, clear_globs=True, out=sys.stdout.write)
- if hasattr(mod, "run_tests") and callable(mod.run_tests):
- self.output(1, "%s module: running tests" % module)
- try:
- mod.run_tests(verbosity_level)
- except Exception, e:
- log_error(module, "Exception running tests", ''.join(traceback.format_exception(*sys.exc_info())[1:]))
- continue
+ unexpected = [err for err in actual if err not in expected]
+ missing = [err for err in expected if err not in actual]
- # Unless we're using SQLite, remove the test database to clean up after
- # ourselves. Connect to the previous database (not the test database)
- # to do so, because it's not allowed to delete a database while being
- # connected to it.
- if settings.DATABASE_ENGINE != "sqlite3":
- connection.close()
- settings.DATABASE_NAME = old_database_name
- cursor = connection.cursor()
- self.output(1, "Deleting test database")
- self._set_autocommit(connection)
- time.sleep(1) # To avoid "database is being accessed by other users" errors.
- cursor.execute("DROP DATABASE %s" % TEST_DATABASE_NAME)
+ self.assert_(not unexpected, "Unexpected Errors: " + '\n'.join(unexpected))
+ self.assert_(not missing, "Missing Errors: " + '\n'.join(missing))
- # Display output.
- if error_list:
- for d in error_list:
- print
- print d['title']
- print "=" * len(d['title'])
- print d['description']
- print "%s error%s:" % (len(error_list), len(error_list) != 1 and 's' or '')
- else:
- print "All tests passed."
+def django_tests(verbosity, tests_to_run):
+ from django.conf import settings
+ from django.db.models.loading import get_apps, load_app
- def _set_autocommit(self, connection):
- """
- Make sure a connection is in autocommit mode.
- """
- if hasattr(connection.connection, "autocommit"):
- connection.connection.autocommit(True)
- elif hasattr(connection.connection, "set_isolation_level"):
- connection.connection.set_isolation_level(0)
+ old_installed_apps = settings.INSTALLED_APPS
+ old_test_database_name = settings.TEST_DATABASE_NAME
+ old_root_urlconf = settings.ROOT_URLCONF
+ old_template_dirs = settings.TEMPLATE_DIRS
+
+ # Redirect some settings for the duration of these tests
+ settings.TEST_DATABASE_NAME = TEST_DATABASE_NAME
+ settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS
+ settings.ROOT_URLCONF = 'urls'
+ settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), TEST_TEMPLATE_DIR),)
+
+ # load all the ALWAYS_INSTALLED_APPS
+ get_apps()
+
+ # Load all the test model apps
+ test_models = []
+ for model_dir, model_name in get_test_models():
+ model_label = '.'.join([model_dir, model_name])
+ try:
+ # if the model was named on the command line, or
+ # no models were named (i.e., run all), import
+ # this model and add it to the list to test.
+ if not tests_to_run or model_name in tests_to_run:
+ if verbosity >= 1:
+ print "Importing model %s" % model_name
+ mod = load_app(model_label)
+ settings.INSTALLED_APPS.append(model_label)
+ test_models.append(mod)
+ except Exception, e:
+ sys.stderr.write("Error while importing %s:" % model_name + ''.join(traceback.format_exception(*sys.exc_info())[1:]))
+ continue
+ # Add tests for invalid models
+ extra_tests = []
+ for model_dir, model_name in get_invalid_models():
+ model_label = '.'.join([model_dir, model_name])
+ if not tests_to_run or model_name in tests_to_run:
+ extra_tests.append(InvalidModelTestCase(model_label))
+
+ # Run the test suite, including the extra validation tests.
+ from django.test.simple import run_tests
+ run_tests(test_models, verbosity, extra_tests=extra_tests)
+
+ # Restore the old settings
+ settings.INSTALLED_APPS = old_installed_apps
+ settings.TESTS_DATABASE_NAME = old_test_database_name
+ settings.ROOT_URLCONF = old_root_urlconf
+ settings.TEMPLATE_DIRS = old_template_dirs
+
if __name__ == "__main__":
from optparse import OptionParser
usage = "%prog [options] [model model model ...]"
parser = OptionParser(usage=usage)
- parser.add_option('-v', help='How verbose should the output be? Choices are 0, 1 and 2, where 2 is most verbose. Default is 0.',
- type='choice', choices=['0', '1', '2'])
+ parser.add_option('-v','--verbosity', action='store', dest='verbosity', default='0',
+ type='choice', choices=['0', '1', '2'],
+ help='Verbosity level; 0=minimal output, 1=normal output, 2=all output')
parser.add_option('--settings',
help='Python path to settings module, e.g. "myproject.settings". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.')
options, args = parser.parse_args()
- verbosity_level = 0
- if options.v:
- verbosity_level = int(options.v)
if options.settings:
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
- t = TestRunner(verbosity_level, args)
- t.run_tests()
+
+ django_tests(int(options.verbosity), args)
diff --git a/tests/templates/404.html b/tests/templates/404.html
new file mode 100644
index 0000000000..da627e2222
--- /dev/null
+++ b/tests/templates/404.html
@@ -0,0 +1 @@
+Django Internal Tests: 404 Error \ No newline at end of file
diff --git a/tests/templates/500.html b/tests/templates/500.html
new file mode 100644
index 0000000000..ff028cbeb0
--- /dev/null
+++ b/tests/templates/500.html
@@ -0,0 +1 @@
+Django Internal Tests: 500 Error \ No newline at end of file
diff --git a/tests/templates/login.html b/tests/templates/login.html
new file mode 100644
index 0000000000..8a0974c9a1
--- /dev/null
+++ b/tests/templates/login.html
@@ -0,0 +1,19 @@
+<html>
+<head></head>
+<body>
+<h1>Django Internal Tests: Login</h1>
+{% if form.has_errors %}
+<p>Your username and password didn't match. Please try again.</p>
+{% endif %}
+
+<form method="post" action=".">
+<table>
+<tr><td><label for="id_username">Username:</label></td><td>{{ form.username }}</td></tr>
+<tr><td><label for="id_password">Password:</label></td><td>{{ form.password }}</td></tr>
+</table>
+
+<input type="submit" value="login" />
+<input type="hidden" name="next" value="{{ next }}" />
+</form>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/urls.py b/tests/urls.py
new file mode 100644
index 0000000000..39d5aaee6b
--- /dev/null
+++ b/tests/urls.py
@@ -0,0 +1,10 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+ # test_client modeltest urls
+ (r'^test_client/', include('modeltests.test_client.urls')),
+
+ # Always provide the auth system login and logout views
+ (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
+ (r'^accounts/logout/$', 'django.contrib.auth.views.login'),
+)