summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoulder Sprinters <boulder-sprinters@djangoproject.com>2007-05-14 15:58:54 +0000
committerBoulder Sprinters <boulder-sprinters@djangoproject.com>2007-05-14 15:58:54 +0000
commitc53378eb4b66742df4d8bcb4b9135e4fda343498 (patch)
treead46ed3d7f7f2bae60c9b65f79bece61dcf7ea0a
parentbcc26d8eeae483814ad80c80a0336311b17de8bf (diff)
downloaddjango-c53378eb4b66742df4d8bcb4b9135e4fda343498.tar.gz
boulder-oracle-sprint: Merged to [5234]
git-svn-id: http://code.djangoproject.com/svn/django/branches/boulder-oracle-sprint@5235 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--AUTHORS2
-rw-r--r--django/conf/global_settings.py1
-rw-r--r--django/conf/locale/bg/LC_MESSAGES/django.mobin0 -> 51713 bytes
-rw-r--r--django/conf/locale/bg/LC_MESSAGES/django.po2670
-rw-r--r--django/conf/locale/bg/LC_MESSAGES/djangojs.mobin0 -> 1727 bytes
-rw-r--r--django/conf/locale/bg/LC_MESSAGES/djangojs.po106
-rw-r--r--django/contrib/localflavor/is_/forms.py2
-rw-r--r--django/core/management.py16
-rw-r--r--django/core/serializers/python.py7
-rw-r--r--django/core/serializers/xml_serializer.py4
-rw-r--r--django/db/backends/postgresql/base.py4
-rw-r--r--django/db/backends/postgresql_psycopg2/base.py4
-rw-r--r--django/newforms/forms.py6
-rw-r--r--django/newforms/models.py47
-rw-r--r--django/test/testcases.py28
-rw-r--r--docs/databrowse.txt6
-rw-r--r--docs/i18n.txt2
-rw-r--r--docs/newforms.txt589
-rw-r--r--docs/testing.txt21
-rw-r--r--tests/modeltests/model_forms/models.py30
-rw-r--r--tests/regressiontests/forms/regressions.py14
-rw-r--r--tests/regressiontests/forms/tests.py100
-rw-r--r--tests/regressiontests/serializers_regress/models.py10
-rw-r--r--tests/regressiontests/serializers_regress/tests.py6
-rw-r--r--tests/regressiontests/test_client_regress/models.py28
25 files changed, 3604 insertions, 99 deletions
diff --git a/AUTHORS b/AUTHORS
index 855717ea64..1e6cc5be86 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -78,6 +78,7 @@ answer newbie questions, and generally made Django that much better:
flavio.curella@gmail.com
Jure Cuhalev <gandalf@owca.info>
dackze+django@gmail.com
+ David Danier <goliath.mailinglist@gmx.de>
Dirk Datzert <dummy@habmalnefrage.de>
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
dave@thebarproject.com
@@ -85,6 +86,7 @@ answer newbie questions, and generally made Django that much better:
Alex Dedul
deric@monowerks.com
Max Derkachev <mderk@yandex.ru>
+ Jordan Dimov <s3x3y1@gmail.com>
dne@mayonnaise.net
Maximillian Dornseif <md@hudora.de>
Jeremy Dunck <http://dunck.us/>
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
index 61751db8cd..9abc8d6a6c 100644
--- a/django/conf/global_settings.py
+++ b/django/conf/global_settings.py
@@ -38,6 +38,7 @@ LANGUAGE_CODE = 'en-us'
LANGUAGES = (
('ar', gettext_noop('Arabic')),
('bn', gettext_noop('Bengali')),
+ ('bg', gettext_noop('Bulgarian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
diff --git a/django/conf/locale/bg/LC_MESSAGES/django.mo b/django/conf/locale/bg/LC_MESSAGES/django.mo
new file mode 100644
index 0000000000..bfa09dcc23
--- /dev/null
+++ b/django/conf/locale/bg/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/bg/LC_MESSAGES/django.po b/django/conf/locale/bg/LC_MESSAGES/django.po
new file mode 100644
index 0000000000..9c1030685e
--- /dev/null
+++ b/django/conf/locale/bg/LC_MESSAGES/django.po
@@ -0,0 +1,2670 @@
+# translation of django.po to Bulgarian
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: django\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-04-05 01:32+1000\n"
+"PO-Revision-Date: 2007-05-12 17:45+0300\n"
+"Last-Translator: Jordan Dimov <s3x3y1@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: db/models/manipulators.py:307
+#, python-format
+msgid "%(object)s with this %(type)s already exists for the given %(field)s."
+msgstr "%(object)s с този %(type)s вече съществува за зададеното %(field)s.s"
+
+#: db/models/manipulators.py:308 contrib/admin/views/main.py:335
+#: contrib/admin/views/main.py:337 contrib/admin/views/main.py:339
+msgid "and"
+msgstr "и"
+
+#: db/models/fields/related.py:53
+#, python-format
+msgid "Please enter a valid %s."
+msgstr "Въведете валиден %s."
+
+#: db/models/fields/related.py:642
+msgid "Separate multiple IDs with commas."
+msgstr "Множество ID-та се разделят с запетайки"
+
+#: db/models/fields/related.py:644
+msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
+msgstr "Задръжте натиснат клавиша \"Control\" (или \"Command\" на Mac-а) за да направите повече от един избор. "
+
+#: db/models/fields/related.py:691
+#, 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] "Въведете валидни %(self)s ID-та. Стойността %(value)r не е валидна."
+msgstr[1] ""
+
+#: db/models/fields/__init__.py:42
+#, python-format
+msgid "%(optname)s with this %(fieldname)s already exists."
+msgstr "%(optname)s с този %(fieldname)s вече съществува."
+
+#: db/models/fields/__init__.py:117 db/models/fields/__init__.py:274
+#: db/models/fields/__init__.py:610 db/models/fields/__init__.py:621
+#: oldforms/__init__.py:357 newforms/fields.py:80 newforms/fields.py:376
+#: newforms/fields.py:452 newforms/fields.py:463 newforms/models.py:178
+msgid "This field is required."
+msgstr "Това поле е задължително."
+
+#: db/models/fields/__init__.py:367
+msgid "This value must be an integer."
+msgstr "Тази стойност трябва да бъде цяло число"
+
+#: db/models/fields/__init__.py:402
+msgid "This value must be either True or False."
+msgstr "Тази стойност трябва да бъде True или False."
+
+#: db/models/fields/__init__.py:423
+msgid "This field cannot be null."
+msgstr "Това поле не може да има празна стойност."
+
+#: db/models/fields/__init__.py:457 core/validators.py:148
+msgid "Enter a valid date in YYYY-MM-DD format."
+msgstr "Въведете валидна дата в формат ГГГГ-ММ-ДД."
+
+#: db/models/fields/__init__.py:526 core/validators.py:157
+msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
+msgstr "Въведете валидна дата и час в формат ГГГГ-ММ-ДД ЧЧ:ММ."
+
+#: db/models/fields/__init__.py:630
+msgid "Enter a valid filename."
+msgstr "Въведете валидно име на файл."
+
+#: db/models/fields/__init__.py:751
+msgid "This value must be either None, True or False."
+msgstr "Тази стойност трябва да бъде None, True, или False."
+
+#: conf/global_settings.py:39
+msgid "Arabic"
+msgstr "арабски"
+
+#: conf/global_settings.py:40
+msgid "Bengali"
+msgstr "бенгалски"
+
+#: conf/global_settings.py:41
+msgid "Catalan"
+msgstr "каталонски"
+
+#: conf/global_settings.py:42
+msgid "Czech"
+msgstr "чешки"
+
+#: conf/global_settings.py:43
+msgid "Welsh"
+msgstr "уелски"
+
+#: conf/global_settings.py:44
+msgid "Danish"
+msgstr "датски"
+
+#: conf/global_settings.py:45
+msgid "German"
+msgstr "немски"
+
+#: conf/global_settings.py:46
+msgid "Greek"
+msgstr "гръцки"
+
+#: conf/global_settings.py:47
+msgid "English"
+msgstr "английски"
+
+#: conf/global_settings.py:48
+msgid "Spanish"
+msgstr "испански"
+
+#: conf/global_settings.py:49
+msgid "Argentinean Spanish"
+msgstr "аржентински испански"
+
+#: conf/global_settings.py:50
+msgid "Finnish"
+msgstr "финландски"
+
+#: conf/global_settings.py:51
+msgid "French"
+msgstr "френски"
+
+#: conf/global_settings.py:52
+msgid "Galician"
+msgstr "галицейски"
+
+#: conf/global_settings.py:53
+msgid "Hungarian"
+msgstr "унгарски"
+
+#: conf/global_settings.py:54
+msgid "Hebrew"
+msgstr "еврит"
+
+#: conf/global_settings.py:55
+msgid "Icelandic"
+msgstr "исландски"
+
+#: conf/global_settings.py:56
+msgid "Italian"
+msgstr "италиански"
+
+#: conf/global_settings.py:57
+msgid "Japanese"
+msgstr "японски"
+
+#: conf/global_settings.py:58
+msgid "Kannada"
+msgstr "каннада (индийски)"
+
+#: conf/global_settings.py:59
+msgid "Latvian"
+msgstr "латвийски"
+
+#: conf/global_settings.py:60
+msgid "Macedonian"
+msgstr "македонски"
+
+#: conf/global_settings.py:61
+msgid "Dutch"
+msgstr "холандски"
+
+#: conf/global_settings.py:62
+msgid "Norwegian"
+msgstr "норвежки"
+
+#: conf/global_settings.py:63
+msgid "Polish"
+msgstr "полски"
+
+#: conf/global_settings.py:64
+msgid "Portugese"
+msgstr "португалски"
+
+#: conf/global_settings.py:65
+msgid "Brazilian"
+msgstr "бразилски"
+
+#: conf/global_settings.py:66
+msgid "Romanian"
+msgstr "ромънски"
+
+#: conf/global_settings.py:67
+msgid "Russian"
+msgstr "руски"
+
+#: conf/global_settings.py:68
+msgid "Slovak"
+msgstr "словашки"
+
+#: conf/global_settings.py:69
+msgid "Slovenian"
+msgstr "словенски"
+
+#: conf/global_settings.py:70
+msgid "Serbian"
+msgstr "сръбски"
+
+#: conf/global_settings.py:71
+msgid "Swedish"
+msgstr "шведски"
+
+#: conf/global_settings.py:72
+msgid "Tamil"
+msgstr "тамил (индийски)"
+
+#: conf/global_settings.py:73
+msgid "Telugu"
+msgstr "телугу (индийски)"
+
+#: conf/global_settings.py:74
+msgid "Turkish"
+msgstr "турски"
+
+#: conf/global_settings.py:75
+msgid "Ukrainian"
+msgstr "украински"
+
+#: conf/global_settings.py:76
+msgid "Simplified Chinese"
+msgstr "китайски"
+
+#: conf/global_settings.py:77
+msgid "Traditional Chinese"
+msgstr "традиционен китайски"
+
+#: 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/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/dateformat.py:40
+msgid "p.m."
+msgstr "p.m."
+
+#: utils/dateformat.py:41
+msgid "a.m."
+msgstr "a.m."
+
+#: utils/dateformat.py:46
+msgid "PM"
+msgstr "PM"
+
+#: utils/dateformat.py:47
+msgid "AM"
+msgstr "AM"
+
+#: utils/dateformat.py:95
+msgid "midnight"
+msgstr "полунощ"
+
+#: utils/dateformat.py:97
+msgid "noon"
+msgstr "обяд"
+
+#: utils/translation/trans_real.py:358
+msgid "DATE_FORMAT"
+msgstr "j N, Y"
+
+#: utils/translation/trans_real.py:359
+msgid "DATETIME_FORMAT"
+msgstr "j N, Y, P"
+
+#: utils/translation/trans_real.py:360
+msgid "TIME_FORMAT"
+msgstr "P"
+
+#: utils/translation/trans_real.py:376
+msgid "YEAR_MONTH_FORMAT"
+msgstr "F Y"
+
+#: utils/translation/trans_real.py:377
+msgid "MONTH_DAY_FORMAT"
+msgstr "j F"
+
+#: oldforms/__init__.py:392
+#, 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] ""
+
+#: oldforms/__init__.py:397
+msgid "Line breaks are not allowed here."
+msgstr "Тук не се допускат нови редове."
+
+#: oldforms/__init__.py:498 oldforms/__init__.py:571 oldforms/__init__.py:610
+#, python-format
+msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
+msgstr "Направете валиден избор; '%(data)s' не е сред %(choices)s."
+
+#: oldforms/__init__.py:577 contrib/admin/filterspecs.py:150
+#: newforms/widgets.py:174
+msgid "Unknown"
+msgstr "Неизвестно"
+
+#: oldforms/__init__.py:577 contrib/admin/filterspecs.py:143
+#: newforms/widgets.py:174
+msgid "Yes"
+msgstr "Да"
+
+#: oldforms/__init__.py:577 contrib/admin/filterspecs.py:143
+#: newforms/widgets.py:174
+msgid "No"
+msgstr "Не"
+
+#: oldforms/__init__.py:672 core/validators.py:174 core/validators.py:445
+msgid "No file was submitted. Check the encoding type on the form."
+msgstr "Не е получен файл. Проверете типът кодиране на формата. "
+
+#: oldforms/__init__.py:674
+msgid "The submitted file is empty."
+msgstr "Каченият файл е празен. "
+
+#: oldforms/__init__.py:730
+msgid "Enter a whole number between -32,768 and 32,767."
+msgstr "Въведете цяло число между -32768 и 32767."
+
+#: oldforms/__init__.py:740
+msgid "Enter a positive number."
+msgstr "Въведете положително число. "
+
+#: oldforms/__init__.py:750
+msgid "Enter a whole number between 0 and 32,767."
+msgstr "Въведете цяло число между 0 и 32767."
+
+#: contrib/localflavor/no/forms.py:15
+msgid "Enter a zip code in the format XXXX."
+msgstr "Въведете пощенски код в формат XXXX."
+
+#: contrib/localflavor/no/forms.py:36
+msgid "Enter a valid Norwegian social security number."
+msgstr "Въведете валиден норвежки номер на социалната осигуровка."
+
+#: contrib/localflavor/it/forms.py:14 contrib/localflavor/fr/forms.py:17
+#: contrib/localflavor/fi/forms.py:14 contrib/localflavor/de/forms.py:16
+msgid "Enter a zip code in the format XXXXX."
+msgstr "Въведете пощенски код в формат XXXXX."
+
+#: contrib/localflavor/jp/forms.py:21
+msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX."
+msgstr "Въведете пощенски код в формат XXXXXXX или XXX-XXXX."
+
+#: contrib/localflavor/jp/jp_prefectures.py:4
+msgid "Hokkaido"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:5
+msgid "Aomori"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:6
+msgid "Iwate"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:7
+msgid "Miyagi"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:8
+msgid "Akita"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:9
+msgid "Yamagata"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:10
+msgid "Fukushima"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:11
+msgid "Ibaraki"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:12
+msgid "Tochigi"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:13
+msgid "Gunma"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:14
+msgid "Saitama"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:15
+msgid "Chiba"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:16
+msgid "Tokyo"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:17
+msgid "Kanagawa"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:18
+msgid "Yamanashi"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:19
+msgid "Nagano"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:20
+msgid "Niigata"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:21
+msgid "Toyama"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:22
+msgid "Ishikawa"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:23
+msgid "Fukui"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:24
+msgid "Gifu"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:25
+msgid "Shizuoka"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:26
+msgid "Aichi"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:27
+msgid "Mie"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:28
+msgid "Shiga"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:29
+msgid "Kyoto"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:30
+msgid "Osaka"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:31
+msgid "Hyogo"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:32
+msgid "Nara"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:33
+msgid "Wakayama"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:34
+msgid "Tottori"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:35
+msgid "Shimane"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:36
+msgid "Okayama"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:37
+msgid "Hiroshima"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:38
+msgid "Yamaguchi"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:39
+msgid "Tokushima"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:40
+msgid "Kagawa"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:41
+msgid "Ehime"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:42
+msgid "Kochi"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:43
+msgid "Fukuoka"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:44
+msgid "Saga"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:45
+msgid "Nagasaki"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:46
+msgid "Kumamoto"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:47
+msgid "Oita"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:48
+msgid "Miyazaki"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:49
+msgid "Kagoshima"
+msgstr ""
+
+#: contrib/localflavor/jp/jp_prefectures.py:50
+msgid "Okinawa"
+msgstr ""
+
+#: contrib/localflavor/br/forms.py:18
+msgid "Enter a zip code in the format XXXXX-XXX."
+msgstr "Въведете пощенски код в формат XXXXX-XXX."
+
+#: contrib/localflavor/br/forms.py:30
+msgid "Phone numbers must be in XX-XXXX-XXXX format."
+msgstr "Телефонните номера трябва да бъдат в формат XX-XXXX-XXXX. "
+
+#: contrib/localflavor/fi/forms.py:40 contrib/localflavor/fi/forms.py:46
+msgid "Enter a valid Finnish social security number."
+msgstr "Въведете валиден финландски номер на социалната осигуровка."
+
+#: contrib/localflavor/uk/forms.py:18
+msgid "Enter a postcode. A space is required between the two postcode parts."
+msgstr "Въведете пощенски код. Между двете части на пощенския код трябва да има разстояние. "
+
+#: contrib/localflavor/de/forms.py:63
+msgid ""
+"Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X "
+"format"
+msgstr "Въведете валиден номер на германска лична карта в формат XXXXXXXXXXX-XXXXXXX-XXXXXXX-X."
+
+#: contrib/localflavor/de/de_states.py:5
+msgid "Baden-Wuerttemberg"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:6
+msgid "Bavaria"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:7
+msgid "Berlin"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:8
+msgid "Brandenburg"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:9
+msgid "Bremen"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:10
+msgid "Hamburg"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:11
+msgid "Hessen"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:12
+msgid "Mecklenburg-Western Pomerania"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:13
+msgid "Lower Saxony"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:14
+msgid "North Rhine-Westphalia"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:15
+msgid "Rhineland-Palatinate"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:16
+msgid "Saarland"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:17
+msgid "Saxony"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:18
+msgid "Saxony-Anhalt"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:19
+msgid "Schleswig-Holstein"
+msgstr ""
+
+#: contrib/localflavor/de/de_states.py:20
+msgid "Thuringia"
+msgstr ""
+
+#: contrib/localflavor/usa/forms.py:18
+msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX."
+msgstr "Въведете zip код в формат XXXXX или XXXXX-XXXX."
+
+#: contrib/localflavor/usa/forms.py:51
+msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format."
+msgstr "Въведете валиден номер на социалната осигуровка в формат XXX-XX-XXXX."
+
+#: contrib/sessions/models.py:68
+msgid "session key"
+msgstr "ключ на сесията"
+
+#: contrib/sessions/models.py:69
+msgid "session data"
+msgstr "данни от сесията"
+
+#: contrib/sessions/models.py:70
+msgid "expire date"
+msgstr "дата на валидност"
+
+#: contrib/sessions/models.py:74
+msgid "session"
+msgstr "сесия"
+
+#: contrib/sessions/models.py:75
+msgid "sessions"
+msgstr "сесии"
+
+#: contrib/auth/forms.py:17 contrib/auth/forms.py:138
+msgid "The two password fields didn't match."
+msgstr "Двете полета за паролата не съвпадат. "
+
+#: contrib/auth/forms.py:25
+msgid "A user with that username already exists."
+msgstr "Потребител с това потребителско име вече съществува. "
+
+#: contrib/auth/forms.py:53
+msgid ""
+"Your Web browser doesn't appear to have cookies enabled. Cookies are "
+"required for logging in."
+msgstr "Браузерът, който използвате не поддържа cookies, а те са необходими за да можете да се логнете. "
+
+#: contrib/auth/forms.py:60 contrib/admin/views/decorators.py:10
+msgid ""
+"Please enter a correct username and password. Note that both fields are case-"
+"sensitive."
+msgstr "Въведете правилно потребителско име и парола. И двете полета правят разлика между малки и големи букви!"
+
+#: contrib/auth/forms.py:62
+msgid "This account is inactive."
+msgstr "Този акаунт е деактивиран."
+
+#: contrib/auth/forms.py:85
+msgid ""
+"That e-mail address doesn't have an associated user account. Are you sure "
+"you've registered?"
+msgstr "С този email адрес няма обвързан потребителски акаунт. Сигурни ли сте, че сте се регистрирали?"
+
+#: contrib/auth/forms.py:117
+msgid "The two 'new password' fields didn't match."
+msgstr "Двете полета за нова парола не съвпадат. "
+
+#: contrib/auth/forms.py:124
+msgid "Your old password was entered incorrectly. Please enter it again."
+msgstr "Въвели сте погрешна стара парола. Въведете я пак. "
+
+#: 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:40
+msgid "codename"
+msgstr "код"
+
+#: contrib/auth/models.py:42
+msgid "permission"
+msgstr "право"
+
+#: contrib/auth/models.py:43 contrib/auth/models.py:58
+msgid "permissions"
+msgstr "права"
+
+#: contrib/auth/models.py:60
+msgid "group"
+msgstr "група"
+
+#: contrib/auth/models.py:61 contrib/auth/models.py:100
+msgid "groups"
+msgstr "групи"
+
+#: contrib/auth/models.py:90
+msgid "username"
+msgstr "потребител"
+
+#: 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:92
+msgid "last name"
+msgstr "фамилно име"
+
+#: contrib/auth/models.py:93
+msgid "e-mail address"
+msgstr "e-mail адрес"
+
+#: contrib/auth/models.py:94
+msgid "password"
+msgstr "парола"
+
+#: contrib/auth/models.py:94
+msgid ""
+"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
+"password form</a>."
+msgstr "Въведете '[algo]$[salt]$[hexdigest]' или използвайте <a href=\"password/\">формата за смяна на парола</a>."
+
+#: contrib/auth/models.py:95
+msgid "staff status"
+msgstr "персонал"
+
+#: contrib/auth/models.py:95
+msgid "Designates whether the user can log into this admin site."
+msgstr "Указва дали този потребител има достъп до административния панел."
+
+#: contrib/auth/models.py:96
+msgid "active"
+msgstr "активен"
+
+#: 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: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:99
+msgid "date joined"
+msgstr "дата на регистриране"
+
+#: 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:102
+msgid "user permissions"
+msgstr "потребителски права"
+
+#: contrib/auth/models.py:105
+msgid "user"
+msgstr "потребител"
+
+#: contrib/auth/models.py:106
+msgid "users"
+msgstr "потребители"
+
+#: contrib/auth/models.py:111
+msgid "Personal info"
+msgstr "Лична информация"
+
+#: contrib/auth/models.py:112
+msgid "Permissions"
+msgstr "Права"
+
+#: contrib/auth/models.py:113
+msgid "Important dates"
+msgstr "Важни дати"
+
+#: contrib/auth/models.py:114
+msgid "Groups"
+msgstr "Групи"
+
+#: contrib/auth/models.py:258
+msgid "message"
+msgstr "съобщение"
+
+#: contrib/humanize/templatetags/humanize.py:17
+msgid "th"
+msgstr "и"
+
+#: contrib/humanize/templatetags/humanize.py:17
+msgid "st"
+msgstr "ви"
+
+#: contrib/humanize/templatetags/humanize.py:17
+msgid "nd"
+msgstr "ри"
+
+#: contrib/humanize/templatetags/humanize.py:17
+msgid "rd"
+msgstr "ти"
+
+#: contrib/humanize/templatetags/humanize.py:47
+#, python-format
+msgid "%(value).1f million"
+msgid_plural "%(value).1f million"
+msgstr[0] "%(value).1f милион"
+msgstr[1] "%(value).1f милиона"
+
+#: contrib/humanize/templatetags/humanize.py:50
+#, python-format
+msgid "%(value).1f billion"
+msgid_plural "%(value).1f billion"
+msgstr[0] "%(value).1f милиард"
+msgstr[1] "%(value).1f милиарда"
+
+#: contrib/humanize/templatetags/humanize.py:53
+#, python-format
+msgid "%(value).1f trillion"
+msgid_plural "%(value).1f trillion"
+msgstr[0] "%(value).1f трилион"
+msgstr[1] "%(value).1f трилионаn"
+
+#: contrib/humanize/templatetags/humanize.py:68
+msgid "one"
+msgstr "един"
+
+#: contrib/humanize/templatetags/humanize.py:68
+msgid "two"
+msgstr "два"
+
+#: contrib/humanize/templatetags/humanize.py:68
+msgid "three"
+msgstr "три"
+
+#: contrib/humanize/templatetags/humanize.py:68
+msgid "four"
+msgstr "четири"
+
+#: contrib/humanize/templatetags/humanize.py:68
+msgid "five"
+msgstr "пет"
+
+#: contrib/humanize/templatetags/humanize.py:68
+msgid "six"
+msgstr "шест"
+
+#: contrib/humanize/templatetags/humanize.py:68
+msgid "seven"
+msgstr "седем"
+
+#: contrib/humanize/templatetags/humanize.py:68
+msgid "eight"
+msgstr "осем"
+
+#: contrib/humanize/templatetags/humanize.py:68
+msgid "nine"
+msgstr "девет"
+
+#: contrib/contenttypes/models.py:36
+msgid "python model class name"
+msgstr "има на класа на модела в Python"
+
+#: contrib/contenttypes/models.py:39
+msgid "content type"
+msgstr "тип на съдържанието"
+
+#: contrib/contenttypes/models.py:40
+msgid "content types"
+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 "Това може да бъде или абсолютен път (като горното) или пълен URL, започващ с 'http://'."
+
+#: contrib/redirects/models.py:13
+msgid "redirect"
+msgstr "препратка"
+
+#: contrib/redirects/models.py:14
+msgid "redirects"
+msgstr "препратки"
+
+#: 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 "Пример: '/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.html'. If this isn't provided, the system "
+"will use 'flatpages/default.html'."
+msgstr "Пример: 'flatpages/contact_page.html'. Ако това не е указано, системата ще използва 'flatpages/default.html'. "
+
+#: 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/comments/models.py:67 contrib/comments/models.py:166
+msgid "object ID"
+msgstr "ID на обекта"
+
+#: 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:304
+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 "Content обект"
+
+#: 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 "%(score)d рейтинг от %(user)s"
+
+#: 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/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_doc/bookmarklets.html:4
+#: contrib/admin/templates/admin_doc/missing_docutils.html:4
+#: contrib/admin/templates/admin_doc/view_detail.html:4
+#: contrib/admin/templates/admin_doc/template_filter_index.html:5
+#: contrib/admin/templates/admin_doc/view_index.html:5
+#: contrib/admin/templates/admin_doc/template_tag_index.html:5
+#: contrib/admin/templates/admin_doc/model_detail.html:3
+#: contrib/admin/templates/admin_doc/model_index.html:5
+#: contrib/admin/templates/admin_doc/index.html:4
+#: contrib/admin/templates/admin_doc/template_detail.html:4
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/admin/base.html:25
+#: contrib/admin/templates/admin/auth/user/change_password.html:9
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/registration/password_change_done.html:3
+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 "Рейтинги"
+
+#: 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:28
+#: contrib/comments/templates/comments/freeform.html:5
+msgid "Comment:"
+msgstr "Коментар:"
+
+#: 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
+msgid "Your name:"
+msgstr "Вашето име:"
+
+#: 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:27
+msgid "This rating is required because you've entered at least one other rating."
+msgstr "Този рейтинг е задължителен, понеже сте въвели поне един друг рейтинг. "
+
+#: 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] ""
+"Този коментар е от потребител, който има по-малко от %(count)s "
+"коментар:\n"
+"\n"
+"%(text)s"
+msgstr[1] ""
+"Този коментар е от потребител, който има по-малко от %(count)s "
+"коментара:\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 ""
+"Този коментар е от съмнителен потребител:\n"
+"\n"
+"%(text)s"
+
+#: contrib/comments/views/comments.py:188
+#: contrib/comments/views/comments.py:280
+msgid "Only POSTs are allowed"
+msgstr "Само POST заявките са позволени"
+
+#: 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:196
+#: contrib/comments/views/comments.py:286
+msgid "Somebody tampered with the comment form (security violation)"
+msgstr "Някой е променял формата за коментари (нарушение на сигурността)"
+
+#: 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 "Формата за коментарите има невалиден параметър '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 "Формата за коментарите не предоставя нито преглед нито постване. "
+
+#: 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 "сайтове"
+
+#: 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 contrib/admin/filterspecs.py:169
+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/models.py:16
+msgid "action time"
+msgstr "време на действие"
+
+#: contrib/admin/models.py:19
+msgid "object id"
+msgstr "id на обекта"
+
+#: contrib/admin/models.py:20
+msgid "object repr"
+msgstr "repr на обекта"
+
+#: 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:247
+msgid "All dates"
+msgstr "Всички дати"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+#: contrib/admin/templates/admin/500.html:4
+#: contrib/admin/templates/admin/invalid_setup.html:4
+#: contrib/admin/templates/admin/object_history.html:5
+#: contrib/admin/templates/admin/delete_confirmation.html:6
+#: contrib/admin/templates/admin/change_list.html:6
+#: contrib/admin/templates/admin/change_form.html:13
+#: contrib/admin/templates/admin/base.html:30
+#: contrib/admin/templates/admin/auth/user/change_password.html:12
+#: 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
+#: contrib/admin/templates/registration/password_reset_form.html:4
+msgid "Home"
+msgstr "Начало"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/admin/base.html:25
+#: contrib/admin/templates/admin/auth/user/change_password.html:9
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/registration/password_change_done.html:3
+msgid "Documentation"
+msgstr "Документация"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:3
+msgid "Bookmarklets"
+msgstr "Bookmarklet-и"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:4
+#: contrib/admin/templates/admin_doc/missing_docutils.html:4
+#: contrib/admin/templates/admin_doc/view_detail.html:4
+#: contrib/admin/templates/admin_doc/template_filter_index.html:5
+#: contrib/admin/templates/admin_doc/view_index.html:5
+#: contrib/admin/templates/admin_doc/template_tag_index.html:5
+#: contrib/admin/templates/admin_doc/model_detail.html:3
+#: contrib/admin/templates/admin_doc/model_index.html:5
+#: contrib/admin/templates/admin_doc/index.html:4
+#: contrib/admin/templates/admin_doc/template_detail.html:4
+#: contrib/admin/templates/admin/object_history.html:3
+#: contrib/admin/templates/admin/delete_confirmation.html:3
+#: contrib/admin/templates/admin/change_list.html:5
+#: contrib/admin/templates/admin/change_form.html:10
+#: contrib/admin/templates/admin/base.html:25
+#: contrib/admin/templates/admin/auth/user/change_password.html:9
+#: contrib/admin/templates/admin/auth/user/change_password.html:15
+#: contrib/admin/templates/admin/auth/user/change_password.html:46
+#: contrib/admin/templates/registration/password_change_form.html:3
+#: contrib/admin/templates/registration/password_change_done.html:3
+msgid "Change password"
+msgstr "Промени парола"
+
+#: contrib/admin/templates/admin_doc/bookmarklets.html:5
+msgid "Documentation bookmarklets"
+msgstr "Bookmarklet-и за документация"
+
+#: 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\">За да инсталирате bookmarklet-и, задърпайте линка в bookmarks\n"
+"toolbar-а, или щракнете с десния бутон и добавете линка в отметките. Сега можете да\n"
+"изберете bookmarklet-а от която и да е страница. Някой от тези\n"
+"bookmarklet-и могат да се разглеждат само от компютър, който е маркиран \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 "Препраща от която и да е страница към документацията за изгледа, който я е генерирал. "
+
+#: 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-то на страници, които представляват единичен обект. "
+
+#: 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 "Отива в админската страница за страници, които представляват единичен обект. "
+
+#: 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/admin/submit_line.html:3
+#: contrib/admin/templates/admin/delete_confirmation.html:9
+msgid "Delete"
+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/admin/500.html:4
+msgid "Server error"
+msgstr ""
+
+#: contrib/admin/templates/admin/500.html:6
+msgid "Server error (500)"
+msgstr ""
+
+#: contrib/admin/templates/admin/500.html:9
+msgid "Server Error <em>(500)</em>"
+msgstr "Server Error <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/filter.html:2
+#, python-format
+msgid " By %(filter_title)s "
+msgstr " По %(filter_title)s "
+
+#: contrib/admin/templates/admin/filters.html:4
+msgid "Filter"
+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/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/object_history.html:5
+#: contrib/admin/templates/admin/change_form.html:21
+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 "j N, 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 "Този обект няма исторя на промените. Вероятно не е добавен чрез административния панел. "
+
+#: 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 "Изтриването на обекта %(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 \"%(escaped_object)s\"? "
+"All of the following related items will be deleted:"
+msgstr ""
+"Наистина ли искате да затрием обектите %(object_name)s \"%(escaped_object)s\"? "
+"Следните свързани елементи също ще бъдат изтрити:"
+
+#: contrib/admin/templates/admin/delete_confirmation.html:26
+msgid "Yes, I'm sure"
+msgstr "Абсолютно"
+
+#: contrib/admin/templates/admin/pagination.html:10
+msgid "Show all"
+msgstr "Покажи всички"
+
+#: contrib/admin/templates/admin/change_list.html:12
+#, python-format
+msgid "Add %(name)s"
+msgstr "Добави %(name)s"
+
+#: contrib/admin/templates/admin/change_form.html:15
+#: contrib/admin/templates/admin/index.html:28
+msgid "Add"
+msgstr "Добави"
+
+#: contrib/admin/templates/admin/change_form.html:22
+msgid "View on site"
+msgstr "Разгледай в сайта"
+
+#: contrib/admin/templates/admin/change_form.html:32
+#: contrib/admin/templates/admin/auth/user/change_password.html:24
+msgid "Please correct the error below."
+msgid_plural "Please correct the errors below."
+msgstr[0] "Коригирайте долу допуснатата грешка. "
+msgstr[1] "Коригирайте долу допуснатите грешки."
+
+#: contrib/admin/templates/admin/change_form.html:50
+msgid "Ordering"
+msgstr "Подреждане"
+
+#: contrib/admin/templates/admin/change_form.html:53
+msgid "Order:"
+msgstr "Подредба:"
+
+#: contrib/admin/templates/admin/base.html:25
+msgid "Welcome,"
+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/login.html:25
+#: contrib/admin/views/decorators.py:24
+msgid "Log in"
+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 "Промени"
+
+#: 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/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/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
+#: contrib/admin/templates/admin/auth/user/change_password.html:34
+msgid "Password"
+msgstr "Парола"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:23
+#: contrib/admin/templates/admin/auth/user/change_password.html:39
+msgid "Password (again)"
+msgstr "Парола (пак)"
+
+#: contrib/admin/templates/admin/auth/user/add_form.html:24
+#: contrib/admin/templates/admin/auth/user/change_password.html:40
+msgid "Enter the same password as above, for verification."
+msgstr "Въведете същата парола още веднъж за проверка. "
+
+#: contrib/admin/templates/admin/auth/user/change_password.html:28
+#, python-format
+msgid "Enter a new password for the user <strong>%(username)s</strong>."
+msgstr "Въведете нова парола за потребител <strong>%(username)s</strong>."
+
+#: contrib/admin/templates/widget/file.html:2
+msgid "Currently:"
+msgstr "Сега:"
+
+#: contrib/admin/templates/widget/file.html:3
+msgid "Change:"
+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/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_email.html:2
+msgid "You're receiving this e-mail because you requested a password reset"
+msgstr "Получавате този e-mail, защото сте поръчали да Ви бъде издадена нова парола "
+
+#: 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/registration/password_reset_done.html:4
+#: 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
+msgid "Password reset"
+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: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 "Промяна на парола"
+
+#: 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_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: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 адреса по-долу и ще ви изпратим нова!"
+
+#: contrib/admin/templates/registration/password_reset_form.html:16
+msgid "E-mail address:"
+msgstr "E-mail адрес:"
+
+#: contrib/admin/templates/registration/password_reset_form.html:16
+msgid "Reset my password"
+msgstr "Нова парола"
+
+#: contrib/admin/views/main.py:223
+msgid "Site administration"
+msgstr "Администрация на сайта"
+
+#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:19
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was added successfully."
+msgstr "Обектът %(name)s \"%(obj)s\" бе успешно добавен. "
+
+#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347
+#: contrib/admin/views/auth.py:24
+msgid "You may edit it again below."
+msgstr "Може да го редактирате пак по-долу. "
+
+#: 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:289
+#, python-format
+msgid "Add %s"
+msgstr "Добави %s"
+
+#: contrib/admin/views/main.py:335
+#, python-format
+msgid "Added %s."
+msgstr "Добавен %s."
+
+#: contrib/admin/views/main.py:337
+#, python-format
+msgid "Changed %s."
+msgstr "Променен %s."
+
+#: contrib/admin/views/main.py:339
+#, python-format
+msgid "Deleted %s."
+msgstr "Изтрит %s."
+
+#: contrib/admin/views/main.py:342
+msgid "No fields changed."
+msgstr "Няма променени полета."
+
+#: 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: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:391
+#, python-format
+msgid "Change %s"
+msgstr "Промени %s"
+
+#: contrib/admin/views/main.py:476
+#, python-format
+msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
+msgstr "Едно или повече %(fieldname)s в %(name)s: %(obj)s"
+
+#: contrib/admin/views/main.py:481
+#, python-format
+msgid "One or more %(fieldname)s in %(name)s:"
+msgstr "Едно или повече %(fieldname)s в %(name)s:"
+
+#: contrib/admin/views/main.py:514
+#, python-format
+msgid "The %(name)s \"%(obj)s\" was deleted successfully."
+msgstr "Обектът %(name)s \"%(obj)s\" бе успешно изтрит. "
+
+#: contrib/admin/views/main.py:517
+msgid "Are you sure?"
+msgstr "Сериозно?"
+
+#: contrib/admin/views/main.py:539
+#, python-format
+msgid "Change history: %s"
+msgstr "История на промените: %s"
+
+#: contrib/admin/views/main.py:573
+#, python-format
+msgid "Select %s"
+msgstr "Изберете %s"
+
+#: contrib/admin/views/main.py:573
+#, python-format
+msgid "Select %s to change"
+msgstr "Изберете %s за промяна"
+
+#: contrib/admin/views/main.py:768
+msgid "Database error"
+msgstr "Грешка с базата данни"
+
+#: 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:69
+msgid ""
+"Looks like your browser isn't configured to accept cookies. Please enable "
+"cookies, reload this page, and try again."
+msgstr "Браузерът ви май не е настроен да приема cookies. Пуснете ги и заредете страницата на ново. "
+
+#: contrib/admin/views/decorators.py:83
+msgid "Usernames cannot contain the '@' character."
+msgstr "Потребителските имена не могат да съдържат символа '@'."
+
+#: contrib/admin/views/decorators.py:85
+#, python-format
+msgid "Your e-mail address is not your username. Try '%s' instead."
+msgstr "E-mail адресът ти не ти е потребителско име. Пробвай '%s'."
+
+#: 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 %(name)r not found in app %(label)r"
+msgstr "Моделът %(name)r го няма в приложение %(label)r"
+
+#: contrib/admin/views/doc.py:183
+#, python-format
+msgid "the related `%(label)s.%(type)s` object"
+msgstr "свързаният обект `%(label)s.%(type)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 `%(label)s.%(name)s` objects"
+msgstr "свързани `%(label)s.%(name)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:292
+msgid "Boolean (Either True or False)"
+msgstr "Boolean (True или False)"
+
+#: 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:294
+msgid "Comma-separated integers"
+msgstr "Цели числа, разделени с запетая"
+
+#: contrib/admin/views/doc.py:295
+msgid "Date (without time)"
+msgstr "Дата (без час)"
+
+#: contrib/admin/views/doc.py:296
+msgid "Date (with time)"
+msgstr "Дата (и час)"
+
+#: contrib/admin/views/doc.py:297
+msgid "E-mail address"
+msgstr "E-mail адрес"
+
+#: 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:300
+msgid "Decimal number"
+msgstr "Десетична дроб"
+
+#: contrib/admin/views/doc.py:306
+msgid "Boolean (Either True, False or None)"
+msgstr "Boolean (Възможните стойности са True, False или None)"
+
+#: contrib/admin/views/doc.py:307
+msgid "Relation to parent model"
+msgstr "Връзка с родителския обект"
+
+#: contrib/admin/views/doc.py:308
+msgid "Phone number"
+msgstr "Телефонен номер"
+
+#: contrib/admin/views/doc.py:313
+msgid "Text"
+msgstr "Текст"
+
+#: contrib/admin/views/doc.py:314
+msgid "Time"
+msgstr "Час"
+
+#: contrib/admin/views/doc.py:316
+msgid "U.S. state (two uppercase letters)"
+msgstr "американски щат (две главни букви)"
+
+#: contrib/admin/views/doc.py:317
+msgid "XML text"
+msgstr "XML текст"
+
+#: contrib/admin/views/doc.py:343
+#, python-format
+msgid "%s does not appear to be a urlpattern object"
+msgstr "%s не прилича на обект от тип urlpattern"
+
+#: contrib/admin/views/auth.py:30
+msgid "Add user"
+msgstr "Добави потребител"
+
+#: contrib/admin/views/auth.py:57
+msgid "Password changed successfully."
+msgstr "Паролата бе успешно сменена. "
+
+#: contrib/admin/views/auth.py:64
+#, python-format
+msgid "Change password: %s"
+msgstr "Смени парола: %s"
+
+#: newforms/fields.py:103 newforms/fields.py:256
+#, python-format
+msgid "Ensure this value has at most %d characters."
+msgstr "Тази стойност трябва да има не повече от %d символа. "
+
+#: newforms/fields.py:105 newforms/fields.py:258
+#, python-format
+msgid "Ensure this value has at least %d characters."
+msgstr "Тази стойност трябва да има поне %d символа. "
+
+#: newforms/fields.py:128 core/validators.py:120
+msgid "Enter a whole number."
+msgstr "Въведете цяло число. "
+
+#: newforms/fields.py:130
+#, python-format
+msgid "Ensure this value is less than or equal to %s."
+msgstr "Тази стойност трябва да е по-малка или равна на %s. "
+
+#: newforms/fields.py:132
+#, python-format
+msgid "Ensure this value is greater than or equal to %s."
+msgstr "Тази стойност трябва да е по-голяма или равна на %s."
+
+#: newforms/fields.py:165
+msgid "Enter a valid date."
+msgstr "Въведете валидна дата. "
+
+#: newforms/fields.py:192
+msgid "Enter a valid time."
+msgstr "Въведете валиден час."
+
+#: newforms/fields.py:228
+msgid "Enter a valid date/time."
+msgstr "Въведете валидна дата / час. "
+
+#: newforms/fields.py:242
+msgid "Enter a valid value."
+msgstr "Въведете валидна стойност. "
+
+#: newforms/fields.py:271 core/validators.py:162
+msgid "Enter a valid e-mail address."
+msgstr "Въведете валиден e-mail адрес. "
+
+#: newforms/fields.py:289 newforms/fields.py:311
+msgid "Enter a valid URL."
+msgstr "Въведете валиден URL. "
+
+#: newforms/fields.py:313
+msgid "This URL appears to be a broken link."
+msgstr "Този URL май е счупен линк. "
+
+#: newforms/fields.py:362 newforms/models.py:165
+msgid "Select a valid choice. That choice is not one of the available choices."
+msgstr "Направете валиден избор. Този не е един от възможните избори. "
+
+#: newforms/fields.py:380 newforms/fields.py:456 newforms/models.py:182
+msgid "Enter a list of values."
+msgstr "Въведете списък от стойности"
+
+#: newforms/fields.py:389 newforms/models.py:188
+#, python-format
+msgid "Select a valid choice. %s is not one of the available choices."
+msgstr "Направете валиден избор. %s не е един от възможните избори. "
+
+#: template/defaultfilters.py:491
+msgid "yes,no,maybe"
+msgstr "да,не,може-би"
+
+#: 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 бе затрит."
+
+#: core/validators.py:64
+msgid "This value must contain only letters, numbers and underscores."
+msgstr "Тази стойност може да съдържа само букви, цифри и подчертавки. "
+
+#: core/validators.py:68
+msgid ""
+"This value must contain only letters, numbers, underscores, dashes or "
+"slashes."
+msgstr "Тази стойност може да съдържа само букви, цифри, подчертавки, тиренца и наклонени чертички. "
+
+#: core/validators.py:72
+msgid "This value must contain only letters, numbers, underscores or hyphens."
+msgstr "Тази стойност трябва да съдържа само букви, цифри, подчертавки или тиренца. "
+
+#: core/validators.py:76
+msgid "Uppercase letters are not allowed here."
+msgstr "Тук не се допускат главни букви. "
+
+#: core/validators.py:80
+msgid "Lowercase letters are not allowed here."
+msgstr "Тук не се допускат малки букви. "
+
+#: core/validators.py:87
+msgid "Enter only digits separated by commas."
+msgstr "Въведете само цифри, разделени със запетая. "
+
+#: core/validators.py:99
+msgid "Enter valid e-mail addresses separated by commas."
+msgstr "Въведете валидни e-mail адреси разделени със запетая. "
+
+#: core/validators.py:103
+msgid "Please enter a valid IP address."
+msgstr "Въведете валиден IP адрес. "
+
+#: core/validators.py:107
+msgid "Empty values are not allowed here."
+msgstr "Тук не се допускат празни стойности. "
+
+#: core/validators.py:111
+msgid "Non-numeric characters aren't allowed here."
+msgstr "Тук не се допускат символи, които не са цифри. "
+
+#: core/validators.py:115
+msgid "This value can't be comprised solely of digits."
+msgstr "Тази стойност не може да бъде само цифри. "
+
+#: core/validators.py:124
+msgid "Only alphabetical characters are allowed here."
+msgstr "Само букви и цифри се допускат тук. "
+
+#: core/validators.py:139
+msgid "Year must be 1900 or later."
+msgstr "Годината трябва да бъде от 1900 нагоре."
+
+#: core/validators.py:143
+#, python-format
+msgid "Invalid date: %s"
+msgstr "Невалидна дата: %s"
+
+#: core/validators.py:153
+msgid "Enter a valid time in HH:MM format."
+msgstr "Въведете валиден час във формат ЧЧ:ММ. "
+
+#: core/validators.py:178
+msgid ""
+"Upload a valid image. The file you uploaded was either not an image or a "
+"corrupted image."
+msgstr "Качете валидна картинка. Файлът, който сте качили или не е картинка или е развалена. "
+
+#: core/validators.py:185
+#, python-format
+msgid "The URL %s does not point to a valid image."
+msgstr "URL %s не сочи към валидна картинка. "
+
+#: core/validators.py:189
+#, python-format
+msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
+msgstr "Телефонните номера трябва да бъдат във формат XXX-XXX-XXXX. \"%s\" не е валиден. "
+
+#: core/validators.py:197
+#, python-format
+msgid "The URL %s does not point to a valid QuickTime video."
+msgstr "URL %s не сочи към валиден QuickTime видео клип."
+
+#: core/validators.py:201
+msgid "A valid URL is required."
+msgstr "Изисква се валиден URL."
+
+#: core/validators.py:215
+#, python-format
+msgid ""
+"Valid HTML is required. Specific errors are:\n"
+"%s"
+msgstr ""
+"Изисква се валиден HTML. Конкретните грешки са:\n"
+"%s"
+
+#: core/validators.py:222
+#, python-format
+msgid "Badly formed XML: %s"
+msgstr "Неправилно форматиран XML: %s"
+
+#: core/validators.py:239
+#, python-format
+msgid "Invalid URL: %s"
+msgstr "Невалиден URL: %s"
+
+#: core/validators.py:244 core/validators.py:246
+#, python-format
+msgid "The URL %s is a broken link."
+msgstr "Този URL %s е счупен линк. "
+
+#: core/validators.py:252
+msgid "Enter a valid U.S. state abbreviation."
+msgstr "Въведете валидно съкращение на американски щат. "
+
+#: core/validators.py:266
+#, 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:273
+#, python-format
+msgid "This field must match the '%s' field."
+msgstr "Това поле трябва да съвпада с полето '%s' ."
+
+#: core/validators.py:292
+msgid "Please enter something for at least one field."
+msgstr "Въведете нещичко поне за едното поле. "
+
+#: core/validators.py:301 core/validators.py:312
+msgid "Please enter both fields or leave them both empty."
+msgstr "Или въведете и двете полета или ги оставете празни."
+
+#: core/validators.py:320
+#, python-format
+msgid "This field must be given if %(field)s is %(value)s"
+msgstr "Това поле трябва да е зададено ако %(field)s е %(value)s"
+
+#: core/validators.py:333
+#, python-format
+msgid "This field must be given if %(field)s is not %(value)s"
+msgstr "Това поле трябва да е зададено ако %(field)s не е %(value)s"
+
+#: core/validators.py:352
+msgid "Duplicate values are not allowed."
+msgstr "Не са позволени стойности, които се повтарят. "
+
+#: core/validators.py:367
+#, python-format
+msgid "This value must be between %(lower)s and %(upper)s."
+msgstr "Тази стойност трябва да бъде между %(lower)s и %(upper)s."
+
+#: core/validators.py:369
+#, python-format
+msgid "This value must be at least %s."
+msgstr "Тази стойност трябва да бъде поне %s. "
+
+#: core/validators.py:371
+#, python-format
+msgid "This value must be no more than %s."
+msgstr "Тази стойност не трябва да надвишава %s."
+
+#: core/validators.py:407
+#, python-format
+msgid "This value must be a power of %s."
+msgstr "Тази стойност трябва да е точна степен на %s."
+
+#: core/validators.py:418
+msgid "Please enter a valid decimal number."
+msgstr "Въведете валидна десетична дроб. "
+
+#: core/validators.py:422
+#, 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 цифри. "
+
+#: core/validators.py:425
+#, 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:428
+#, 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 цифри след десетичната точка. "
+
+#: core/validators.py:438
+#, python-format
+msgid "Make sure your uploaded file is at least %s bytes big."
+msgstr "Файлът, който сте качили трябва да бъде поне %s байта."
+
+#: core/validators.py:439
+#, python-format
+msgid "Make sure your uploaded file is at most %s bytes big."
+msgstr "Размерът на файла, който сте качили не трябва да надхвърля %s байта. "
+
+#: core/validators.py:456
+msgid "The format for this field is wrong."
+msgstr "Форматът на това поле е грешен."
+
+#: core/validators.py:471
+msgid "This field is invalid."
+msgstr "Това поле не е валидно"
+
+#: core/validators.py:507
+#, python-format
+msgid "Could not retrieve anything from %s."
+msgstr "Не получихме нищо от %s."
+
+#: core/validators.py:510
+#, python-format
+msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
+msgstr "URL %(url)s върна невалиден Content-Type хедър '%(contenttype)s'."
+
+#: core/validators.py:543
+#, python-format
+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:547
+#, 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:552
+#, python-format
+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:557
+#, python-format
+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:561
+#, 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:566
+#, python-format
+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\".)"
+
diff --git a/django/conf/locale/bg/LC_MESSAGES/djangojs.mo b/django/conf/locale/bg/LC_MESSAGES/djangojs.mo
new file mode 100644
index 0000000000..e912789236
--- /dev/null
+++ b/django/conf/locale/bg/LC_MESSAGES/djangojs.mo
Binary files differ
diff --git a/django/conf/locale/bg/LC_MESSAGES/djangojs.po b/django/conf/locale/bg/LC_MESSAGES/djangojs.po
new file mode 100644
index 0000000000..2caffdca53
--- /dev/null
+++ b/django/conf/locale/bg/LC_MESSAGES/djangojs.po
@@ -0,0 +1,106 @@
+# translation of djangojs.po to Bulgarian
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: djangojs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-12-09 11:51+0100\n"
+"PO-Revision-Date: 2007-05-12 17:51+0300\n"
+"Last-Translator: Jordan Dimov <s3x3y1@gmail.com>\n"
+"Language-Team: Bulgarian\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 "Налични %s"
+
+#: contrib/admin/media/js/SelectFilter2.js:41
+msgid "Choose all"
+msgstr "Избери всички"
+
+#: contrib/admin/media/js/SelectFilter2.js:46
+msgid "Add"
+msgstr "Добави"
+
+#: contrib/admin/media/js/SelectFilter2.js:48
+msgid "Remove"
+msgstr "Премахни"
+
+#: contrib/admin/media/js/SelectFilter2.js:53
+#, perl-format
+msgid "Chosen %s"
+msgstr "Избрахме %s"
+
+#: contrib/admin/media/js/SelectFilter2.js:54
+msgid "Select your choice(s) and click "
+msgstr "Направете своя избор и щракнете "
+
+#: contrib/admin/media/js/SelectFilter2.js:59
+msgid "Clear all"
+msgstr "Изчисти всички"
+
+#: 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 "Януари Февруари Март Април Май Юни Юли Август Септември Октомври Ноември Декември"
+
+#: contrib/admin/media/js/dateparse.js:27
+msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
+msgstr "Неделя Понеделник Вторник Сряда Четвъртък Петък Събота"
+
+#: contrib/admin/media/js/calendar.js:25
+msgid "S M T W T F S"
+msgstr "Н П В С Ч П С"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
+msgid "Now"
+msgstr "Сега"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
+msgid "Clock"
+msgstr "Часовник"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
+msgid "Choose a time"
+msgstr "Избери време"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
+msgid "Midnight"
+msgstr "Полунощ"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
+msgid "6 a.m."
+msgstr "6 a.m."
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
+msgid "Noon"
+msgstr "По обяд"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
+msgid "Cancel"
+msgstr "Отказ"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
+msgid "Today"
+msgstr "Днес"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
+msgid "Calendar"
+msgstr "Календар"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
+msgid "Yesterday"
+msgstr "Вчера"
+
+#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
+msgid "Tomorrow"
+msgstr "Утре"
+
diff --git a/django/contrib/localflavor/is_/forms.py b/django/contrib/localflavor/is_/forms.py
index d052acf579..41727d8fa3 100644
--- a/django/contrib/localflavor/is_/forms.py
+++ b/django/contrib/localflavor/is_/forms.py
@@ -41,7 +41,7 @@ class ISIdNumberField(RegexField):
method is modulo 11.
"""
check = [3, 2, 7, 6, 5, 4, 3, 2, 1, 0]
- return sum(int(value[i]) * check[i] for i in range(10)) % 11 == 0
+ return sum([int(value[i]) * check[i] for i in range(10)]) % 11 == 0
def _format(self, value):
"""
diff --git a/django/core/management.py b/django/core/management.py
index 91de11f3b3..79e57ff0c8 100644
--- a/django/core/management.py
+++ b/django/core/management.py
@@ -1463,20 +1463,24 @@ def load_data(fixture_labels, verbosity=1):
if verbosity > 1:
print "No %s fixture '%s' in %s." % \
(format, fixture_name, humanize(fixture_dir))
- if count[0] == 0:
- if verbosity > 0:
- print "No fixtures found."
- else:
- if verbosity > 0:
- print "Installed %d object(s) from %d fixture(s)" % tuple(count)
+
+ if count[0] > 0:
sequence_sql = backend.get_sql_sequence_reset(style, models)
if sequence_sql:
if verbosity > 1:
print "Resetting sequences"
for line in sequence_sql:
cursor.execute(line)
+
transaction.commit()
transaction.leave_transaction_management()
+
+ if count[0] == 0:
+ if verbosity > 0:
+ print "No fixtures found."
+ else:
+ if verbosity > 0:
+ print "Installed %d object(s) from %d fixture(s)" % tuple(count)
load_data.help_doc = 'Installs the named fixture(s) in the database'
load_data.args = "[--verbosity] fixture, fixture, ..."
diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py
index 29ce6bf9bd..66dbbff335 100644
--- a/django/core/serializers/python.py
+++ b/django/core/serializers/python.py
@@ -37,7 +37,7 @@ class Serializer(base.Serializer):
def handle_fk_field(self, obj, field):
related = getattr(obj, field.name)
if related is not None:
- related = related._get_pk_val()
+ related = getattr(related, field.rel.field_name)
self._current[field.name] = related
def handle_m2m_field(self, obj, field):
@@ -80,7 +80,10 @@ def Deserializer(object_list, **options):
# Handle FK fields
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
- data[field.attname] = field.rel.to._meta.pk.to_python(field_value)
+ if field_value:
+ data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
+ else:
+ data[field.attname] = None
# Handle all other fields
else:
diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py
index 3a0fdb5395..633001f5f0 100644
--- a/django/core/serializers/xml_serializer.py
+++ b/django/core/serializers/xml_serializer.py
@@ -82,7 +82,7 @@ class Serializer(base.Serializer):
self._start_relational_field(field)
related = getattr(obj, field.name)
if related is not None:
- self.xml.characters(str(related._get_pk_val()))
+ self.xml.characters(str(getattr(related, field.rel.field_name)))
else:
self.xml.addQuickElement("None")
self.xml.endElement("field")
@@ -181,7 +181,7 @@ class Deserializer(base.Deserializer):
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
return None
else:
- return field.rel.to._meta.pk.to_python(
+ return field.rel.to._meta.get_field(field.rel.field_name).to_python(
getInnerText(node).strip().encode(self.encoding))
def _handle_m2m_field_node(self, node, field):
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py
index 66479eb557..96420a7cf0 100644
--- a/django/db/backends/postgresql/base.py
+++ b/django/db/backends/postgresql/base.py
@@ -242,7 +242,7 @@ def get_sql_sequence_reset(style, model_list):
if isinstance(f, models.AutoField):
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
(style.SQL_KEYWORD('SELECT'),
- style.SQL_FIELD('%s_%s_seq' % (model._meta.db_table, f.column)),
+ style.SQL_FIELD(quote_name('%s_%s_seq' % (model._meta.db_table, f.column))),
style.SQL_KEYWORD('SELECT'),
style.SQL_FIELD(quote_name(f.column)),
style.SQL_KEYWORD('FROM'),
@@ -251,7 +251,7 @@ def get_sql_sequence_reset(style, model_list):
for f in model._meta.many_to_many:
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
(style.SQL_KEYWORD('SELECT'),
- style.SQL_FIELD('%s_id_seq' % f.m2m_db_table()),
+ style.SQL_FIELD(quote_name('%s_id_seq' % f.m2m_db_table())),
style.SQL_KEYWORD('SELECT'),
style.SQL_FIELD(quote_name('id')),
style.SQL_KEYWORD('FROM'),
diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py
index c85504bfaa..e27f4f61e0 100644
--- a/django/db/backends/postgresql_psycopg2/base.py
+++ b/django/db/backends/postgresql_psycopg2/base.py
@@ -199,7 +199,7 @@ def get_sql_sequence_reset(style, model_list):
if isinstance(f, models.AutoField):
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
(style.SQL_KEYWORD('SELECT'),
- style.SQL_FIELD('%s_%s_seq' % (model._meta.db_table, f.column)),
+ style.SQL_FIELD(quote_name('%s_%s_seq' % (model._meta.db_table, f.column))),
style.SQL_KEYWORD('SELECT'),
style.SQL_FIELD(quote_name(f.column)),
style.SQL_KEYWORD('FROM'),
@@ -208,7 +208,7 @@ def get_sql_sequence_reset(style, model_list):
for f in model._meta.many_to_many:
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
(style.SQL_KEYWORD('SELECT'),
- style.SQL_FIELD('%s_id_seq' % f.m2m_db_table()),
+ style.SQL_FIELD(quote_name('%s_id_seq' % f.m2m_db_table())),
style.SQL_KEYWORD('SELECT'),
style.SQL_FIELD(quote_name('id')),
style.SQL_KEYWORD('FROM'),
diff --git a/django/newforms/forms.py b/django/newforms/forms.py
index 9fafd20787..f624e005e9 100644
--- a/django/newforms/forms.py
+++ b/django/newforms/forms.py
@@ -184,8 +184,8 @@ class BaseForm(StrAndUnicode):
try:
value = field.clean(value)
self.clean_data[name] = value
- if hasattr(self, 'clean_%s' % name):
- value = getattr(self, 'clean_%s' % name)()
+ if hasattr(self, 'do_clean_%s' % name):
+ value = getattr(self, 'do_clean_%s' % name)()
self.clean_data[name] = value
except ValidationError, e:
errors[name] = e.messages
@@ -255,6 +255,8 @@ class BoundField(StrAndUnicode):
attrs['id'] = auto_id
if not self.form.is_bound:
data = self.form.initial.get(self.name, self.field.initial)
+ if callable(data):
+ data = data()
else:
data = self.data
return widget.render(self.html_name, data, attrs=attrs)
diff --git a/django/newforms/models.py b/django/newforms/models.py
index a60002b705..ea99ca9ea0 100644
--- a/django/newforms/models.py
+++ b/django/newforms/models.py
@@ -12,17 +12,7 @@ from widgets import Select, SelectMultiple, MultipleHiddenInput
__all__ = ('save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields',
'ModelChoiceField', 'ModelMultipleChoiceField')
-def model_save(self, commit=True):
- """
- Creates and returns model instance according to self.clean_data.
-
- This method is created for any form_for_model Form.
- """
- if self.errors:
- raise ValueError("The %s could not be created because the data didn't validate." % self._model._meta.object_name)
- return save_instance(self, self._model(), commit)
-
-def save_instance(form, instance, commit=True):
+def save_instance(form, instance, fields=None, fail_message='saved', commit=True):
"""
Saves bound Form ``form``'s clean_data into model instance ``instance``.
@@ -33,15 +23,19 @@ def save_instance(form, instance, commit=True):
from django.db import models
opts = instance.__class__._meta
if form.errors:
- raise ValueError("The %s could not be changed because the data didn't validate." % opts.object_name)
+ raise ValueError("The %s could not be %s because the data didn't validate." % (opts.object_name, fail_message))
clean_data = form.clean_data
for f in opts.fields:
if not f.editable or isinstance(f, models.AutoField) or not f.name in clean_data:
continue
+ if fields and f.name not in fields:
+ continue
setattr(instance, f.name, clean_data[f.name])
if commit:
instance.save()
for f in opts.many_to_many:
+ if fields and f.name not in fields:
+ continue
if f.name in clean_data:
setattr(instance, f.attname, clean_data[f.name])
# GOTCHA: If many-to-many data is given and commit=False, the many-to-many
@@ -50,13 +44,19 @@ def save_instance(form, instance, commit=True):
# exception in that case.
return instance
-def make_instance_save(instance):
- "Returns the save() method for a form_for_instance Form."
+def make_model_save(model, fields, fail_message):
+ "Returns the save() method for a Form."
def save(self, commit=True):
- return save_instance(self, instance, commit)
+ return save_instance(self, model(), fields, fail_message, commit)
+ return save
+
+def make_instance_save(instance, fields, fail_message):
+ "Returns the save() method for a Form."
+ def save(self, commit=True):
+ return save_instance(self, instance, fields, fail_message, commit)
return save
-def form_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formfield()):
+def form_for_model(model, form=BaseForm, fields=None, formfield_callback=lambda f: f.formfield()):
"""
Returns a Form class for the given Django model class.
@@ -71,13 +71,16 @@ def form_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formfiel
for f in opts.fields + opts.many_to_many:
if not f.editable:
continue
+ if fields and not f.name in fields:
+ continue
formfield = formfield_callback(f)
if formfield:
field_list.append((f.name, formfield))
- fields = SortedDictFromList(field_list)
- return type(opts.object_name + 'Form', (form,), {'base_fields': fields, '_model': model, 'save': model_save})
+ base_fields = SortedDictFromList(field_list)
+ return type(opts.object_name + 'Form', (form,),
+ {'base_fields': base_fields, '_model': model, 'save': make_model_save(model, fields, 'created')})
-def form_for_instance(instance, form=BaseForm, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
+def form_for_instance(instance, form=BaseForm, fields=None, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
"""
Returns a Form class for the given Django model instance.
@@ -94,13 +97,15 @@ def form_for_instance(instance, form=BaseForm, formfield_callback=lambda f, **kw
for f in opts.fields + opts.many_to_many:
if not f.editable:
continue
+ if fields and not f.name in fields:
+ continue
current_value = f.value_from_object(instance)
formfield = formfield_callback(f, initial=current_value)
if formfield:
field_list.append((f.name, formfield))
- fields = SortedDictFromList(field_list)
+ base_fields = SortedDictFromList(field_list)
return type(opts.object_name + 'InstanceForm', (form,),
- {'base_fields': fields, '_model': model, 'save': make_instance_save(instance)})
+ {'base_fields': base_fields, '_model': model, 'save': make_instance_save(instance, fields, 'changed')})
def form_for_fields(field_list):
"Returns a Form class for the given list of Django database field instances."
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 788e215ca1..dd1f73befd 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -45,16 +45,16 @@ class TestCase(unittest.TestCase):
if hasattr(self, 'fixtures'):
management.load_data(self.fixtures, verbosity=0)
mail.outbox = []
-
- def run(self, result=None):
- """Wrapper around default run method to perform common Django test set up.
- This means that user-defined Test Cases aren't required to include a call
- to super().setUp().
-
+
+ def __call__(self, result=None):
+ """
+ Wrapper around default __call__ method to perform common Django test
+ set up. This means that user-defined Test Cases aren't required to
+ include a call to super().setUp().
"""
self.client = Client()
self._pre_setup()
- super(TestCase, self).run(result)
+ super(TestCase, self).__call__(result)
def assertRedirects(self, response, expected_path, status_code=302, target_status_code=200):
"""Assert that a response redirected to a specific URL, and that the
@@ -62,7 +62,7 @@ class TestCase(unittest.TestCase):
"""
self.assertEqual(response.status_code, status_code,
- "Response didn't redirect: Reponse code was %d (expected %d)" %
+ "Response didn't redirect as expected: Reponse code was %d (expected %d)" %
(response.status_code, status_code))
scheme, netloc, path, params, query, fragment = urlparse(response['Location'])
self.assertEqual(path, expected_path,
@@ -70,7 +70,7 @@ class TestCase(unittest.TestCase):
redirect_response = self.client.get(path)
self.assertEqual(redirect_response.status_code, target_status_code,
"Couldn't retrieve redirection page '%s': response code was %d (expected %d)" %
- (path, response.status_code, status_code))
+ (path, redirect_response.status_code, target_status_code))
def assertContains(self, response, text, count=1, status_code=200):
"""Assert that a response indicates that a page was retreived successfully,
@@ -108,7 +108,7 @@ class TestCase(unittest.TestCase):
for err in errors:
if field:
if field in context[form].errors:
- self.assertTrue(err in context[form].errors[field],
+ self.failUnless(err in context[form].errors[field],
"The field '%s' on form '%s' in context %d does not contain the error '%s' (actual errors: %s)" %
(field, form, i, err, list(context[form].errors[field])))
elif field in context[form].fields:
@@ -117,7 +117,7 @@ class TestCase(unittest.TestCase):
else:
self.fail("The form '%s' in context %d does not contain the field '%s'" % (form, i, field))
else:
- self.assertTrue(err in context[form].non_field_errors(),
+ self.failUnless(err in context[form].non_field_errors(),
"The form '%s' in context %d does not contain the non-field error '%s' (actual errors: %s)" %
(form, i, err, list(context[form].non_field_errors())))
if not found_form:
@@ -127,7 +127,7 @@ class TestCase(unittest.TestCase):
"Assert that the template with the provided name was used in rendering the response"
if isinstance(response.template, list):
template_names = [t.name for t in response.template]
- self.assertTrue(template_name in template_names,
+ self.failUnless(template_name in template_names,
"Template '%s' was not one of the templates used to render the response. Templates used: %s" %
(template_name, template_names))
elif response.template:
@@ -140,9 +140,9 @@ class TestCase(unittest.TestCase):
def assertTemplateNotUsed(self, response, template_name):
"Assert that the template with the provided name was NOT used in rendering the response"
if isinstance(response.template, list):
- self.assertFalse(template_name in [t.name for t in response.template],
+ self.failIf(template_name in [t.name for t in response.template],
"Template '%s' was used unexpectedly in rendering the response" % template_name)
elif response.template:
self.assertNotEqual(template_name, response.template.name,
"Template '%s' was used unexpectedly in rendering the response" % template_name)
- \ No newline at end of file
+
diff --git a/docs/databrowse.txt b/docs/databrowse.txt
index e9691cc879..9c03e7e4ea 100644
--- a/docs/databrowse.txt
+++ b/docs/databrowse.txt
@@ -44,7 +44,11 @@ How to use Databrowse
It doesn't matter where you put this, as long as it gets executed at
some point. A good place for it is in your URLconf file (``urls.py``).
- 3. Add the following line to your URLconf::
+ 3. Change your URLconf to import the ``databrowse`` module::
+
+ from django.contrib import databrowse
+
+ ...and add the following line to your URLconf::
(r'^databrowse/(.*)', databrowse.site.root),
diff --git a/docs/i18n.txt b/docs/i18n.txt
index 1d7a0063b2..27abadacc9 100644
--- a/docs/i18n.txt
+++ b/docs/i18n.txt
@@ -236,7 +236,7 @@ To pluralize, specify both the singular and plural forms with the
``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and
``{% endblocktrans %}``. Example::
- {% blocktrans count list|count as counter %}
+ {% blocktrans count list|length as counter %}
There is only one {{ name }} object.
{% plural %}
There are {{ counter }} {{ name }} objects.
diff --git a/docs/newforms.txt b/docs/newforms.txt
index ddb850f54c..7c861ed405 100644
--- a/docs/newforms.txt
+++ b/docs/newforms.txt
@@ -9,28 +9,30 @@ framework. This document explains how to use this new library.
Migration plan
==============
-``django.newforms`` currently is only available in Django beginning
-with the 0.96 release. the Django development version -- i.e., it's
-not available in the Django 0.95 release. For the next Django release,
-our plan is to do the following:
+``django.newforms`` is new in Django's 0.96 release, but, as it won't be new
+forever, we plan to rename it to ``django.forms`` in the future. The current
+``django.forms`` package will be available as ``django.oldforms`` until Django
+1.0, when we plan to remove it for good.
- * As of revision [4208], we've copied the current ``django.forms`` to
- ``django.oldforms``. This allows you to upgrade your code *now* rather
- than waiting for the backwards-incompatible change and rushing to fix
- your code after the fact. Just change your import statements like this::
+That has direct repercussions on the forward compatibility of your code. Please
+read the following migration plan and code accordingly:
+
+ * The old forms framework (the current ``django.forms``) has been copied to
+ ``django.oldforms``. Thus, you can start upgrading your code *now*,
+ rather than waiting for the future backwards-incompatible change, by
+ changing your import statements like this::
from django import forms # old
from django import oldforms as forms # new
- * At an undecided future date, we will move the current ``django.newforms``
- to ``django.forms``. This will be a backwards-incompatible change, and
- anybody who is still using the old version of ``django.forms`` at that
- time will need to change their import statements, as described in the
- previous bullet.
+ * In the next Django release (0.97), we will move the current
+ ``django.newforms`` to ``django.forms``. This will be a
+ backwards-incompatible change, and anybody who is still using the old
+ version of ``django.forms`` at that time will need to change their import
+ statements, as described in the previous bullet.
* We will remove ``django.oldforms`` in the release *after* the next Django
- release -- the release that comes after the release in which we're
- creating the new ``django.forms``.
+ release -- either 0.98 or 1.0, whichever comes first.
With this in mind, we recommend you use the following import statement when
using ``django.newforms``::
@@ -184,7 +186,7 @@ e-mail address::
>>> f.is_valid()
False
-Access the ``Form`` attribute ``errors`` to get a dictionary of error messages::
+Access the ``errors`` attribute to get a dictionary of error messages::
>>> f.errors
{'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']}
@@ -197,6 +199,10 @@ You can access ``errors`` without having to call ``is_valid()`` first. The
form's data will be validated the first time either you call ``is_valid()`` or
access ``errors``.
+The validation routines will only get called once, regardless of how many times
+you access ``errors`` or call ``is_valid()``. This means that if validation has
+side effects, those side effects will only be triggered once.
+
Behavior of unbound forms
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -274,6 +280,27 @@ but ``clean_data`` contains only the form's fields::
>>> f.clean_data # Doesn't contain extra_field_1, etc.
{'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
+``clean_data`` will include a key and value for *all* fields defined in the
+``Form``, even if the data didn't include a value for fields that are not
+required. In this example, the data dictionary doesn't include a value for the
+``nick_name`` field, but ``clean_data`` includes it, with an empty value::
+
+ >>> class OptionalPersonForm(Form):
+ ... first_name = CharField()
+ ... last_name = CharField()
+ ... nick_name = CharField(required=False)
+ >>> data = {'first_name': u'John', 'last_name': u'Lennon'}
+ >>> f = OptionalPersonForm(data)
+ >>> f.is_valid()
+ True
+ >>> f.clean_data
+ {'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
+
+In this above example, the ``clean_data`` value for ``nick_name`` is set to an
+empty string, because ``nick_name`` is ``CharField``, and ``CharField``\s treat
+empty values as an empty string. Each field type knows what its "blank" value
+is -- e.g., for ``DateField``, it's ``None`` instead of the empty string.
+
Behavior of unbound forms
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -454,7 +481,7 @@ field::
If ``auto_id`` is set to a string containing the format character ``'%s'``,
then the form output will include ``<label>`` tags, and will generate ``id``
attributes based on the format string. For example, for a format string
-``'field_%s'``, a field named ``subject`` will get the ``id``
+``'field_%s'``, a field named ``subject`` will get the ``id`` value
``'field_subject'``. Continuing our example::
>>> f = ContactForm(auto_id='id_for_%s')
@@ -493,8 +520,9 @@ How errors are displayed
If you render a bound ``Form`` object, the act of rendering will automatically
run the form's validation if it hasn't already happened, and the HTML output
-will include the validation errors as a ``<ul>`` near the field. The particular
-positioning of the error messages depends on the output method you're using::
+will include the validation errors as a ``<ul class="errorlist">`` near the
+field. The particular positioning of the error messages depends on the output
+method you're using::
>>> data = {'subject': '',
... 'message': 'Hi there',
@@ -556,7 +584,8 @@ The field-specific output honors the form object's ``auto_id`` setting::
<input type="text" name="message" id="id_message" />
For a field's list of errors, access the field's ``errors`` attribute. This
-is a list-like object that is displayed as an HTML ``<ul>`` when printed::
+is a list-like object that is displayed as an HTML ``<ul class="errorlist">``
+when printed::
>>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
>>> f = ContactForm(data, auto_id=False)
@@ -646,7 +675,7 @@ Core field arguments
Each ``Field`` class constructor takes at least these arguments. Some
``Field`` classes take additional, field-specific arguments, but the following
-should *always* be available:
+should *always* be accepted:
``required``
~~~~~~~~~~~~
@@ -704,7 +733,7 @@ field.)
The ``label`` argument lets you specify the "human-friendly" label for this
field. This is used when the ``Field`` is displayed in a ``Form``.
-As explained in _`Outputting forms as HTML` above, the default label for a
+As explained in "Outputting forms as HTML" above, the default label for a
``Field`` is generated from the field name by converting all underscores to
spaces and upper-casing the first letter. Specify ``label`` if that default
behavior doesn't result in an adequate label.
@@ -779,14 +808,15 @@ validation if a particular field's value is not given. ``initial`` values are
~~~~~~~~~~
The ``widget`` argument lets you specify a ``Widget`` class to use when
-rendering this ``Field``. See _`Widgets` below for more information.
+rendering this ``Field``. See "Widgets" below for more information.
``help_text``
~~~~~~~~~~~~~
The ``help_text`` argument lets you specify descriptive text for this
``Field``. If you provide ``help_text``, it will be displayed next to the
-``Field`` when the ``Field`` is rendered in a ``Form``.
+``Field`` when the ``Field`` is rendered by one of the convenience ``Form``
+methods (e.g., ``as_ul()``).
Here's a full example ``Form`` that implements ``help_text`` for two of its
fields. We've specified ``auto_id=False`` to simplify the output::
@@ -860,6 +890,212 @@ level and at the form instance level, and the latter gets precedence::
<tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+Built-in ``Field`` classes
+--------------------------
+
+Naturally, the ``newforms`` library comes with a set of ``Field`` classes that
+represent common validation needs. This section documents each built-in field.
+
+For each field, we describe the default widget used if you don't specify
+``widget``. We also specify the value returned when you provide an empty value
+(see the section on ``required`` above to understand what that means).
+
+``BooleanField``
+~~~~~~~~~~~~~~~~
+
+ * Default widget: ``CheckboxInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``True`` or ``False`` value.
+ * Validates nothing (i.e., it never raises a ``ValidationError``).
+
+``CharField``
+~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates nothing, unless ``max_length`` or ``min_length`` is provided.
+
+Has two optional arguments for validation, ``max_length`` and ``min_length``.
+If provided, these arguments ensure that the string is at most or at least the
+given length.
+
+``ChoiceField``
+~~~~~~~~~~~~~~~
+
+ * Default widget: ``Select``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates that the given value exists in the list of choices.
+
+Takes one extra argument, ``choices``, which is an iterable (e.g., a list or
+tuple) of 2-tuples to use as choices for this field.
+
+``DateField``
+~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``datetime.date`` object.
+ * Validates that the given value is either a ``datetime.date``,
+ ``datetime.datetime`` or string formatted in a particular date format.
+
+Takes one optional argument, ``input_formats``, which is a list of formats used
+to attempt to convert a string to a valid ``datetime.date`` object.
+
+If no ``input_formats`` argument is provided, the default input formats are::
+
+ '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
+ '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
+ '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006'
+ '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006'
+ '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006'
+
+``DateTimeField``
+~~~~~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``datetime.datetime`` object.
+ * Validates that the given value is either a ``datetime.datetime``,
+ ``datetime.date`` or string formatted in a particular datetime format.
+
+Takes one optional argument, ``input_formats``, which is a list of formats used
+to attempt to convert a string to a valid ``datetime.datetime`` object.
+
+If no ``input_formats`` argument is provided, the default input formats are::
+
+ '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
+ '%Y-%m-%d %H:%M', # '2006-10-25 14:30'
+ '%Y-%m-%d', # '2006-10-25'
+ '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59'
+ '%m/%d/%Y %H:%M', # '10/25/2006 14:30'
+ '%m/%d/%Y', # '10/25/2006'
+ '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59'
+ '%m/%d/%y %H:%M', # '10/25/06 14:30'
+ '%m/%d/%y', # '10/25/06'
+
+``EmailField``
+~~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates that the given value is a valid e-mail address, using a
+ moderately complex regular expression.
+
+Has two optional arguments for validation, ``max_length`` and ``min_length``.
+If provided, these arguments ensure that the string is at most or at least the
+given length.
+
+``IntegerField``
+~~~~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python integer or long integer.
+ * Validates that the given value is an integer. Leading and trailing
+ whitespace is allowed, as in Python's ``int()`` function.
+
+``MultipleChoiceField``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+ * Default widget: ``SelectMultiple``
+ * Empty value: ``[]`` (an empty list)
+ * Normalizes to: A list of Unicode objects.
+ * Validates that every value in the given list of values exists in the list
+ of choices.
+
+Takes one extra argument, ``choices``, which is an iterable (e.g., a list or
+tuple) of 2-tuples to use as choices for this field.
+
+``NullBooleanField``
+~~~~~~~~~~~~~~~~~~~~
+
+ * Default widget: ``NullBooleanSelect``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``True``, ``False`` or ``None`` value.
+ * Validates nothing (i.e., it never raises a ``ValidationError``).
+
+``RegexField``
+~~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates that the given value matches against a certain regular
+ expression.
+
+Takes one required argument, ``regex``, which is a regular expression specified
+either as a string or a compiled regular expression object.
+
+Also takes the following optional arguments:
+
+ ====================== =====================================================
+ Argument Description
+ ====================== =====================================================
+ ``max_length`` Ensures the string has at most this many characters.
+ ``min_length`` Ensures the string has at least this many characters.
+ ``error_message`` Error message to return for failed validation. If no
+ message is provided, a generic error message will be
+ used.
+ ====================== =====================================================
+
+``TimeField``
+~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``datetime.time`` object.
+ * Validates that the given value is either a ``datetime.time`` or string
+ formatted in a particular time format.
+
+Takes one optional argument, ``input_formats``, which is a list of formats used
+to attempt to convert a string to a valid ``datetime.time`` object.
+
+If no ``input_formats`` argument is provided, the default input formats are::
+
+ '%H:%M:%S', # '14:30:59'
+ '%H:%M', # '14:30'
+
+``URLField``
+~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates that the given value is a valid URL.
+
+Takes the following optional arguments:
+
+ ======================== =====================================================
+ Argument Description
+ ======================== =====================================================
+ ``max_length`` Ensures the string has at most this many characters.
+ ``min_length`` Ensures the string has at least this many characters.
+ ``verify_exists`` If ``True``, the validator will attempt to load the
+ given URL, raising ``ValidationError`` if the page
+ gives a 404. Defaults to ``False``.
+ ``validator_user_agent`` String used as the user-agent used when checking for
+ a URL's existence. Defaults to the value of the
+ ``URL_VALIDATOR_USER_AGENT`` setting.
+ ======================== =====================================================
+
+Slightly complex built-in ``Field`` classes
+-------------------------------------------
+
+The following are not yet documented here. See the unit tests, linked-to from
+the bottom of this document, for examples of their use.
+
+``ComboField``
+~~~~~~~~~~~~~~
+
+``MultiValueField``
+~~~~~~~~~~~~~~~~~~~
+
+``SplitDateTimeField``
+~~~~~~~~~~~~~~~~~~~~~~
+
Creating custom fields
----------------------
@@ -870,6 +1106,308 @@ custom ``Field`` classes. To do this, just create a subclass of
mentioned above (``required``, ``label``, ``initial``, ``widget``,
``help_text``).
+Generating forms for models
+===========================
+
+If you're building a database-driven app, chances are you'll have forms that
+map closely to Django models. For instance, you might have a ``BlogComment``
+model, and you want to create a form that lets people submit comments. In this
+case, it would be redundant to define the field types in your form, because
+you've already defined the fields in your model.
+
+For this reason, Django provides a few helper functions that let you create a
+``Form`` class from a Django model.
+
+``form_for_model()``
+--------------------
+
+The method ``django.newforms.form_for_model()`` creates a form based on the
+definition of a specific model. Pass it the model class, and it will return a
+``Form`` class that contains a form field for each model field.
+
+For example::
+
+ >>> from django.newforms import form_for_model
+
+ # Create the form class.
+ >>> ArticleForm = form_for_model(Article)
+
+ # Create an empty form instance.
+ >>> f = ArticleForm()
+
+It bears repeating that ``form_for_model()`` takes the model *class*, not a
+model instance, and it returns a ``Form`` *class*, not a ``Form`` instance.
+
+Field types
+~~~~~~~~~~~
+
+The generated ``Form`` class will have a form field for every model field. Each
+model field has a corresponding default form field. For example, a
+``CharField`` on a model is represented as a ``CharField`` on a form. A
+model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is
+the full list of conversions:
+
+ =============================== ========================================
+ Model field Form field
+ =============================== ========================================
+ ``AutoField`` Not represented in the form
+ ``BooleanField`` ``BooleanField``
+ ``CharField`` ``CharField`` with ``max_length`` set to
+ the model field's ``maxlength``
+ ``CommaSeparatedIntegerField`` ``CharField``
+ ``DateField`` ``DateField``
+ ``DateTimeField`` ``DateTimeField``
+ ``EmailField`` ``EmailField``
+ ``FileField`` ``CharField``
+ ``FilePathField`` ``CharField``
+ ``FloatField`` ``CharField``
+ ``ForeignKey`` ``ModelChoiceField`` (see below)
+ ``ImageField`` ``CharField``
+ ``IntegerField`` ``IntegerField``
+ ``IPAddressField`` ``CharField``
+ ``ManyToManyField`` ``ModelMultipleChoiceField`` (see
+ below)
+ ``NullBooleanField`` ``CharField``
+ ``PhoneNumberField`` ``USPhoneNumberField``
+ (from ``django.contrib.localflavor.us``)
+ ``PositiveIntegerField`` ``IntegerField``
+ ``PositiveSmallIntegerField`` ``IntegerField``
+ ``SlugField`` ``CharField``
+ ``SmallIntegerField`` ``IntegerField``
+ ``TextField`` ``CharField`` with ``widget=Textarea``
+ ``TimeField`` ``TimeField``
+ ``URLField`` ``URLField`` with ``verify_exists`` set
+ to the model field's ``verify_exists``
+ ``USStateField`` ``CharField`` with
+ ``widget=USStateSelect``
+ (``USStateSelect`` is from
+ ``django.contrib.localflavor.us``)
+ ``XMLField`` ``CharField`` with ``widget=Textarea``
+ =============================== ========================================
+
+As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
+types are special cases:
+
+ * ``ForeignKey`` is represented by ``django.newforms.ModelChoiceField``,
+ which is a ``ChoiceField`` whose choices are a model ``QuerySet``.
+
+ * ``ManyToManyField`` is represented by
+ ``django.newforms.ModelMultipleChoiceField``, which is a
+ ``MultipleChoiceField`` whose choices are a model ``QuerySet``.
+
+In addition, each generated form field has attributes set as follows:
+
+ * If the model field has ``blank=True``, then ``required`` is set to
+ ``False`` on the form field. Otherwise, ``required=True``.
+
+ * The form field's ``label`` is set to the ``verbose_name`` of the model
+ field, with the first character capitalized.
+
+ * The form field's ``help_text`` is set to the ``help_text`` of the model
+ field.
+
+ * If the model field has ``choices`` set, then the form field's ``widget``
+ will be set to ``Select``, with choices coming from the model field's
+ ``choices``.
+
+Finally, note that you can override the form field used for a given model
+field. See "Overriding the default field types" below.
+
+A full example
+~~~~~~~~~~~~~~
+
+Consider this set of models::
+
+ from django.db import models
+
+ TITLE_CHOICES = (
+ ('MR', 'Mr.'),
+ ('MRS', 'Mrs.'),
+ ('MS', 'Ms.'),
+ )
+
+ class Author(models.Model):
+ name = models.CharField(maxlength=100)
+ title = models.CharField(maxlength=3, choices=TITLE_CHOICES)
+ birth_date = models.DateField(blank=True, null=True)
+
+ def __str__(self):
+ return self.name
+
+ class Book(models.Model):
+ name = models.CharField(maxlength=100)
+ authors = models.ManyToManyField(Author)
+
+With these models, a call to ``form_for_model(Author)`` would return a ``Form``
+class equivalent to this::
+
+ class AuthorForm(forms.Form):
+ name = forms.CharField(max_length=100)
+ title = forms.CharField(max_length=3,
+ widget=forms.Select(choices=TITLE_CHOICES))
+ birth_date = forms.DateField(required=False)
+
+A call to ``form_for_model(Book)`` would return a ``Form`` class equivalent to
+this::
+
+ class BookForm(forms.Form):
+ name = forms.CharField(max_length=100)
+ authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
+
+The ``save()`` method
+~~~~~~~~~~~~~~~~~~~~~
+
+Every form produced by ``form_for_model()`` also has a ``save()`` method. This
+method creates and saves a database object from the data bound to the form. For
+example::
+
+ # Create a form instance from POST data.
+ >>> f = ArticleForm(request.POST)
+
+ # Save a new Article object from the form's data.
+ >>> new_article = f.save()
+
+Note that ``save()`` will raise a ``ValueError`` if the data in the form
+doesn't validate -- i.e., ``if form.errors``.
+
+Using an alternate base class
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you want to add custom methods to the form generated by
+``form_for_model()``, write a class that extends ``django.newforms.BaseForm``
+and contains your custom methods. Then, use the ``form`` argument to
+``form_for_model()`` to tell it to use your custom form as its base class.
+For example::
+
+ # Create the new base class.
+ >>> class MyBase(BaseForm):
+ ... def my_method(self):
+ ... # Do whatever the method does
+
+ # Create the form class with a different base class.
+ >>> ArticleForm = form_for_model(Article, form=MyBase)
+
+ # Instantiate the form.
+ >>> f = ArticleForm()
+
+ # Use the base class method.
+ >>> f.my_method()
+
+Using a subset of fields on the form
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**New in Django development version**
+
+In some cases, you may not want all the model fields to appear on the generated
+form. There are two ways of telling ``form_for_model()`` to use only a subset
+of the model fields:
+
+ 1. Set ``editable=False`` on the model field. As a result, *any* form
+ created from the model via ``form_for_model()`` will not include that
+ field.
+
+ 2. Use the ``fields`` argument to ``form_for_model()``. This argument, if
+ given, should be a list of field names to include in the form.
+
+ For example, if you want a form for the ``Author`` model (defined above)
+ that includes only the ``name`` and ``title`` fields, you would specify
+ ``fields`` like this::
+
+ PartialArticleForm = form_for_model(Author, fields=('name', 'title'))
+
+.. note::
+
+ If you specify ``fields`` when creating a form with ``form_for_model()``,
+ make sure that the fields that are *not* specified can provide default
+ values, or are allowed to have a value of ``None``. If a field isn't
+ specified on a form, the object created from the form can't provide
+ a value for that attribute, which will prevent the new instance from
+ being saved.
+
+Overriding the default field types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The default field types, as described in the "Field types" table above, are
+sensible defaults; if you have a ``DateField`` in your model, chances are you'd
+want that to be represented as a ``DateField`` in your form. But
+``form_for_model()`` gives you the flexibility of changing the form field type
+for a given model field. You do this by specifying a **formfield callback**.
+
+A formfield callback is a function that, when provided with a model field,
+returns a form field instance. When constructing a form, ``form_for_model()``
+asks the formfield callback to provide form field types.
+
+By default, ``form_for_model()`` calls the ``formfield()`` method on the model
+field::
+
+ def default_callback(field, **kwargs):
+ return field.formfield(**kwargs)
+
+The ``kwargs`` are any keyword arguments that might be passed to the form
+field, such as ``required=True`` or ``label='Foo'``.
+
+For example, if you wanted to use ``MyDateFormField`` for any ``DateField``
+field on the model, you could define the callback::
+
+ >>> def my_callback(field, **kwargs):
+ ... if isinstance(field, models.DateField):
+ ... return MyDateFormField(**kwargs)
+ ... else:
+ ... return field.formfield(**kwargs)
+
+ >>> ArticleForm = form_for_model(formfield_callback=my_callback)
+
+Note that your callback needs to handle *all* possible model field types, not
+just the ones that you want to behave differently to the default. That's why
+this example has an ``else`` clause that implements the default behavior.
+
+Finding the model associated with a form
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The model class that was used to construct the form is available
+using the ``_model`` property of the generated form::
+
+ >>> ArticleForm = form_for_model(Article)
+ >>> ArticleForm._model
+ <class 'myapp.models.Article'>
+
+``form_for_instance()``
+-----------------------
+
+``form_for_instance()`` is like ``form_for_model()``, but it takes a model
+instance instead of a model class::
+
+ # Create an Author.
+ >>> a = Author(name='Joe Smith', title='MR', birth_date=None)
+ >>> a.save()
+
+ # Create a form for this particular Author.
+ >>> AuthorForm = form_for_instance(a)
+
+ # Instantiate the form.
+ >>> f = AuthorForm()
+
+When a form created by ``form_for_instance()`` is created, the initial
+data values for the form fields are drawn from the instance. However,
+this data is not bound to the form. You will need to bind data to the
+form before the form can be saved.
+
+When you call ``save()`` on a form created by ``form_for_instance()``,
+the database instance will be updated. As in ``form_for_model()``, ``save()``
+will raise ``ValueError`` if the data doesn't validate.
+
+``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
+arguments that behave the same way as they do for ``form_for_model()``.
+
+When should you use ``form_for_model()`` and ``form_for_instance()``?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``form_for_model()`` and ``form_for_instance()`` functions are meant to be
+shortcuts for the common case. If you want to create a form whose fields map to
+more than one model, or a form that contains fields that *aren't* on a model,
+you shouldn't use these shortcuts. Creating a ``Form`` class the "long" way
+isn't that difficult, after all.
+
More coming soon
================
@@ -880,6 +1418,3 @@ what's possible.
If you're really itching to learn and use this library, please be patient.
We're working hard on finishing both the code and documentation.
-
-Widgets
-=======
diff --git a/docs/testing.txt b/docs/testing.txt
index b44b67c20a..92edf46e09 100644
--- a/docs/testing.txt
+++ b/docs/testing.txt
@@ -177,7 +177,7 @@ tools that can be used to establish tests and test conditions.
* `Test Client`_
* `TestCase`_
-* `Email services`_
+* `E-mail services`_
Test Client
-----------
@@ -459,9 +459,9 @@ Emptying the test outbox
**New in Django development version**
At the start of each test case, in addition to installing fixtures,
-Django clears the contents of the test email outbox.
+Django clears the contents of the test e-mail outbox.
-For more detail on email services during tests, see `Email services`_.
+For more detail on e-mail services during tests, see `E-mail services`_.
Assertions
~~~~~~~~~~
@@ -502,16 +502,17 @@ that can be useful in testing the behavior of web sites.
Assert that the template with the given name was used in rendering the
response.
-Email services
---------------
+E-mail services
+---------------
+
**New in Django development version**
-If your view makes use of the `Django email services`_, you don't really
-want email to be sent every time you run a test using that view.
+If your view makes use of the `Django e-mail services`_, you don't really
+want e-mail to be sent every time you run a test using that view.
When the Django test framework is initialized, it transparently replaces the
normal `SMTPConnection`_ class with a dummy implementation that redirects all
-email to a dummy outbox. This outbox, stored as ``django.core.mail.outbox``,
+e-mail to a dummy outbox. This outbox, stored as ``django.core.mail.outbox``,
is a simple list of all `EmailMessage`_ instances that have been sent.
For example, during test conditions, it would be possible to run the following
code::
@@ -541,7 +542,7 @@ to mail.outbox::
# Empty the test outbox
mail.outbox = []
-.. _`Django email services`: ../email/
+.. _`Django e-mail services`: ../email/
.. _`SMTPConnection`: ../email/#the-emailmessage-and-smtpconnection-classes
.. _`EmailMessage`: ../email/#the-emailmessage-and-smtpconnection-classes
.. _`previously`: #emptying-the-test-outbox
@@ -669,7 +670,7 @@ a number of utility methods in the ``django.test.utils`` module.
``teardown_test_environment()``
Performs any global post-test teardown, such as removing the instrumentation
- of the template rendering system and restoring normal email services.
+ of the template rendering system and restoring normal e-mail services.
``create_test_db(verbosity=1, autoclobber=False)``
Creates a new test database, and run ``syncdb`` against it.
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py
index a23529b566..e78f5f7bd7 100644
--- a/tests/modeltests/model_forms/models.py
+++ b/tests/modeltests/model_forms/models.py
@@ -179,6 +179,18 @@ fields with the 'choices' attribute are represented by a ChoiceField.
<option value="3">Third test</option>
</select><br /> Hold down "Control", or "Command" on a Mac, to select more than one.</td></tr>
+You can restrict a form to a subset of the complete list of fields
+by providing a 'fields' argument. If you try to save a
+model created with such a form, you need to ensure that the fields
+that are _not_ on the form have default values, or are allowed to have
+a value of None. If a field isn't specified on a form, the object created
+from the form can't provide a value for that field!
+>>> PartialArticleForm = form_for_model(Article, fields=('headline','pub_date'))
+>>> f = PartialArticleForm(auto_id=False)
+>>> print f
+<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
+<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
+
You can pass a custom Form class to form_for_model. Make sure it's a
subclass of BaseForm, not Form.
>>> class CustomForm(BaseForm):
@@ -224,7 +236,23 @@ current values are inserted as 'initial' data in each Field.
<option value="2">It&#39;s a test</option>
<option value="3">Third test</option>
</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li>
->>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 'writer': u'1', 'article': 'Hello.'})
+>>> f = TestArticleForm({'headline': u'Test headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'})
+>>> f.is_valid()
+True
+>>> test_art = f.save()
+>>> test_art.id
+1
+>>> test_art = Article.objects.get(id=1)
+>>> test_art.headline
+'Test headline'
+
+You can create a form over a subset of the available fields
+by specifying a 'fields' argument to form_for_instance.
+>>> PartialArticleForm = form_for_instance(art, fields=('headline','pub_date'))
+>>> f = PartialArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04'}, auto_id=False)
+>>> print f.as_ul()
+<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
+<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
>>> f.is_valid()
True
>>> new_art = f.save()
diff --git a/tests/regressiontests/forms/regressions.py b/tests/regressiontests/forms/regressions.py
index 5daabc03af..789ac81715 100644
--- a/tests/regressiontests/forms/regressions.py
+++ b/tests/regressiontests/forms/regressions.py
@@ -34,4 +34,18 @@ Unicode decoding problems...
>>> f = SomeForm()
>>> f.as_p()
u'<p><label for="id_somechoice_0">Somechoice:</label> <ul>\n<li><label><input type="radio" id="id_somechoice_0" value="0" name="somechoice" /> En tied\xe4</label></li>\n<li><label><input type="radio" id="id_somechoice_1" value="1" name="somechoice" /> Mies</label></li>\n<li><label><input type="radio" id="id_somechoice_2" value="2" name="somechoice" /> Nainen</label></li>\n</ul></p>'
+
+#######################
+# Miscellaneous Tests #
+#######################
+
+There once was a problem with Form fields called "data". Let's make sure that
+doesn't come back.
+>>> class DataForm(Form):
+... data = CharField(max_length=10)
+>>> f = DataForm({'data': 'xyzzy'})
+>>> f.is_valid()
+True
+>>> f.clean_data
+{'data': u'xyzzy'}
"""
diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
index 0d3a65277c..82be58dd0c 100644
--- a/tests/regressiontests/forms/tests.py
+++ b/tests/regressiontests/forms/tests.py
@@ -1916,6 +1916,34 @@ True
>>> p.clean_data
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
+clean_data will include a key and value for *all* fields defined in the Form,
+even if the Form's data didn't include a value for fields that are not
+required. In this example, the data dictionary doesn't include a value for the
+"nick_name" field, but clean_data includes it. For CharFields, it's set to the
+empty string.
+>>> class OptionalPersonForm(Form):
+... first_name = CharField()
+... last_name = CharField()
+... nick_name = CharField(required=False)
+>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
+>>> f = OptionalPersonForm(data)
+>>> f.is_valid()
+True
+>>> f.clean_data
+{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
+
+For DateFields, it's set to None.
+>>> class OptionalPersonForm(Form):
+... first_name = CharField()
+... last_name = CharField()
+... birth_date = DateField(required=False)
+>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
+>>> f = OptionalPersonForm(data)
+>>> f.is_valid()
+True
+>>> f.clean_data
+{'birth_date': None, 'first_name': u'John', 'last_name': u'Lennon'}
+
"auto_id" tells the Form to add an "id" attribute to each form element.
If it's a string that contains '%s', Django will use that as a format string
into which the field's name will be inserted. It will also put a <label> around
@@ -2275,7 +2303,7 @@ returns a list of input.
Validation errors are HTML-escaped when output as HTML.
>>> class EscapingForm(Form):
... special_name = CharField()
-... def clean_special_name(self):
+... def do_clean_special_name(self):
... raise ValidationError("Something's wrong with '%s'" % self.clean_data['special_name'])
>>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False)
@@ -2298,7 +2326,7 @@ including the current field (e.g., the field XXX if you're in clean_XXX()).
... username = CharField(max_length=10)
... password1 = CharField(widget=PasswordInput)
... password2 = CharField(widget=PasswordInput)
-... def clean_password2(self):
+... def do_clean_password2(self):
... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']:
... raise ValidationError(u'Please make sure your passwords match.')
... return self.clean_data['password2']
@@ -2752,6 +2780,64 @@ then the latter will get precedence.
<li>Username: <input type="text" name="username" value="babik" maxlength="10" /></li>
<li>Password: <input type="password" name="password" /></li>
+# Callable initial data ########################################################
+
+The previous technique dealt with raw values as initial data, but it's also
+possible to specify callable data.
+
+>>> class UserRegistration(Form):
+... username = CharField(max_length=10)
+... password = CharField(widget=PasswordInput)
+
+We need to define functions that get called later.
+>>> def initial_django():
+... return 'django'
+>>> def initial_stephane():
+... return 'stephane'
+
+Here, we're not submitting any data, so the initial value will be displayed.
+>>> p = UserRegistration(initial={'username': initial_django}, auto_id=False)
+>>> print p.as_ul()
+<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
+<li>Password: <input type="password" name="password" /></li>
+
+The 'initial' parameter is meaningless if you pass data.
+>>> p = UserRegistration({}, initial={'username': initial_django}, auto_id=False)
+>>> print p.as_ul()
+<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
+<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
+>>> p = UserRegistration({'username': u''}, initial={'username': initial_django}, auto_id=False)
+>>> print p.as_ul()
+<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
+<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
+>>> p = UserRegistration({'username': u'foo'}, initial={'username': initial_django}, auto_id=False)
+>>> print p.as_ul()
+<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
+<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
+
+A callable 'initial' value is *not* used as a fallback if data is not provided.
+In this example, we don't provide a value for 'username', and the form raises a
+validation error rather than using the initial value for 'username'.
+>>> p = UserRegistration({'password': 'secret'}, initial={'username': initial_django})
+>>> p.errors
+{'username': [u'This field is required.']}
+>>> p.is_valid()
+False
+
+If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(),
+then the latter will get precedence.
+>>> class UserRegistration(Form):
+... username = CharField(max_length=10, initial=initial_django)
+... password = CharField(widget=PasswordInput)
+>>> p = UserRegistration(auto_id=False)
+>>> print p.as_ul()
+<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
+<li>Password: <input type="password" name="password" /></li>
+>>> p = UserRegistration(initial={'username': initial_stephane}, auto_id=False)
+>>> print p.as_ul()
+<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
+<li>Password: <input type="password" name="password" /></li>
+
# Help text ###################################################################
You can specify descriptive text for a field by using the 'help_text' argument
@@ -3320,7 +3406,7 @@ True
</select>
# MultiWidget and MultiValueField #############################################
-# MultiWidgets are widgets composed of other widgets. They are usually
+# MultiWidgets are widgets composed of other widgets. They are usually
# combined with MultiValueFields - a field that is composed of other fields.
# MulitWidgets can themselved be composed of other MultiWidgets.
# SplitDateTimeWidget is one example of a MultiWidget.
@@ -3328,7 +3414,7 @@ True
>>> class ComplexMultiWidget(MultiWidget):
... def __init__(self, attrs=None):
... widgets = (
-... TextInput(),
+... TextInput(),
... SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
... SplitDateTimeWidget(),
... )
@@ -3353,13 +3439,13 @@ True
<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" />
>>> class ComplexField(MultiValueField):
-... def __init__(self, required=True, widget=None, label=None, initial=None):
+... def __init__(self, required=True, widget=None, label=None, initial=None):
... fields = (
-... CharField(),
+... CharField(),
... MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
... SplitDateTimeField()
... )
-... super(ComplexField, self).__init__(fields, required, widget, label, initial)
+... super(ComplexField, self).__init__(fields, required, widget, label, initial)
...
... def compress(self, data_list):
... if data_list:
diff --git a/tests/regressiontests/serializers_regress/models.py b/tests/regressiontests/serializers_regress/models.py
index c287b6e0d6..fea5c94cab 100644
--- a/tests/regressiontests/serializers_regress/models.py
+++ b/tests/regressiontests/serializers_regress/models.py
@@ -100,6 +100,12 @@ class Anchor(models.Model):
something for other models to point at"""
data = models.CharField(maxlength=30)
+
+class UniqueAnchor(models.Model):
+ """This is a model that can be used as
+ something for other models to point at"""
+
+ data = models.CharField(unique=True, maxlength=30)
class FKData(models.Model):
data = models.ForeignKey(Anchor, null=True)
@@ -116,6 +122,10 @@ class FKSelfData(models.Model):
class M2MSelfData(models.Model):
data = models.ManyToManyField('self', null=True, symmetrical=False)
+
+class FKDataToField(models.Model):
+ data = models.ForeignKey(UniqueAnchor, null=True, to_field='data')
+
# The following test classes are for validating the
# deserialization of objects that use a user-defined
# field as the primary key.
diff --git a/tests/regressiontests/serializers_regress/tests.py b/tests/regressiontests/serializers_regress/tests.py
index 97b3fbacbe..317739dac4 100644
--- a/tests/regressiontests/serializers_regress/tests.py
+++ b/tests/regressiontests/serializers_regress/tests.py
@@ -159,6 +159,7 @@ The end."""),
(data_obj, 300, Anchor, "Anchor 1"),
(data_obj, 301, Anchor, "Anchor 2"),
+ (data_obj, 302, UniqueAnchor, "UAnchor 1"),
(fk_obj, 400, FKData, 300), # Post reference
(fk_obj, 401, FKData, 500), # Pre reference
@@ -184,8 +185,13 @@ The end."""),
(m2m_obj, 445, M2MSelfData, []),
(m2m_obj, 446, M2MSelfData, []),
+ (fk_obj, 450, FKDataToField, "UAnchor 1"),
+ (fk_obj, 451, FKDataToField, "UAnchor 2"),
+ (fk_obj, 452, FKDataToField, None),
+
(data_obj, 500, Anchor, "Anchor 3"),
(data_obj, 501, Anchor, "Anchor 4"),
+ (data_obj, 502, UniqueAnchor, "UAnchor 2"),
(pk_obj, 601, BooleanPKData, True),
(pk_obj, 602, BooleanPKData, False),
diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py
index c39fafe314..40d022a47a 100644
--- a/tests/regressiontests/test_client_regress/models.py
+++ b/tests/regressiontests/test_client_regress/models.py
@@ -60,7 +60,35 @@ class AssertTemplateUsedTests(TestCase):
self.assertTemplateUsed(response, "Valid POST Template")
except AssertionError, e:
self.assertEquals(str(e), "Template 'Valid POST Template' was not one of the templates used to render the response. Templates used: ['form_view.html', 'base.html']")
+
+class AssertRedirectsTests(TestCase):
+ def test_redirect_page(self):
+ "An assertion is raised if the original page couldn't be retrieved as expected"
+ # This page will redirect with code 301, not 302
+ response = self.client.get('/test_client/permanent_redirect_view/')
+ try:
+ self.assertRedirects(response, '/test_client/get_view/')
+ except AssertionError, e:
+ self.assertEquals(str(e), "Response didn't redirect as expected: Reponse code was 301 (expected 302)")
+
+ def test_incorrect_target(self):
+ "An assertion is raised if the response redirects to another target"
+ response = self.client.get('/test_client/permanent_redirect_view/')
+ try:
+ # Should redirect to get_view
+ self.assertRedirects(response, '/test_client/some_view/')
+ except AssertionError, e:
+ self.assertEquals(str(e), "Response didn't redirect as expected: Reponse code was 301 (expected 302)")
+ def test_target_page(self):
+ "An assertion is raised if the reponse redirect target cannot be retrieved as expected"
+ response = self.client.get('/test_client/double_redirect_view/')
+ try:
+ # The redirect target responds with a 301 code, not 200
+ self.assertRedirects(response, '/test_client/permanent_redirect_view/')
+ except AssertionError, e:
+ self.assertEquals(str(e), "Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)")
+
class AssertFormErrorTests(TestCase):
def test_unknown_form(self):
"An assertion is raised if the form name is unknown"