1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

sqlalchemy: Merged revisions 4054 to 4185 from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/sqlalchemy@4186 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Robin Munn 2006-12-08 15:10:09 +00:00
parent dadfca08c0
commit 122426e745
52 changed files with 2416 additions and 657 deletions

View File

@ -51,6 +51,7 @@ answer newbie questions, and generally made Django that much better:
Jiri Barton Jiri Barton
Ned Batchelder <http://www.nedbatchelder.com/> Ned Batchelder <http://www.nedbatchelder.com/>
Shannon -jj Behrens <http://jjinux.blogspot.com/> Shannon -jj Behrens <http://jjinux.blogspot.com/>
Esdras Beleza <linux@esdrasbeleza.com>
James Bennett James Bennett
Paul Bissex <http://e-scribe.com/> Paul Bissex <http://e-scribe.com/>
Simon Blanchard Simon Blanchard
@ -150,6 +151,7 @@ answer newbie questions, and generally made Django that much better:
SmileyChris <smileychris@gmail.com> SmileyChris <smileychris@gmail.com>
sopel sopel
Thomas Steinacher <tom@eggdrop.ch> Thomas Steinacher <tom@eggdrop.ch>
nowell strite
Radek Švarz <http://www.svarz.cz/translate/> Radek Švarz <http://www.svarz.cz/translate/>
Swaroop C H <http://www.swaroopch.info> Swaroop C H <http://www.swaroopch.info>
Aaron Swartz <http://www.aaronsw.com/> Aaron Swartz <http://www.aaronsw.com/>

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django 1.0\n" "Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-09-25 16:04+0200\n" "POT-Creation-Date: 2006-11-15 18:35+0100\n"
"PO-Revision-Date: 2005-10-08 00:03+0200\n" "PO-Revision-Date: 2005-10-08 00:03+0200\n"
"Last-Translator: Georg Bauer <gb@bofh.ms>\n" "Last-Translator: Georg Bauer <gb@bofh.ms>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -452,7 +452,7 @@ msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable " "Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again." "cookies, reload this page, and try again."
msgstr "" msgstr ""
"Es sieht danach aus, das der Browser keine Cookies akzeptiert. Bitte im " "Es sieht danach aus, dass der Browser keine Cookies akzeptiert. Bitte im "
"Browser Cookies aktivieren und diese Seite neu laden." "Browser Cookies aktivieren und diese Seite neu laden."
#: contrib/admin/views/decorators.py:83 #: contrib/admin/views/decorators.py:83
@ -470,13 +470,13 @@ msgstr ""
msgid "Site administration" msgid "Site administration"
msgstr "Website Verwaltung" msgstr "Website Verwaltung"
#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:17 #: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:18
#, python-format #, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully." msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "%(name)s \"%(obj)s\" wurde erfolgreich hinzugefügt." msgstr "%(name)s \"%(obj)s\" wurde erfolgreich hinzugefügt."
#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347 #: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347
#: contrib/admin/views/auth.py:22 #: contrib/admin/views/auth.py:23
msgid "You may edit it again below." msgid "You may edit it again below."
msgstr "Das Element kann jetzt weiter geändert werden." msgstr "Das Element kann jetzt weiter geändert werden."
@ -496,7 +496,7 @@ msgid "Added %s."
msgstr "%s hinzugefügt." msgstr "%s hinzugefügt."
#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337 #: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
#: contrib/admin/views/main.py:339 #: contrib/admin/views/main.py:339 db/models/manipulators.py:306
msgid "and" msgid "and"
msgstr "und" msgstr "und"
@ -702,7 +702,7 @@ msgstr "XML Text"
msgid "%s does not appear to be a urlpattern object" msgid "%s does not appear to be a urlpattern object"
msgstr "%s ist scheinbar kein urlpattern Objekt" msgstr "%s ist scheinbar kein urlpattern Objekt"
#: contrib/admin/views/auth.py:28 #: contrib/admin/views/auth.py:29
msgid "Add user" msgid "Add user"
msgstr "Benutzer zufügen" msgstr "Benutzer zufügen"
@ -861,10 +861,6 @@ msgstr "Keine vorhanden"
msgid "Add %(name)s" msgid "Add %(name)s"
msgstr "%(name)s zufügen" msgstr "%(name)s zufügen"
#: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "Haben Sie <a href=\"/password_reset/\">ihr Passwort vergessen</a>?"
#: contrib/admin/templates/admin/base.html:25 #: contrib/admin/templates/admin/base.html:25
msgid "Welcome," msgid "Welcome,"
msgstr "Willkommen," msgstr "Willkommen,"
@ -891,7 +887,7 @@ msgid ""
"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " "Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
"All of the following related items will be deleted:" "All of the following related items will be deleted:"
msgstr "" msgstr ""
"Sind Sie sicher, das Sie %(object_name)s \"%(escaped_object)s\" löschen " "Sind Sie sicher, dass Sie %(object_name)s \"%(escaped_object)s\" löschen "
"wollen? Es werden zusätzlich die folgenden abhängigen Daten mit gelöscht:" "wollen? Es werden zusätzlich die folgenden abhängigen Daten mit gelöscht:"
#: contrib/admin/templates/admin/delete_confirmation.html:26 #: contrib/admin/templates/admin/delete_confirmation.html:26
@ -1061,7 +1057,7 @@ msgid ""
"password twice so we can verify you typed it in correctly." "password twice so we can verify you typed it in correctly."
msgstr "" msgstr ""
"Bitte geben Sie aus Sicherheitsgründen erst Ihr altes Kennwort und darunter " "Bitte geben Sie aus Sicherheitsgründen erst Ihr altes Kennwort und darunter "
"dann zweimal (um sicherzustellen, das Sie es korrekt eingegeben haben) das " "dann zweimal (um sicherzustellen, dass Sie es korrekt eingegeben haben) das "
"neue Kennwort ein." "neue Kennwort ein."
#: contrib/admin/templates/registration/password_change_form.html:17 #: contrib/admin/templates/registration/password_change_form.html:17
@ -1087,7 +1083,7 @@ msgstr "Sie erhalten diese Mail, weil Sie ein neues Kennwort"
#: contrib/admin/templates/registration/password_reset_email.html:3 #: contrib/admin/templates/registration/password_reset_email.html:3
#, python-format #, python-format
msgid "for your user account at %(site_name)s" msgid "for your user account at %(site_name)s"
msgstr "für ihren Benutzer bei %(site_name)s angefordert haben." msgstr "für Ihren Benutzer bei %(site_name)s angefordert haben."
#: contrib/admin/templates/registration/password_reset_email.html:5 #: contrib/admin/templates/registration/password_reset_email.html:5
#, python-format #, python-format
@ -1104,7 +1100,7 @@ msgstr "Ihr Benutzername, falls Sie ihn vergessen haben:"
#: contrib/admin/templates/registration/password_reset_email.html:13 #: contrib/admin/templates/registration/password_reset_email.html:13
msgid "Thanks for using our site!" msgid "Thanks for using our site!"
msgstr "Vielen Dank, das Sie unsere Seiten benutzen!" msgstr "Vielen Dank, dass Sie unsere Seiten benutzen!"
#: contrib/admin/templates/registration/password_reset_email.html:15 #: contrib/admin/templates/registration/password_reset_email.html:15
#, python-format #, python-format
@ -1367,7 +1363,7 @@ msgid ""
"Designates that this user has all permissions without explicitly assigning " "Designates that this user has all permissions without explicitly assigning "
"them." "them."
msgstr "" msgstr ""
"Bestimmt, das dieser Benutzer alle Berechtigungen hat, ohne diese einzeln " "Bestimmt, dass dieser Benutzer alle Berechtigungen hat, ohne diese einzeln "
"zuweisen zu müssen." "zuweisen zu müssen."
#: contrib/auth/models.py:98 #: contrib/auth/models.py:98
@ -1414,10 +1410,18 @@ msgstr "Wichtige Daten"
msgid "Groups" msgid "Groups"
msgstr "Gruppen" msgstr "Gruppen"
#: contrib/auth/models.py:256 #: contrib/auth/models.py:258
msgid "message" msgid "message"
msgstr "Mitteilung" msgstr "Mitteilung"
#: contrib/auth/forms.py:16
msgid "The two password fields didn't match."
msgstr "Die zwei Passwörter sind nicht gleich."
#: contrib/auth/forms.py:24
msgid "A user with that username already exists."
msgstr "Ein Benutzer mit diesem Namen existiert bereits."
#: contrib/auth/forms.py:52 #: contrib/auth/forms.py:52
msgid "" msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are " "Your Web browser doesn't appear to have cookies enabled. Cookies are "
@ -1432,10 +1436,10 @@ msgstr "Dieser Benutzer ist inaktiv."
#: contrib/auth/forms.py:84 #: contrib/auth/forms.py:84
msgid "" msgid ""
"That e-mail address doesn't have an associated user acount. Are you sure " "That e-mail address doesn't have an associated user account. Are you sure "
"you've registered?" "you've registered?"
msgstr "" msgstr ""
"Die Email-Adresse hat keinen Benutzer zugeordnet. Sicher, das die Adresse " "Die Email-Adresse hat keinen Benutzer zugeordnet. Sicher, dass die Adresse "
"hier angemeldet ist?" "hier angemeldet ist?"
#: contrib/auth/forms.py:116 #: contrib/auth/forms.py:116
@ -1783,58 +1787,62 @@ msgid "Norwegian"
msgstr "Norwegisch" msgstr "Norwegisch"
#: conf/global_settings.py:59 #: conf/global_settings.py:59
msgid "Polish"
msgstr "Polnisch"
#: conf/global_settings.py:60
msgid "Brazilian" msgid "Brazilian"
msgstr "Brasilianisch" msgstr "Brasilianisch"
#: conf/global_settings.py:60 #: conf/global_settings.py:61
msgid "Romanian" msgid "Romanian"
msgstr "Rumänisch" msgstr "Rumänisch"
#: conf/global_settings.py:61 #: conf/global_settings.py:62
msgid "Russian" msgid "Russian"
msgstr "Russisch" msgstr "Russisch"
#: conf/global_settings.py:62 #: conf/global_settings.py:63
msgid "Slovak" msgid "Slovak"
msgstr "Slowakisch" msgstr "Slowakisch"
#: conf/global_settings.py:63 #: conf/global_settings.py:64
msgid "Slovenian" msgid "Slovenian"
msgstr "Slowenisch" msgstr "Slowenisch"
#: conf/global_settings.py:64 #: conf/global_settings.py:65
msgid "Serbian" msgid "Serbian"
msgstr "Serbisch" msgstr "Serbisch"
#: conf/global_settings.py:65 #: conf/global_settings.py:66
msgid "Swedish" msgid "Swedish"
msgstr "Schwedisch" msgstr "Schwedisch"
#: conf/global_settings.py:66 #: conf/global_settings.py:67
msgid "Tamil" msgid "Tamil"
msgstr "Tamilisch" msgstr "Tamilisch"
#: conf/global_settings.py:67 #: conf/global_settings.py:68
msgid "Turkish" msgid "Turkish"
msgstr "Türkisch" msgstr "Türkisch"
#: conf/global_settings.py:68 #: conf/global_settings.py:69
msgid "Ukrainian" msgid "Ukrainian"
msgstr "Ukrainisch" msgstr "Ukrainisch"
#: conf/global_settings.py:69 #: conf/global_settings.py:70
msgid "Simplified Chinese" msgid "Simplified Chinese"
msgstr "Vereinfachtes Chinesisch" msgstr "Vereinfachtes Chinesisch"
#: conf/global_settings.py:70 #: conf/global_settings.py:71
msgid "Traditional Chinese" msgid "Traditional Chinese"
msgstr "Traditionelles Chinesisch" msgstr "Traditionelles Chinesisch"
#: core/validators.py:63 #: core/validators.py:64
msgid "This value must contain only letters, numbers and underscores." msgid "This value must contain only letters, numbers and underscores."
msgstr "Dieser Wert darf nur Buchstaben, Ziffern und Unterstriche enthalten." msgstr "Dieser Wert darf nur Buchstaben, Ziffern und Unterstriche enthalten."
#: core/validators.py:67 #: core/validators.py:68
msgid "" msgid ""
"This value must contain only letters, numbers, underscores, dashes or " "This value must contain only letters, numbers, underscores, dashes or "
"slashes." "slashes."
@ -1842,85 +1850,85 @@ msgstr ""
"Dieser Wert darf nur Buchstaben, Ziffern, Unterstriche und Schrägstriche " "Dieser Wert darf nur Buchstaben, Ziffern, Unterstriche und Schrägstriche "
"enthalten." "enthalten."
#: core/validators.py:71 #: core/validators.py:72
msgid "This value must contain only letters, numbers, underscores or hyphens." msgid "This value must contain only letters, numbers, underscores or hyphens."
msgstr "" msgstr ""
"Dieser Wert darf nur Buchstaben, Ziffern, Unterstriche und Bindestriche " "Dieser Wert darf nur Buchstaben, Ziffern, Unterstriche und Bindestriche "
"enthalten." "enthalten."
#: core/validators.py:75 #: core/validators.py:76
msgid "Uppercase letters are not allowed here." msgid "Uppercase letters are not allowed here."
msgstr "Großbuchstaben sind hier nicht erlaubt." msgstr "Großbuchstaben sind hier nicht erlaubt."
#: core/validators.py:79 #: core/validators.py:80
msgid "Lowercase letters are not allowed here." msgid "Lowercase letters are not allowed here."
msgstr "Kleinbuchstaben sind hier nicht erlaubt." msgstr "Kleinbuchstaben sind hier nicht erlaubt."
#: core/validators.py:86 #: core/validators.py:87
msgid "Enter only digits separated by commas." msgid "Enter only digits separated by commas."
msgstr "Hier sind nur durch Komma getrennte Ziffern erlaubt." msgstr "Hier sind nur durch Komma getrennte Ziffern erlaubt."
#: core/validators.py:98 #: core/validators.py:99
msgid "Enter valid e-mail addresses separated by commas." msgid "Enter valid e-mail addresses separated by commas."
msgstr "Bitte mit Komma getrennte, gültige eMail-Adressen eingeben." msgstr "Bitte mit Komma getrennte, gültige eMail-Adressen eingeben."
#: core/validators.py:102 #: core/validators.py:103
msgid "Please enter a valid IP address." msgid "Please enter a valid IP address."
msgstr "Bitte eine gültige IP-Adresse eingeben." msgstr "Bitte eine gültige IP-Adresse eingeben."
#: core/validators.py:106 #: core/validators.py:107
msgid "Empty values are not allowed here." msgid "Empty values are not allowed here."
msgstr "Dieses Feld darf nicht leer sein." msgstr "Dieses Feld darf nicht leer sein."
#: core/validators.py:110 #: core/validators.py:111
msgid "Non-numeric characters aren't allowed here." msgid "Non-numeric characters aren't allowed here."
msgstr "Nichtnumerische Zeichen sind hier nicht erlaubt." msgstr "Nichtnumerische Zeichen sind hier nicht erlaubt."
#: core/validators.py:114 #: core/validators.py:115
msgid "This value can't be comprised solely of digits." msgid "This value can't be comprised solely of digits."
msgstr "Dieser Wert darf nicht nur aus Ziffern bestehen." msgstr "Dieser Wert darf nicht nur aus Ziffern bestehen."
#: core/validators.py:119 #: core/validators.py:120
msgid "Enter a whole number." msgid "Enter a whole number."
msgstr "Bitte eine ganze Zahl eingeben." msgstr "Bitte eine ganze Zahl eingeben."
#: core/validators.py:123 #: core/validators.py:124
msgid "Only alphabetical characters are allowed here." msgid "Only alphabetical characters are allowed here."
msgstr "Nur alphabetische Zeichen sind hier erlaubt." msgstr "Nur alphabetische Zeichen sind hier erlaubt."
#: core/validators.py:138 #: core/validators.py:139
msgid "Year must be 1900 or later." msgid "Year must be 1900 or later."
msgstr "Das Jahr muss 1900 oder später sein." msgstr "Das Jahr muss 1900 oder später sein."
#: core/validators.py:142 #: core/validators.py:143
#, python-format #, python-format
msgid "Invalid date: %s." msgid "Invalid date: %s."
msgstr "Ungültiges Datum: %s" msgstr "Ungültiges Datum: %s"
#: core/validators.py:146 db/models/fields/__init__.py:415 #: core/validators.py:147 db/models/fields/__init__.py:424
msgid "Enter a valid date in YYYY-MM-DD format." msgid "Enter a valid date in YYYY-MM-DD format."
msgstr "Bitte ein gültiges Datum im Format JJJJ-MM-TT eingeben." msgstr "Bitte ein gültiges Datum im Format JJJJ-MM-TT eingeben."
#: core/validators.py:151 #: core/validators.py:152
msgid "Enter a valid time in HH:MM format." msgid "Enter a valid time in HH:MM format."
msgstr "Bitte eine gültige Zeit im Format SS:MM eingeben." msgstr "Bitte eine gültige Zeit im Format SS:MM eingeben."
#: core/validators.py:155 db/models/fields/__init__.py:477 #: core/validators.py:156 db/models/fields/__init__.py:488
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr "" msgstr ""
"Bitte eine gültige Datums- und Zeitangabe im Format JJJJ-MM-TT SS:MM " "Bitte eine gültige Datums- und Zeitangabe im Format JJJJ-MM-TT SS:MM "
"eingeben." "eingeben."
#: core/validators.py:160 #: core/validators.py:161
msgid "Enter a valid e-mail address." msgid "Enter a valid e-mail address."
msgstr "Bitte eine gültige eMail-Adresse eingeben" msgstr "Bitte eine gültige eMail-Adresse eingeben"
#: core/validators.py:172 core/validators.py:401 forms/__init__.py:661 #: core/validators.py:173 core/validators.py:442 forms/__init__.py:667
msgid "No file was submitted. Check the encoding type on the form." msgid "No file was submitted. Check the encoding type on the form."
msgstr "" msgstr ""
"Es wurde keine Datei geschickt. Eventuell ist das Formular-Encoding falsch." "Es wurde keine Datei geschickt. Eventuell ist das Formular-Encoding falsch."
#: core/validators.py:176 #: core/validators.py:177
msgid "" msgid ""
"Upload a valid image. The file you uploaded was either not an image or a " "Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image." "corrupted image."
@ -1928,27 +1936,27 @@ msgstr ""
"Bitte ein Bild hochladen. Die Datei, die hochgeladen wurde, ist kein Bild " "Bitte ein Bild hochladen. Die Datei, die hochgeladen wurde, ist kein Bild "
"oder ist defekt." "oder ist defekt."
#: core/validators.py:183 #: core/validators.py:184
#, python-format #, python-format
msgid "The URL %s does not point to a valid image." msgid "The URL %s does not point to a valid image."
msgstr "Die URL %s zeigt nicht auf ein gültiges Bild." msgstr "Die URL %s zeigt nicht auf ein gültiges Bild."
#: core/validators.py:187 #: core/validators.py:188
#, python-format #, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr "" msgstr ""
"Telefonnummern müssen im Format XXX-XXX-XXXX sein. \"%s\" ist ungültig." "Telefonnummern müssen im Format XXX-XXX-XXXX sein. \"%s\" ist ungültig."
#: core/validators.py:195 #: core/validators.py:196
#, python-format #, python-format
msgid "The URL %s does not point to a valid QuickTime video." msgid "The URL %s does not point to a valid QuickTime video."
msgstr "Die URL %s zeigt nicht auf ein gültiges QuickTime video." msgstr "Die URL %s zeigt nicht auf ein gültiges QuickTime video."
#: core/validators.py:199 #: core/validators.py:200
msgid "A valid URL is required." msgid "A valid URL is required."
msgstr "Eine gültige URL ist hier verlangt." msgstr "Eine gültige URL ist hier verlangt."
#: core/validators.py:213 #: core/validators.py:214
#, python-format #, python-format
msgid "" msgid ""
"Valid HTML is required. Specific errors are:\n" "Valid HTML is required. Specific errors are:\n"
@ -1957,71 +1965,83 @@ msgstr ""
"Bitte gültiges HTML eingeben. Fehler sind:\n" "Bitte gültiges HTML eingeben. Fehler sind:\n"
"%s" "%s"
#: core/validators.py:220 #: core/validators.py:221
#, python-format #, python-format
msgid "Badly formed XML: %s" msgid "Badly formed XML: %s"
msgstr "Ungültiges XML: %s" msgstr "Ungültiges XML: %s"
#: core/validators.py:230 #: core/validators.py:238
#, python-format #, python-format
msgid "Invalid URL: %s" msgid "Invalid URL: %s"
msgstr "Ungültige URL: %s" msgstr "Ungültige URL: %s"
#: core/validators.py:234 core/validators.py:236 #: core/validators.py:243 core/validators.py:245
#, python-format #, python-format
msgid "The URL %s is a broken link." msgid "The URL %s is a broken link."
msgstr "Die URL %s funktioniert nicht." msgstr "Die URL %s funktioniert nicht."
#: core/validators.py:242 #: core/validators.py:251
msgid "Enter a valid U.S. state abbreviation." msgid "Enter a valid U.S. state abbreviation."
msgstr "Bitte eine gültige Abkürzung für einen US-Staat eingeben." msgstr "Bitte eine gültige Abkürzung für einen US-Staat eingeben."
#: core/validators.py:256 #: core/validators.py:265
#, python-format #, python-format
msgid "Watch your mouth! The word %s is not allowed here." msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Keine Schimpfworte! Das Wort %s ist hier nicht gern gesehen!" msgstr[0] "Keine Schimpfworte! Das Wort %s ist hier nicht gern gesehen!"
msgstr[1] "Keine Schimpfworte! Die Wörter %s sind hier nicht gern gesehen!" msgstr[1] "Keine Schimpfworte! Die Wörter %s sind hier nicht gern gesehen!"
#: core/validators.py:263 #: core/validators.py:272
#, python-format #, python-format
msgid "This field must match the '%s' field." msgid "This field must match the '%s' field."
msgstr "Dieses Feld muss zum Feld '%s' passen." msgstr "Dieses Feld muss zum Feld '%s' passen."
#: core/validators.py:282 #: core/validators.py:291
msgid "Please enter something for at least one field." msgid "Please enter something for at least one field."
msgstr "Bitte mindestens eines der Felder ausfüllen." msgstr "Bitte mindestens eines der Felder ausfüllen."
#: core/validators.py:291 core/validators.py:302 #: core/validators.py:300 core/validators.py:311
msgid "Please enter both fields or leave them both empty." msgid "Please enter both fields or leave them both empty."
msgstr "Bitte entweder beide Felder ausfüllen, oder beide leer lassen." msgstr "Bitte entweder beide Felder ausfüllen, oder beide leer lassen."
#: core/validators.py:309 #: core/validators.py:318
#, python-format #, python-format
msgid "This field must be given if %(field)s is %(value)s" msgid "This field must be given if %(field)s is %(value)s"
msgstr "" msgstr ""
"Dieses Feld muss gefüllt sein, wenn Feld %(field)s den Wert %(value)s hat." "Dieses Feld muss gefüllt sein, wenn Feld %(field)s den Wert %(value)s hat."
#: core/validators.py:321 #: core/validators.py:330
#, python-format #, python-format
msgid "This field must be given if %(field)s is not %(value)s" msgid "This field must be given if %(field)s is not %(value)s"
msgstr "" msgstr ""
"Dieses Feld muss gefüllt sein, wenn Feld %(field)s nicht %(value)s ist." "Dieses Feld muss gefüllt sein, wenn Feld %(field)s nicht %(value)s ist."
#: core/validators.py:340 #: core/validators.py:349
msgid "Duplicate values are not allowed." msgid "Duplicate values are not allowed."
msgstr "Doppelte Werte sind hier nicht erlaubt." msgstr "Doppelte Werte sind hier nicht erlaubt."
#: core/validators.py:363 #: core/validators.py:364
msgid "This value must be between %s and %s."
msgstr "Dieser Wert muss zwischen %s und %s sein."
#: core/validators.py:366
msgid "This value must be at least %s."
msgstr "Dieser Wert muss mindestens %s sein."
#: core/validators.py:368
msgid "This value must be no more than %s."
msgstr "Dieser Wert darf maximal %s sein."
#: core/validators.py:404
#, python-format #, python-format
msgid "This value must be a power of %s." msgid "This value must be a power of %s."
msgstr "Dieser Wert muss eine Potenz von %s sein." msgstr "Dieser Wert muss eine Potenz von %s sein."
#: core/validators.py:374 #: core/validators.py:415
msgid "Please enter a valid decimal number." msgid "Please enter a valid decimal number."
msgstr "Bitte eine gültige Dezimalzahl eingeben." msgstr "Bitte eine gültige Dezimalzahl eingeben."
#: core/validators.py:378 #: core/validators.py:419
#, python-format #, python-format
msgid "Please enter a valid decimal number with at most %s total digit." msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural "" msgid_plural ""
@ -2029,7 +2049,7 @@ msgid_plural ""
msgstr[0] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffer eingeben." msgstr[0] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffer eingeben."
msgstr[1] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffern eingeben." msgstr[1] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffern eingeben."
#: core/validators.py:381 #: core/validators.py:422
#, python-format #, python-format
msgid "" msgid ""
"Please enter a valid decimal number with a whole part of at most %s digit." "Please enter a valid decimal number with a whole part of at most %s digit."
@ -2038,7 +2058,7 @@ msgid_plural ""
msgstr[0] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffer eingeben." msgstr[0] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffer eingeben."
msgstr[1] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffern eingeben." msgstr[1] "Bitte eine gültige Dezimalzahl mit maximal %s Ziffern eingeben."
#: core/validators.py:384 #: core/validators.py:425
#, python-format #, python-format
msgid "Please enter a valid decimal number with at most %s decimal place." msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural "" msgid_plural ""
@ -2048,39 +2068,39 @@ msgstr[0] ""
msgstr[1] "" msgstr[1] ""
"Bitte eine gültige Dezimalzahl mit maximal %s Dezimalstellen eingeben." "Bitte eine gültige Dezimalzahl mit maximal %s Dezimalstellen eingeben."
#: core/validators.py:394 #: core/validators.py:435
#, python-format #, python-format
msgid "Make sure your uploaded file is at least %s bytes big." msgid "Make sure your uploaded file is at least %s bytes big."
msgstr "" msgstr ""
"Bitte sicherstellen, daß die hochgeladene Datei mindestens %s Bytes gross " "Bitte sicherstellen, daß die hochgeladene Datei mindestens %s Bytes gross "
"ist." "ist."
#: core/validators.py:395 #: core/validators.py:436
#, python-format #, python-format
msgid "Make sure your uploaded file is at most %s bytes big." msgid "Make sure your uploaded file is at most %s bytes big."
msgstr "" msgstr ""
"Bitte sicherstellen, daß die hochgeladene Datei maximal %s Bytes gross ist." "Bitte sicherstellen, daß die hochgeladene Datei maximal %s Bytes gross ist."
#: core/validators.py:412 #: core/validators.py:453
msgid "The format for this field is wrong." msgid "The format for this field is wrong."
msgstr "Das Format für dieses Feld ist falsch." msgstr "Das Format für dieses Feld ist falsch."
#: core/validators.py:427 #: core/validators.py:468
msgid "This field is invalid." msgid "This field is invalid."
msgstr "Dieses Feld ist ungültig." msgstr "Dieses Feld ist ungültig."
#: core/validators.py:463 #: core/validators.py:504
#, python-format #, python-format
msgid "Could not retrieve anything from %s." msgid "Could not retrieve anything from %s."
msgstr "Konnte nichts von %s empfangen." msgstr "Konnte nichts von %s empfangen."
#: core/validators.py:466 #: core/validators.py:507
#, python-format #, python-format
msgid "" msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr "Die URL %(url)s lieferte den falschen Content-Type '%(contenttype)s'." msgstr "Die URL %(url)s lieferte den falschen Content-Type '%(contenttype)s'."
#: core/validators.py:499 #: core/validators.py:540
#, python-format #, python-format
msgid "" msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
@ -2089,7 +2109,7 @@ msgstr ""
"Bitte das ungeschlossene %(tag)s Tag in Zeile %(line)s schließen. Die Zeile " "Bitte das ungeschlossene %(tag)s Tag in Zeile %(line)s schließen. Die Zeile "
"beginnt mit \"%(start)s\"." "beginnt mit \"%(start)s\"."
#: core/validators.py:503 #: core/validators.py:544
#, python-format #, python-format
msgid "" msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line " "Some text starting on line %(line)s is not allowed in that context. (Line "
@ -2098,7 +2118,7 @@ msgstr ""
"In Zeile %(line)s ist Text, der nicht in dem Kontext erlaubt ist. Die Zeile " "In Zeile %(line)s ist Text, der nicht in dem Kontext erlaubt ist. Die Zeile "
"beginnt mit \"%(start)s\"." "beginnt mit \"%(start)s\"."
#: core/validators.py:508 #: core/validators.py:549
#, python-format #, python-format
msgid "" msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
@ -2107,7 +2127,7 @@ msgstr ""
"Das Attribute %(attr)s in Zeile %(line)s ist ungültig. Die Zeile beginnt mit " "Das Attribute %(attr)s in Zeile %(line)s ist ungültig. Die Zeile beginnt mit "
"\"%(start)s\"." "\"%(start)s\"."
#: core/validators.py:513 #: core/validators.py:554
#, python-format #, python-format
msgid "" msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
@ -2116,7 +2136,7 @@ msgstr ""
"<%(tag)s> in Zeile %(line)s ist ungültig. Die Zeile beginnt mit \"%(start)s" "<%(tag)s> in Zeile %(line)s ist ungültig. Die Zeile beginnt mit \"%(start)s"
"\"." "\"."
#: core/validators.py:517 #: core/validators.py:558
#, python-format #, python-format
msgid "" msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line " "A tag on line %(line)s is missing one or more required attributes. (Line "
@ -2125,7 +2145,7 @@ msgstr ""
"Ein Tag in Zeile %(line)s hat eines oder mehrere Pflichtattribute nicht. Die " "Ein Tag in Zeile %(line)s hat eines oder mehrere Pflichtattribute nicht. Die "
"Zeile beginnt mit \"%(start)s\"." "Zeile beginnt mit \"%(start)s\"."
#: core/validators.py:522 #: core/validators.py:563
#, python-format #, python-format
msgid "" msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
@ -2149,37 +2169,37 @@ msgstr "%(verbose_name)s wurde erfolgreich aktualisiert."
msgid "The %(verbose_name)s was deleted." msgid "The %(verbose_name)s was deleted."
msgstr "%(verbose_name)s wurde gelöscht" msgstr "%(verbose_name)s wurde gelöscht"
#: db/models/manipulators.py:302 #: db/models/manipulators.py:305
#, python-format #, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s." msgid "%(object)s with this %(type)s already exists for the given %(field)s."
msgstr "" msgstr ""
"Ein '%(object)s' in dieser '%(type)s' existiert bereits für dieses '%(field)" "Ein '%(object)s' in dieser '%(type)s' existiert bereits für dieses '%(field)"
"s'." "s'."
#: db/models/fields/__init__.py:40 #: db/models/fields/__init__.py:41
#, python-format #, python-format
msgid "%(optname)s with this %(fieldname)s already exists." msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "Ein '%(optname)s' mit diesem '%(fieldname)s' existiert bereits." msgstr "Ein '%(optname)s' mit diesem '%(fieldname)s' existiert bereits."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 #: db/models/fields/__init__.py:115 db/models/fields/__init__.py:266
#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562 #: db/models/fields/__init__.py:569 db/models/fields/__init__.py:580
#: forms/__init__.py:346 #: forms/__init__.py:352
msgid "This field is required." msgid "This field is required."
msgstr "Dieses Feld ist zwingend." msgstr "Dieses Feld ist zwingend."
#: db/models/fields/__init__.py:340 #: db/models/fields/__init__.py:349
msgid "This value must be an integer." msgid "This value must be an integer."
msgstr "Dieser Wert muss eine Ganzzahl sein." msgstr "Dieser Wert muss eine Ganzzahl sein."
#: db/models/fields/__init__.py:372 #: db/models/fields/__init__.py:381
msgid "This value must be either True or False." msgid "This value must be either True or False."
msgstr "Dieser Wert muss wahr oder falsch sein." msgstr "Dieser Wert muss wahr oder falsch sein."
#: db/models/fields/__init__.py:388 #: db/models/fields/__init__.py:397
msgid "This field cannot be null." msgid "This field cannot be null."
msgstr "Dieses Feld darf nicht leer sein." msgstr "Dieses Feld darf nicht leer sein."
#: db/models/fields/__init__.py:571 #: db/models/fields/__init__.py:589
msgid "Enter a valid filename." msgid "Enter a valid filename."
msgstr "Bitte einen gültigen Dateinamen eingeben" msgstr "Bitte einen gültigen Dateinamen eingeben"
@ -2209,36 +2229,36 @@ msgstr[0] ""
msgstr[1] "" msgstr[1] ""
"Bitte gültige IDs für %(self)s eingeben. Die Werte %(value)r sind ungültig." "Bitte gültige IDs für %(self)s eingeben. Die Werte %(value)r sind ungültig."
#: forms/__init__.py:381 #: forms/__init__.py:387
#, python-format #, python-format
msgid "Ensure your text is less than %s character." msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters." msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Bitte sicherstellen, das der Text weniger als %s Zeichen hat." msgstr[0] "Bitte sicherstellen, dass der Text weniger als %s Zeichen hat."
msgstr[1] "Bitte sicherstellen, das der Text weniger als %s Zeichen hat." msgstr[1] "Bitte sicherstellen, dass der Text weniger als %s Zeichen hat."
#: forms/__init__.py:386 #: forms/__init__.py:392
msgid "Line breaks are not allowed here." msgid "Line breaks are not allowed here."
msgstr "Zeilenumbrüche sind hier nicht erlaubt." msgstr "Zeilenumbrüche sind hier nicht erlaubt."
#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599 #: forms/__init__.py:493 forms/__init__.py:566 forms/__init__.py:605
#, python-format #, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s." msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "" msgstr ""
"Bitte eine gültige Auswahl treffen; '%(data)s' ist nicht in %(choices)s." "Bitte eine gültige Auswahl treffen; '%(data)s' ist nicht in %(choices)s."
#: forms/__init__.py:663 #: forms/__init__.py:669
msgid "The submitted file is empty." msgid "The submitted file is empty."
msgstr "Die ausgewählte Datei ist leer." msgstr "Die ausgewählte Datei ist leer."
#: forms/__init__.py:719 #: forms/__init__.py:725
msgid "Enter a whole number between -32,768 and 32,767." msgid "Enter a whole number between -32,768 and 32,767."
msgstr "Bitte eine ganze Zahl zwischen -32.768 und 32.767 eingeben." msgstr "Bitte eine ganze Zahl zwischen -32.768 und 32.767 eingeben."
#: forms/__init__.py:729 #: forms/__init__.py:735
msgid "Enter a positive number." msgid "Enter a positive number."
msgstr "Bitte eine ganze, positive Zahl eingeben." msgstr "Bitte eine ganze, positive Zahl eingeben."
#: forms/__init__.py:739 #: forms/__init__.py:745
msgid "Enter a whole number between 0 and 32,767." msgid "Enter a whole number between 0 and 32,767."
msgstr "Bitte eine ganze Zahl zwischen 0 und 32.767 eingeben." msgstr "Bitte eine ganze Zahl zwischen 0 und 32.767 eingeben."

View File

@ -107,6 +107,11 @@ msgid ""
"\n" "\n"
"http://%(domain)s%(url)s" "http://%(domain)s%(url)s"
msgstr "" msgstr ""
"Σχόλιο από τον/την %(user)s την %(date)s\n"
"\n"
"%(comment)s\n"
"\n"
"http://%(domain)s%(url)s"
#: contrib/comments/models.py:168 #: contrib/comments/models.py:168
msgid "person's name" msgid "person's name"
@ -141,11 +146,11 @@ msgstr "ημερομηνία βαθμολογίας"
#: contrib/comments/models.py:237 #: contrib/comments/models.py:237
#, fuzzy #, fuzzy
msgid "karma score" msgid "karma score"
msgstr "βαθμολογία" msgstr "karma"
#: contrib/comments/models.py:238 #: contrib/comments/models.py:238
msgid "karma scores" msgid "karma scores"
msgstr "" msgstr "karma"
#: contrib/comments/models.py:242 #: contrib/comments/models.py:242
#, python-format #, python-format
@ -159,7 +164,7 @@ msgid ""
"\n" "\n"
"%(text)s" "%(text)s"
msgstr "" msgstr ""
"Αυτο το σχόλιο σημειώθει απο %(χρήστη)ες\n" "Αυτο το σχόλιο σημειώθηκε απο %(χρήστη)ες\n"
"\n" "\n"
"%(κείμενο)α" "%(κείμενο)α"
@ -245,7 +250,7 @@ msgstr ""
#: contrib/comments/views/comments.py:193 #: contrib/comments/views/comments.py:193
#: contrib/comments/views/comments.py:284 #: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted" msgid "One or more of the required fields wasn't submitted"
msgstr "Ένα ή περισσότερα από τα απαιτούμενα πεδία δεν υποβλίθει" msgstr "Ένα ή περισσότερα από τα απαιτούμενα πεδία δεν υπεβλήθει"
#: contrib/comments/views/comments.py:197 #: contrib/comments/views/comments.py:197
#: contrib/comments/views/comments.py:286 #: contrib/comments/views/comments.py:286
@ -268,7 +273,7 @@ msgstr ""
#: contrib/comments/templates/comments/form.html:8 #: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/login.html:17 #: contrib/admin/templates/admin/login.html:17
msgid "Username:" msgid "Username:"
msgstr "" msgstr "Όνομα χρήστη:"
#: contrib/comments/templates/comments/form.html:6 #: contrib/comments/templates/comments/form.html:6
#: contrib/admin/templates/admin/login.html:20 #: contrib/admin/templates/admin/login.html:20
@ -298,21 +303,21 @@ msgstr "Ξεχάσατε τον κωδικό σας;"
#: contrib/admin/templates/admin_doc/index.html:4 #: contrib/admin/templates/admin_doc/index.html:4
#: contrib/admin/templates/admin_doc/model_index.html:5 #: contrib/admin/templates/admin_doc/model_index.html:5
msgid "Log out" msgid "Log out"
msgstr "" msgstr "Αποσύνδεση"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
msgid "Ratings" msgid "Ratings"
msgstr "" msgstr "Βαθμολογίες"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23 #: contrib/comments/templates/comments/form.html:23
msgid "Required" msgid "Required"
msgstr "" msgstr "Απαραίτητο"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23 #: contrib/comments/templates/comments/form.html:23
msgid "Optional" msgid "Optional"
msgstr "" msgstr "Προαιρετικό"
#: contrib/comments/templates/comments/form.html:23 #: contrib/comments/templates/comments/form.html:23
msgid "Post a photo" msgid "Post a photo"
@ -326,11 +331,11 @@ msgstr "Σχόλιο:"
#: contrib/comments/templates/comments/form.html:32 #: contrib/comments/templates/comments/form.html:32
#: contrib/comments/templates/comments/freeform.html:9 #: contrib/comments/templates/comments/freeform.html:9
msgid "Preview comment" msgid "Preview comment"
msgstr "" msgstr "Προεπισκόπηση σχολίου"
#: contrib/comments/templates/comments/freeform.html:4 #: contrib/comments/templates/comments/freeform.html:4
msgid "Your name:" msgid "Your name:"
msgstr "" msgstr "Το όνομα σας:"
#: contrib/admin/filterspecs.py:40 #: contrib/admin/filterspecs.py:40
#, python-format #, python-format
@ -338,15 +343,17 @@ msgid ""
"<h3>By %s:</h3>\n" "<h3>By %s:</h3>\n"
"<ul>\n" "<ul>\n"
msgstr "" msgstr ""
"<h3>Από %s:</h3>\n"
"<ul>\n"
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88 #: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
#: contrib/admin/filterspecs.py:143 #: contrib/admin/filterspecs.py:143
msgid "All" msgid "All"
msgstr "" msgstr "Όλα"
#: contrib/admin/filterspecs.py:109 #: contrib/admin/filterspecs.py:109
msgid "Any date" msgid "Any date"
msgstr "" msgstr "Όλες οι ημερομηνίες"
#: contrib/admin/filterspecs.py:110 #: contrib/admin/filterspecs.py:110
msgid "Today" msgid "Today"
@ -354,7 +361,7 @@ msgstr "Σήμερα"
#: contrib/admin/filterspecs.py:113 #: contrib/admin/filterspecs.py:113
msgid "Past 7 days" msgid "Past 7 days"
msgstr "" msgstr "Τις προηγούμενες 7 ημέρες"
#: contrib/admin/filterspecs.py:115 #: contrib/admin/filterspecs.py:115
msgid "This month" msgid "This month"
@ -374,7 +381,7 @@ msgstr "Όχι"
#: contrib/admin/filterspecs.py:150 #: contrib/admin/filterspecs.py:150
msgid "Unknown" msgid "Unknown"
msgstr "γνωστο" msgstr "Άγνωστο"
#: contrib/admin/models.py:16 #: contrib/admin/models.py:16
msgid "action time" msgid "action time"
@ -441,7 +448,7 @@ msgstr ""
#: contrib/admin/views/decorators.py:82 #: contrib/admin/views/decorators.py:82
msgid "Usernames cannot contain the '@' character." msgid "Usernames cannot contain the '@' character."
msgstr "Τα ονόματα των Χρηστών δεν μπορόυν να περιέχουν τον χαρακτήρα '@'." msgstr "Τα ονόματα των χρηστών δεν μπορόυν να περιέχουν τον χαρακτήρα '@'."
#: contrib/admin/views/decorators.py:84 #: contrib/admin/views/decorators.py:84
#, python-format #, python-format
@ -452,16 +459,16 @@ msgstr ""
#: contrib/admin/views/main.py:226 #: contrib/admin/views/main.py:226
msgid "Site administration" msgid "Site administration"
msgstr "Διαχείριση του Διαδυκτιακού χώρου" msgstr "Διαχείριση του Διαδικτυακού χώρου"
#: contrib/admin/views/main.py:260 #: contrib/admin/views/main.py:260
#, python-format #, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully." msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "" msgstr "Το %(name)s \"%(obj)s\" αποθηκεύτηκε επιτυχώς."
#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348 #: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
msgid "You may edit it again below." msgid "You may edit it again below."
msgstr "" msgstr "Μπορείτε να το επεξεργαστείτε ξανα παρακάτω."
#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357 #: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
#, python-format #, python-format
@ -471,12 +478,12 @@ msgstr "Μπορείτε να προσθέσετε ακόμα ένα %s απο
#: contrib/admin/views/main.py:290 #: contrib/admin/views/main.py:290
#, python-format #, python-format
msgid "Add %s" msgid "Add %s"
msgstr "" msgstr "Προσθήκη %s"
#: contrib/admin/views/main.py:336 #: contrib/admin/views/main.py:336
#, python-format #, python-format
msgid "Added %s." msgid "Added %s."
msgstr "" msgstr "Προστέθηκε %s."
#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338 #: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
#: contrib/admin/views/main.py:340 #: contrib/admin/views/main.py:340
@ -486,32 +493,33 @@ msgstr "και"
#: contrib/admin/views/main.py:338 #: contrib/admin/views/main.py:338
#, python-format #, python-format
msgid "Changed %s." msgid "Changed %s."
msgstr "" msgstr "Επεξεργάσθηκε %s."
#: contrib/admin/views/main.py:340 #: contrib/admin/views/main.py:340
#, python-format #, python-format
msgid "Deleted %s." msgid "Deleted %s."
msgstr "" msgstr "Διεγράφη %s."
#: contrib/admin/views/main.py:343 #: contrib/admin/views/main.py:343
msgid "No fields changed." msgid "No fields changed."
msgstr "" msgstr "Κανένα πεδίο δεν άλλαξε."
#: contrib/admin/views/main.py:346 #: contrib/admin/views/main.py:346
#, python-format #, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully." msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr "" msgstr "Το %(name)s \"%(obj)s\" επεξεργάσθηκε επιτυχώς."
#: contrib/admin/views/main.py:354 #: contrib/admin/views/main.py:354
#, python-format #, python-format
msgid "" msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr "" msgstr ""
"Το %(name)s \"%(obj)s\" αποθηκεύθηκε επιτυχώς. Μπορείτε να το επεξεργαστείτε πάλι παρακάτω."
#: contrib/admin/views/main.py:392 #: contrib/admin/views/main.py:392
#, python-format #, python-format
msgid "Change %s" msgid "Change %s"
msgstr "" msgstr "Αλλαγή %s"
#: contrib/admin/views/main.py:470 #: contrib/admin/views/main.py:470
#, python-format #, python-format
@ -535,17 +543,17 @@ msgstr "Είστε σίγουρος;"
#: contrib/admin/views/main.py:533 #: contrib/admin/views/main.py:533
#, python-format #, python-format
msgid "Change history: %s" msgid "Change history: %s"
msgstr "" msgstr "Ιστορικό Αλλαγών: %s"
#: contrib/admin/views/main.py:565 #: contrib/admin/views/main.py:565
#, python-format #, python-format
msgid "Select %s" msgid "Select %s"
msgstr "" msgstr "Επιλογή %s"
#: contrib/admin/views/main.py:565 #: contrib/admin/views/main.py:565
#, python-format #, python-format
msgid "Select %s to change" msgid "Select %s to change"
msgstr "" msgstr "Επιλέξτε %s προς αλλαγή"
#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286 #: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294 #: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
@ -555,7 +563,7 @@ msgstr "Ακέραιος"
#: contrib/admin/views/doc.py:278 #: contrib/admin/views/doc.py:278
msgid "Boolean (Either True or False)" msgid "Boolean (Either True or False)"
msgstr "Boolean (Είτε Αλήθεια ή Ψέμα)" msgstr "Boolean (Είτε Αληθές ή Ψέυδές)"
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296 #: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
#, python-format #, python-format
@ -580,7 +588,7 @@ msgstr "Ηλεκτρονική διεύθυνση"
#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287 #: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
msgid "File path" msgid "File path"
msgstr "" msgstr "Τοποθεσία Αρχείου"
#: contrib/admin/views/doc.py:285 #: contrib/admin/views/doc.py:285
msgid "Decimal number" msgid "Decimal number"
@ -592,7 +600,7 @@ msgstr ""
#: contrib/admin/views/doc.py:292 #: contrib/admin/views/doc.py:292
msgid "Relation to parent model" msgid "Relation to parent model"
msgstr "" msgstr "Σχέση με το γονεϊκό μοντέλο"
#: contrib/admin/views/doc.py:293 #: contrib/admin/views/doc.py:293
msgid "Phone number" msgid "Phone number"
@ -627,7 +635,7 @@ msgstr ""
#: contrib/admin/templates/registration/password_change_form.html:3 #: contrib/admin/templates/registration/password_change_form.html:3
#: contrib/admin/templates/admin_doc/bookmarklets.html:3 #: contrib/admin/templates/admin_doc/bookmarklets.html:3
msgid "Documentation" msgid "Documentation"
msgstr "" msgstr "Τεκμηρίωση"
#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/change_list.html:5 #: contrib/admin/templates/admin/change_list.html:5
@ -667,11 +675,11 @@ msgstr "Home"
#: contrib/admin/templates/admin/object_history.html:5 #: contrib/admin/templates/admin/object_history.html:5
#: contrib/admin/templates/admin/change_form.html:20 #: contrib/admin/templates/admin/change_form.html:20
msgid "History" msgid "History"
msgstr "" msgstr "Ιστορικό"
#: contrib/admin/templates/admin/object_history.html:18 #: contrib/admin/templates/admin/object_history.html:18
msgid "Date/time" msgid "Date/time"
msgstr "" msgstr "Ημερομηνία/Ώρα"
#: contrib/admin/templates/admin/object_history.html:19 #: contrib/admin/templates/admin/object_history.html:19
msgid "User" msgid "User"
@ -679,7 +687,7 @@ msgstr "Χρήστης"
#: contrib/admin/templates/admin/object_history.html:20 #: contrib/admin/templates/admin/object_history.html:20
msgid "Action" msgid "Action"
msgstr "" msgstr "Δράση"
#: contrib/admin/templates/admin/object_history.html:26 #: contrib/admin/templates/admin/object_history.html:26
msgid "DATE_WITH_TIME_FULL" msgid "DATE_WITH_TIME_FULL"
@ -697,19 +705,19 @@ msgstr "Διαχειριστής ιστοσελίδας Django"
#: contrib/admin/templates/admin/base_site.html:7 #: contrib/admin/templates/admin/base_site.html:7
msgid "Django administration" msgid "Django administration"
msgstr "" msgstr "Διαχείριση Django"
#: contrib/admin/templates/admin/500.html:4 #: contrib/admin/templates/admin/500.html:4
msgid "Server error" msgid "Server error"
msgstr "" msgstr "Σφάλμα Διακομιστή"
#: contrib/admin/templates/admin/500.html:6 #: contrib/admin/templates/admin/500.html:6
msgid "Server error (500)" msgid "Server error (500)"
msgstr "" msgstr "Σφάλμα Διακομιστή (500)"
#: contrib/admin/templates/admin/500.html:9 #: contrib/admin/templates/admin/500.html:9
msgid "Server Error <em>(500)</em>" msgid "Server Error <em>(500)</em>"
msgstr "" msgstr "Σφάλμα Διακομιστή <em>(500)</em>"
#: contrib/admin/templates/admin/500.html:10 #: contrib/admin/templates/admin/500.html:10
msgid "" msgid ""
@ -720,7 +728,7 @@ msgstr ""
#: contrib/admin/templates/admin/404.html:4 #: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8 #: contrib/admin/templates/admin/404.html:8
msgid "Page not found" msgid "Page not found"
msgstr "" msgstr "Η σελίδα δε βρέθηκε."
#: contrib/admin/templates/admin/404.html:10 #: contrib/admin/templates/admin/404.html:10
msgid "We're sorry, but the requested page could not be found." msgid "We're sorry, but the requested page could not be found."
@ -729,24 +737,24 @@ msgstr ""
#: contrib/admin/templates/admin/index.html:17 #: contrib/admin/templates/admin/index.html:17
#, python-format #, python-format
msgid "Models available in the %(name)s application." msgid "Models available in the %(name)s application."
msgstr "" msgstr "Διαθέσιμα μοντέλα στην εφαρμογή %(name)s."
#: contrib/admin/templates/admin/index.html:28 #: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15 #: contrib/admin/templates/admin/change_form.html:15
msgid "Add" msgid "Add"
msgstr "" msgstr "Προσθήκη"
#: contrib/admin/templates/admin/index.html:34 #: contrib/admin/templates/admin/index.html:34
msgid "Change" msgid "Change"
msgstr "" msgstr "Επεξεργασία"
#: contrib/admin/templates/admin/index.html:44 #: contrib/admin/templates/admin/index.html:44
msgid "You don't have permission to edit anything." msgid "You don't have permission to edit anything."
msgstr "" msgstr "Δεν έχετε άδεια να επεξεργαστείτε τίποτα."
#: contrib/admin/templates/admin/index.html:52 #: contrib/admin/templates/admin/index.html:52
msgid "Recent Actions" msgid "Recent Actions"
msgstr "" msgstr "Πρόσφατες Πράξεις"
#: contrib/admin/templates/admin/index.html:53 #: contrib/admin/templates/admin/index.html:53
msgid "My Actions" msgid "My Actions"
@ -754,16 +762,16 @@ msgstr "Οι πράξεις μου"
#: contrib/admin/templates/admin/index.html:57 #: contrib/admin/templates/admin/index.html:57
msgid "None available" msgid "None available"
msgstr "" msgstr "Κανένα διαθέσιμο"
#: contrib/admin/templates/admin/change_list.html:11 #: contrib/admin/templates/admin/change_list.html:11
#, python-format #, python-format
msgid "Add %(name)s" msgid "Add %(name)s"
msgstr "" msgstr "Προσθήκη %(name)s"
#: contrib/admin/templates/admin/login.html:22 #: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?" msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "" msgstr "<a href=\"/password_reset/\">Ξεχάσατε τον κωδικό σας;</a> "
#: contrib/admin/templates/admin/base.html:23 #: contrib/admin/templates/admin/base.html:23
msgid "Welcome," msgid "Welcome,"
@ -772,7 +780,7 @@ msgstr "Καλωσήρθατε,"
#: contrib/admin/templates/admin/delete_confirmation.html:9 #: contrib/admin/templates/admin/delete_confirmation.html:9
#: contrib/admin/templates/admin/submit_line.html:3 #: contrib/admin/templates/admin/submit_line.html:3
msgid "Delete" msgid "Delete"
msgstr "" msgstr "Διαγραφή"
#: contrib/admin/templates/admin/delete_confirmation.html:14 #: contrib/admin/templates/admin/delete_confirmation.html:14
#, python-format #, python-format
@ -800,37 +808,37 @@ msgstr ""
#: contrib/admin/templates/admin/search_form.html:8 #: contrib/admin/templates/admin/search_form.html:8
msgid "Go" msgid "Go"
msgstr "" msgstr "Πήγαινε"
#: contrib/admin/templates/admin/change_form.html:21 #: contrib/admin/templates/admin/change_form.html:21
msgid "View on site" msgid "View on site"
msgstr "" msgstr "Προβολή στην ιστοσελίδα"
#: contrib/admin/templates/admin/change_form.html:30 #: contrib/admin/templates/admin/change_form.html:30
msgid "Please correct the error below." msgid "Please correct the error below."
msgid_plural "Please correct the errors below." msgid_plural "Please correct the errors below."
msgstr[0] "" msgstr[0] "Παρακαλώ διορθώστε το παρακάτω λάθος."
msgstr[1] "" msgstr[1] "Παρακαλώ διορθώστε τα παρακάτω λάθη."
#: contrib/admin/templates/admin/change_form.html:48 #: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering" msgid "Ordering"
msgstr "" msgstr "Σειρά"
#: contrib/admin/templates/admin/change_form.html:51 #: contrib/admin/templates/admin/change_form.html:51
msgid "Order:" msgid "Order:"
msgstr "" msgstr "Σειρά:"
#: contrib/admin/templates/admin/submit_line.html:4 #: contrib/admin/templates/admin/submit_line.html:4
msgid "Save as new" msgid "Save as new"
msgstr "" msgstr "Αποθήκευση καινούριου"
#: contrib/admin/templates/admin/submit_line.html:5 #: contrib/admin/templates/admin/submit_line.html:5
msgid "Save and add another" msgid "Save and add another"
msgstr "" msgstr "Αποθήκευση και προσθήκη καινούριου."
#: contrib/admin/templates/admin/submit_line.html:6 #: contrib/admin/templates/admin/submit_line.html:6
msgid "Save and continue editing" msgid "Save and continue editing"
msgstr "" msgstr "Αποθήκευση και συνέχεια επεξεργασίας"
#: contrib/admin/templates/admin/submit_line.html:7 #: contrib/admin/templates/admin/submit_line.html:7
msgid "Save" msgid "Save"
@ -841,12 +849,12 @@ msgstr "Αποθήκευση"
#: contrib/admin/templates/registration/password_change_form.html:6 #: contrib/admin/templates/registration/password_change_form.html:6
#: contrib/admin/templates/registration/password_change_form.html:10 #: contrib/admin/templates/registration/password_change_form.html:10
msgid "Password change" msgid "Password change"
msgstr "" msgstr "Αλλαγή Κωδικού"
#: contrib/admin/templates/registration/password_change_done.html:6 #: contrib/admin/templates/registration/password_change_done.html:6
#: contrib/admin/templates/registration/password_change_done.html:10 #: contrib/admin/templates/registration/password_change_done.html:10
msgid "Password change successful" msgid "Password change successful"
msgstr "" msgstr "Αλλαγή κωδικού επιτυχής"
#: contrib/admin/templates/registration/password_change_done.html:12 #: contrib/admin/templates/registration/password_change_done.html:12
msgid "Your password was changed." msgid "Your password was changed."
@ -857,7 +865,7 @@ msgstr "Ο κωδίκός σας άλλαξε."
#: contrib/admin/templates/registration/password_reset_form.html:10 #: contrib/admin/templates/registration/password_reset_form.html:10
#: contrib/admin/templates/registration/password_reset_done.html:4 #: contrib/admin/templates/registration/password_reset_done.html:4
msgid "Password reset" msgid "Password reset"
msgstr "" msgstr "Επαναφορά κωδικού"
#: contrib/admin/templates/registration/password_reset_form.html:12 #: contrib/admin/templates/registration/password_reset_form.html:12
msgid "" msgid ""
@ -867,11 +875,11 @@ msgstr ""
#: contrib/admin/templates/registration/password_reset_form.html:16 #: contrib/admin/templates/registration/password_reset_form.html:16
msgid "E-mail address:" msgid "E-mail address:"
msgstr "" msgstr "E-mail διεύθυνση:"
#: contrib/admin/templates/registration/password_reset_form.html:16 #: contrib/admin/templates/registration/password_reset_form.html:16
msgid "Reset my password" msgid "Reset my password"
msgstr "" msgstr "Επαναφορά του κωδικού μου"
#: contrib/admin/templates/registration/logged_out.html:8 #: contrib/admin/templates/registration/logged_out.html:8
msgid "Thanks for spending some quality time with the Web site today." msgid "Thanks for spending some quality time with the Web site today."
@ -880,7 +888,7 @@ msgstr ""
#: contrib/admin/templates/registration/logged_out.html:10 #: contrib/admin/templates/registration/logged_out.html:10
msgid "Log in again" msgid "Log in again"
msgstr "" msgstr "Εισαγωγή ξανά"
#: contrib/admin/templates/registration/password_reset_done.html:6 #: contrib/admin/templates/registration/password_reset_done.html:6
#: contrib/admin/templates/registration/password_reset_done.html:10 #: contrib/admin/templates/registration/password_reset_done.html:10
@ -909,11 +917,11 @@ msgstr "Νέος κωδικός:"
#: contrib/admin/templates/registration/password_change_form.html:21 #: contrib/admin/templates/registration/password_change_form.html:21
msgid "Confirm password:" msgid "Confirm password:"
msgstr "" msgstr "Επιβεβαίωση κωδικού"
#: contrib/admin/templates/registration/password_change_form.html:23 #: contrib/admin/templates/registration/password_change_form.html:23
msgid "Change my password" msgid "Change my password"
msgstr "" msgstr "Αλλαγή του κωδικού μου"
#: contrib/admin/templates/registration/password_reset_email.html:2 #: contrib/admin/templates/registration/password_reset_email.html:2
msgid "You're receiving this e-mail because you requested a password reset" msgid "You're receiving this e-mail because you requested a password reset"
@ -1003,19 +1011,19 @@ msgstr ""
#: contrib/admin/templates/widget/date_time.html:3 #: contrib/admin/templates/widget/date_time.html:3
msgid "Date:" msgid "Date:"
msgstr "" msgstr "Ημ/νία:"
#: contrib/admin/templates/widget/date_time.html:4 #: contrib/admin/templates/widget/date_time.html:4
msgid "Time:" msgid "Time:"
msgstr "" msgstr "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ώρα:"
#: contrib/admin/templates/widget/file.html:2 #: contrib/admin/templates/widget/file.html:2
msgid "Currently:" msgid "Currently:"
msgstr "" msgstr "Τρέχον:"
#: contrib/admin/templates/widget/file.html:3 #: contrib/admin/templates/widget/file.html:3
msgid "Change:" msgid "Change:"
msgstr "" msgstr "Αλλαγή:"
#: contrib/redirects/models.py:7 #: contrib/redirects/models.py:7
msgid "redirect from" msgid "redirect from"
@ -1271,192 +1279,192 @@ msgstr "P"
#: utils/dates.py:6 #: utils/dates.py:6
msgid "Monday" msgid "Monday"
msgstr "" msgstr "Δευτέρα"
#: utils/dates.py:6 #: utils/dates.py:6
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr "Τρίτη"
#: utils/dates.py:6 #: utils/dates.py:6
msgid "Wednesday" msgid "Wednesday"
msgstr "" msgstr "Τετάρτη"
#: utils/dates.py:6 #: utils/dates.py:6
msgid "Thursday" msgid "Thursday"
msgstr "" msgstr "Πέμπτη"
#: utils/dates.py:6 #: utils/dates.py:6
msgid "Friday" msgid "Friday"
msgstr "" msgstr "Παρασκευή"
#: utils/dates.py:7 #: utils/dates.py:7
msgid "Saturday" msgid "Saturday"
msgstr "" msgstr "Σάββατο"
#: utils/dates.py:7 #: utils/dates.py:7
msgid "Sunday" msgid "Sunday"
msgstr "" msgstr "Κυριακή"
#: utils/dates.py:14 #: utils/dates.py:14
msgid "January" msgid "January"
msgstr "" msgstr "Ιανουάριος"
#: utils/dates.py:14 #: utils/dates.py:14
msgid "February" msgid "February"
msgstr "" msgstr "Φεβρουάριος"
#: utils/dates.py:14 utils/dates.py:27 #: utils/dates.py:14 utils/dates.py:27
msgid "March" msgid "March"
msgstr "" msgstr "Μάρτιος"
#: utils/dates.py:14 utils/dates.py:27 #: utils/dates.py:14 utils/dates.py:27
msgid "April" msgid "April"
msgstr "" msgstr "Απρίλιος"
#: utils/dates.py:14 utils/dates.py:27 #: utils/dates.py:14 utils/dates.py:27
msgid "May" msgid "May"
msgstr "" msgstr "Μάιος"
#: utils/dates.py:14 utils/dates.py:27 #: utils/dates.py:14 utils/dates.py:27
msgid "June" msgid "June"
msgstr "" msgstr "Ιούνιος"
#: utils/dates.py:15 utils/dates.py:27 #: utils/dates.py:15 utils/dates.py:27
msgid "July" msgid "July"
msgstr "" msgstr "Ιούλιος"
#: utils/dates.py:15 #: utils/dates.py:15
msgid "August" msgid "August"
msgstr "" msgstr "Αύγουστος"
#: utils/dates.py:15 #: utils/dates.py:15
msgid "September" msgid "September"
msgstr "" msgstr "Σεπτέμβριος"
#: utils/dates.py:15 #: utils/dates.py:15
msgid "October" msgid "October"
msgstr "" msgstr "Οκτώβριος"
#: utils/dates.py:15 #: utils/dates.py:15
msgid "November" msgid "November"
msgstr "" msgstr "Νοέμβριος"
#: utils/dates.py:16 #: utils/dates.py:16
msgid "December" msgid "December"
msgstr "" msgstr "Δεκέμβριος"
#: utils/dates.py:19 #: utils/dates.py:19
#, fuzzy #, fuzzy
msgid "jan" msgid "jan"
msgstr "και" msgstr "Ιαν"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "feb" msgid "feb"
msgstr "" msgstr "Φεβ"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "mar" msgid "mar"
msgstr "" msgstr "Μάρ"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "apr" msgid "apr"
msgstr "" msgstr "Απρ"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "may" msgid "may"
msgstr "" msgstr "Μάι"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "jun" msgid "jun"
msgstr "" msgstr "Ιούν"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "jul" msgid "jul"
msgstr "" msgstr "Ιούλ"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "aug" msgid "aug"
msgstr "" msgstr "Αύγ"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "sep" msgid "sep"
msgstr "" msgstr "Σεπ"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "oct" msgid "oct"
msgstr "" msgstr "Οκτ"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "nov" msgid "nov"
msgstr "" msgstr "Νοέ"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "dec" msgid "dec"
msgstr "" msgstr "Δεκ"
#: utils/dates.py:27 #: utils/dates.py:27
msgid "Jan." msgid "Jan."
msgstr "" msgstr "Ιάν."
#: utils/dates.py:27 #: utils/dates.py:27
msgid "Feb." msgid "Feb."
msgstr "" msgstr "Φεβ."
#: utils/dates.py:28 #: utils/dates.py:28
msgid "Aug." msgid "Aug."
msgstr "" msgstr "Αύγ."
#: utils/dates.py:28 #: utils/dates.py:28
msgid "Sept." msgid "Sept."
msgstr "" msgstr "Σεπτ."
#: utils/dates.py:28 #: utils/dates.py:28
msgid "Oct." msgid "Oct."
msgstr "" msgstr "Οκτ."
#: utils/dates.py:28 #: utils/dates.py:28
msgid "Nov." msgid "Nov."
msgstr "" msgstr "Νοέ."
#: utils/dates.py:28 #: utils/dates.py:28
msgid "Dec." msgid "Dec."
msgstr "" msgstr "Δεκ."
#: utils/timesince.py:12 #: utils/timesince.py:12
msgid "year" msgid "year"
msgid_plural "years" msgid_plural "years"
msgstr[0] "" msgstr[0] "χρόνος"
msgstr[1] "" msgstr[1] "χρόνια"
#: utils/timesince.py:13 #: utils/timesince.py:13
msgid "month" msgid "month"
msgid_plural "months" msgid_plural "months"
msgstr[0] "" msgstr[0] "μήνας"
msgstr[1] "" msgstr[1] "μήνες"
#: utils/timesince.py:14 #: utils/timesince.py:14
msgid "week" msgid "week"
msgid_plural "weeks" msgid_plural "weeks"
msgstr[0] "" msgstr[0] "εβδομάδα"
msgstr[1] "" msgstr[1] "εβδομάδες"
#: utils/timesince.py:15 #: utils/timesince.py:15
msgid "day" msgid "day"
msgid_plural "days" msgid_plural "days"
msgstr[0] "" msgstr[0] "ημέρα"
msgstr[1] "" msgstr[1] "ημέρες"
#: utils/timesince.py:16 #: utils/timesince.py:16
msgid "hour" msgid "hour"
msgid_plural "hours" msgid_plural "hours"
msgstr[0] "" msgstr[0] "ώρα"
msgstr[1] "" msgstr[1] "ώρες"
#: utils/timesince.py:17 #: utils/timesince.py:17
msgid "minute" msgid "minute"
msgid_plural "minutes" msgid_plural "minutes"
msgstr[0] "" msgstr[0] "λεπτό"
msgstr[1] "" msgstr[1] "λεπτά"
#: conf/global_settings.py:37 #: conf/global_settings.py:37
msgid "Bengali" msgid "Bengali"
@ -1630,7 +1638,7 @@ msgstr ""
#: core/validators.py:136 #: core/validators.py:136
msgid "Enter a valid e-mail address." msgid "Enter a valid e-mail address."
msgstr "" msgstr "Εισάγετε ένα σωστό e-mail."
#: core/validators.py:148 #: core/validators.py:148
msgid "" msgid ""
@ -1745,12 +1753,12 @@ msgstr[1] ""
#: core/validators.py:362 #: core/validators.py:362
#, python-format #, python-format
msgid "Make sure your uploaded file is at least %s bytes big." msgid "Make sure your uploaded file is at least %s bytes big."
msgstr "Σιγουρευτείτε ότι το αρχείου που ανεβάζετε είναι %s bytes τουλάχιστον." msgstr "Σιγουρευτείτε ότι το αρχείο που ανεβάζετε είναι %s bytes τουλάχιστον."
#: core/validators.py:363 #: core/validators.py:363
#, python-format #, python-format
msgid "Make sure your uploaded file is at most %s bytes big." msgid "Make sure your uploaded file is at most %s bytes big."
msgstr "" msgstr "Σιγουρευτείτε ότι το αρχείο που ανεβάζετε έχει μέγεθος μέχρι %s bytes."
#: core/validators.py:376 #: core/validators.py:376
msgid "The format for this field is wrong." msgid "The format for this field is wrong."
@ -1827,7 +1835,7 @@ msgstr ""
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553 #: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
#: forms/__init__.py:346 #: forms/__init__.py:346
msgid "This field is required." msgid "This field is required."
msgstr "" msgstr "Αυτό το πεδίο είναι απαραίτητο"
#: db/models/fields/__init__.py:337 #: db/models/fields/__init__.py:337
msgid "This value must be an integer." msgid "This value must be an integer."
@ -1836,12 +1844,12 @@ msgstr ""
#: db/models/fields/__init__.py:369 #: db/models/fields/__init__.py:369
#, fuzzy #, fuzzy
msgid "This value must be either True or False." msgid "This value must be either True or False."
msgstr "Boolean (Είτε Αλήθεια ή Ψέμα)" msgstr "Boolean (Είτε Αληθές ή Ψευδές)"
#: db/models/fields/__init__.py:385 #: db/models/fields/__init__.py:385
#, fuzzy #, fuzzy
msgid "This field cannot be null." msgid "This field cannot be null."
msgstr "Αυτό το πεδίο είναι άκυρο" msgstr "Αυτό το πεδίο δεν μπορεί να είναι κενό (null)"
#: db/models/fields/__init__.py:562 #: db/models/fields/__init__.py:562
msgid "Enter a valid filename." msgid "Enter a valid filename."
@ -1850,7 +1858,7 @@ msgstr "Εισάγετε ένα έγκυρο όνομα αρχείου"
#: db/models/fields/related.py:43 #: db/models/fields/related.py:43
#, python-format #, python-format
msgid "Please enter a valid %s." msgid "Please enter a valid %s."
msgstr "" msgstr "Παρακαλώ εισάγετε ένα/μία έγκυρο/η %s"
#: db/models/fields/related.py:579 #: db/models/fields/related.py:579
#, fuzzy #, fuzzy

Binary file not shown.

View File

@ -0,0 +1,109 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2006 and beyond.
# This file is distributed under the same license as the Django package.
# Orestis Markou <orestis@orestis.gr>, 2006.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Orestis Markou <orestis@orestis.gr>\n"
"Language-Team: Greek\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 π.μ."
#: 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 "Αύριο"

View File

@ -8,8 +8,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: django\n" "Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-08-18 18:57-0300\n" "POT-Creation-Date: 2006-11-05 19:57-0300\n"
"PO-Revision-Date: 2006-08-21 18:06-0300\n" "PO-Revision-Date: 2006-11-05 20:00-0300\n"
"Last-Translator: Ramiro Morales <rm0@gmx.net>\n" "Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
"Language-Team: Spanish <es@li.org>\n" "Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -165,10 +165,18 @@ msgstr "Fechas importantes"
msgid "Groups" msgid "Groups"
msgstr "Grupos" msgstr "Grupos"
#: contrib/auth/models.py:256 #: contrib/auth/models.py:258
msgid "message" msgid "message"
msgstr "mensaje" msgstr "mensaje"
#: contrib/auth/forms.py:16
msgid "The two password fields didn't match."
msgstr "Los dos campos de contraseñas no coinciden entre si."
#: contrib/auth/forms.py:24
msgid "A user with that username already exists."
msgstr "Ya existe un usuario con ese nombre."
#: contrib/auth/forms.py:52 #: contrib/auth/forms.py:52
msgid "" msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are " "Your Web browser doesn't appear to have cookies enabled. Cookies are "
@ -189,6 +197,24 @@ msgstr ""
msgid "This account is inactive." msgid "This account is inactive."
msgstr "Esta cuenta está inactiva" msgstr "Esta cuenta está inactiva"
#: contrib/auth/forms.py:84
msgid ""
"That e-mail address doesn't have an associated user account. Are you sure "
"you've registered?"
msgstr ""
"Esa dirección de e-mail no está asociada a ninguna cuenta de usuario. ¿Está "
"seguro de que ya se ha registrado?"
#: contrib/auth/forms.py:116
msgid "The two 'new password' fields didn't match."
msgstr "Los dos campos 'nueva contraseña' no coinciden entre si."
#: contrib/auth/forms.py:123
msgid "Your old password was entered incorrectly. Please enter it again."
msgstr ""
"La antigua contraseña ingresada es incorrecta. Por favor ingrésela "
"nuevamente."
#: contrib/redirects/models.py:7 #: contrib/redirects/models.py:7
msgid "redirect from" msgid "redirect from"
msgstr "redirigir desde" msgstr "redirigir desde"
@ -754,13 +780,13 @@ msgstr ""
msgid "Site administration" msgid "Site administration"
msgstr "Sitio administrativo" msgstr "Sitio administrativo"
#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:14 #: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:18
#, python-format #, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully." msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "Se agregó con éxito el %(name)s \"%(obj)s\"." msgstr "Se agregó con éxito %(name)s \"%(obj)s\"."
#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347 #: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347
#: contrib/admin/views/auth.py:19 #: contrib/admin/views/auth.py:23
msgid "You may edit it again below." msgid "You may edit it again below."
msgstr "Puede modificarlo nuevamente abajo." msgstr "Puede modificarlo nuevamente abajo."
@ -780,7 +806,7 @@ msgid "Added %s."
msgstr "Agregado %s." msgstr "Agregado %s."
#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337 #: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
#: contrib/admin/views/main.py:339 #: contrib/admin/views/main.py:339 db/models/manipulators.py:306
msgid "and" msgid "and"
msgstr "y" msgstr "y"
@ -801,15 +827,14 @@ msgstr "No ha modificado ning
#: contrib/admin/views/main.py:345 #: contrib/admin/views/main.py:345
#, python-format #, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully." msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr "Se modificó con éxito el %(name)s \"%(obj)s." msgstr "Se modificó con éxito %(name)s \"%(obj)s."
#: contrib/admin/views/main.py:353 #: contrib/admin/views/main.py:353
#, python-format #, python-format
msgid "" msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr "" msgstr ""
"Se agregó con éxito el %(name)s \"%(obj)s. Puede modificarlo nuevamente " "Se agregó con éxito %(name)s \"%(obj)s. Puede modificarlo nuevamente abajo."
"abajo."
#: contrib/admin/views/main.py:391 #: contrib/admin/views/main.py:391
#, python-format #, python-format
@ -829,7 +854,7 @@ msgstr "Uno o m
#: contrib/admin/views/main.py:511 #: contrib/admin/views/main.py:511
#, python-format #, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "Se eliminó con éxito el %(name)s \"%(obj)s\"." msgstr "Se eliminó con éxito %(name)s \"%(obj)s\"."
#: contrib/admin/views/main.py:514 #: contrib/admin/views/main.py:514
msgid "Are you sure?" msgid "Are you sure?"
@ -850,7 +875,7 @@ msgstr "Seleccione %s"
msgid "Select %s to change" msgid "Select %s to change"
msgstr "Seleccione %s a modificar" msgstr "Seleccione %s a modificar"
#: contrib/admin/views/main.py:756 #: contrib/admin/views/main.py:758
msgid "Database error" msgid "Database error"
msgstr "Error de base de datos" msgstr "Error de base de datos"
@ -977,12 +1002,12 @@ msgstr "Estado de los EEUU (dos letras may
msgid "XML text" msgid "XML text"
msgstr "Texto XML" msgstr "Texto XML"
#: contrib/admin/views/doc.py:339 #: contrib/admin/views/doc.py:343
#, python-format #, python-format
msgid "%s does not appear to be a urlpattern object" msgid "%s does not appear to be a urlpattern object"
msgstr "%s no parece ser un objeto urlpattern" msgstr "%s no parece ser un objeto urlpattern"
#: contrib/admin/views/auth.py:25 #: contrib/admin/views/auth.py:29
msgid "Add user" msgid "Add user"
msgstr "Agregar usuario" msgstr "Agregar usuario"
@ -1181,10 +1206,6 @@ msgstr "P
msgid "We're sorry, but the requested page could not be found." msgid "We're sorry, but the requested page could not be found."
msgstr "Lo sentimos, pero no se encuentra la página solicitada." msgstr "Lo sentimos, pero no se encuentra la página solicitada."
#: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "¿Ha <a href=\"/password_reset/\">olvidado su contraseña</a>?"
#: contrib/admin/templates/admin/filters.html:4 #: contrib/admin/templates/admin/filters.html:4
msgid "Filter" msgid "Filter"
msgstr "Filtrar" msgstr "Filtrar"
@ -1726,123 +1747,134 @@ msgid "Argentinean Spanish"
msgstr "Español Argentino" msgstr "Español Argentino"
#: conf/global_settings.py:49 #: conf/global_settings.py:49
msgid "Finnish"
msgstr "Finlandés"
#: conf/global_settings.py:50
msgid "French" msgid "French"
msgstr "Francés" msgstr "Francés"
#: conf/global_settings.py:50 #: conf/global_settings.py:51
msgid "Galician" msgid "Galician"
msgstr "Gallego" msgstr "Gallego"
#: conf/global_settings.py:51 #: conf/global_settings.py:52
msgid "Hungarian" msgid "Hungarian"
msgstr "Húngaro" msgstr "Húngaro"
#: conf/global_settings.py:52 #: conf/global_settings.py:53
msgid "Hebrew" msgid "Hebrew"
msgstr "Hebreo" msgstr "Hebreo"
#: conf/global_settings.py:53 #: conf/global_settings.py:54
msgid "Icelandic" msgid "Icelandic"
msgstr "Islandés" msgstr "Islandés"
#: conf/global_settings.py:54 #: conf/global_settings.py:55
msgid "Italian" msgid "Italian"
msgstr "Italiano" msgstr "Italiano"
#: conf/global_settings.py:55 #: conf/global_settings.py:56
msgid "Japanese" msgid "Japanese"
msgstr "Japonés" msgstr "Japonés"
#: conf/global_settings.py:56 #: conf/global_settings.py:57
msgid "Dutch" msgid "Dutch"
msgstr "Holandés" msgstr "Holandés"
#: conf/global_settings.py:57 #: conf/global_settings.py:58
msgid "Norwegian" msgid "Norwegian"
msgstr "Noruego" msgstr "Noruego"
#: conf/global_settings.py:58 #: conf/global_settings.py:59
msgid "Polish"
msgstr "Polaco"
#: conf/global_settings.py:60
msgid "Brazilian" msgid "Brazilian"
msgstr "Brasileño" msgstr "Brasileño"
#: conf/global_settings.py:59 #: conf/global_settings.py:61
msgid "Romanian" msgid "Romanian"
msgstr "Rumano" msgstr "Rumano"
#: conf/global_settings.py:60 #: conf/global_settings.py:62
msgid "Russian" msgid "Russian"
msgstr "Ruso" msgstr "Ruso"
#: conf/global_settings.py:61 #: conf/global_settings.py:63
msgid "Slovak" msgid "Slovak"
msgstr "Eslovaco" msgstr "Eslovaco"
#: conf/global_settings.py:62 #: conf/global_settings.py:64
msgid "Slovenian" msgid "Slovenian"
msgstr "Esloveno" msgstr "Esloveno"
#: conf/global_settings.py:63 #: conf/global_settings.py:65
msgid "Serbian" msgid "Serbian"
msgstr "Serbio" msgstr "Serbio"
#: conf/global_settings.py:64 #: conf/global_settings.py:66
msgid "Swedish" msgid "Swedish"
msgstr "Sueco" msgstr "Sueco"
#: conf/global_settings.py:65 #: conf/global_settings.py:67
msgid "Tamil" msgid "Tamil"
msgstr "Tamil" msgstr "Tamil"
#: conf/global_settings.py:66 #: conf/global_settings.py:68
msgid "Turkish"
msgstr "Turco"
#: conf/global_settings.py:69
msgid "Ukrainian" msgid "Ukrainian"
msgstr "Ucraniano" msgstr "Ucraniano"
#: conf/global_settings.py:67 #: conf/global_settings.py:70
msgid "Simplified Chinese" msgid "Simplified Chinese"
msgstr "Chino simplificado" msgstr "Chino simplificado"
#: conf/global_settings.py:68 #: conf/global_settings.py:71
msgid "Traditional Chinese" msgid "Traditional Chinese"
msgstr "Chino tradicional" msgstr "Chino tradicional"
#: db/models/manipulators.py:302 #: db/models/manipulators.py:305
#, python-format #, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s." msgid "%(object)s with this %(type)s already exists for the given %(field)s."
msgstr "" msgstr "Ya existe un(a) %(object)s con este/a %(type)s para %(field)s."
"Ya existen %(object)s con este %(type)s para el %(field)s especificado."
#: db/models/fields/__init__.py:40 #: db/models/fields/__init__.py:41
#, python-format #, python-format
msgid "%(optname)s with this %(fieldname)s already exists." msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "Ya existe %(optname)s con este %(fieldname)s." msgstr "Ya existe %(optname)s con este %(fieldname)s."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 #: db/models/fields/__init__.py:115 db/models/fields/__init__.py:266
#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562 #: db/models/fields/__init__.py:569 db/models/fields/__init__.py:580
#: forms/__init__.py:346 #: forms/__init__.py:347
msgid "This field is required." msgid "This field is required."
msgstr "Este campo es obligatorio." msgstr "Este campo es obligatorio."
#: db/models/fields/__init__.py:340 #: db/models/fields/__init__.py:349
msgid "This value must be an integer." msgid "This value must be an integer."
msgstr "Este valor debe ser un número entero." msgstr "Este valor debe ser un número entero."
#: db/models/fields/__init__.py:372 #: db/models/fields/__init__.py:381
msgid "This value must be either True or False." msgid "This value must be either True or False."
msgstr "Este valor debe ser True o False." msgstr "Este valor debe ser True o False."
#: db/models/fields/__init__.py:388 #: db/models/fields/__init__.py:397
msgid "This field cannot be null." msgid "This field cannot be null."
msgstr "Este campo no puede ser nulo." msgstr "Este campo no puede ser nulo."
#: db/models/fields/__init__.py:415 core/validators.py:127 #: db/models/fields/__init__.py:424 core/validators.py:146
msgid "Enter a valid date in YYYY-MM-DD format." msgid "Enter a valid date in YYYY-MM-DD format."
msgstr "Introduzca una fecha válida en formato AAAA-MM-DD." msgstr "Introduzca una fecha válida en formato AAAA-MM-DD."
#: db/models/fields/__init__.py:477 core/validators.py:135 #: db/models/fields/__init__.py:488 core/validators.py:155
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr "Introduzca una fecha/hora válida en formato YYYY-MM-DD HH:MM." msgstr "Introduzca una fecha/hora válida en formato YYYY-MM-DD HH:MM."
#: db/models/fields/__init__.py:571 #: db/models/fields/__init__.py:589
msgid "Enter a valid filename." msgid "Enter a valid filename."
msgstr "Introduzca un nombre de achivo válido" msgstr "Introduzca un nombre de achivo válido"
@ -1859,7 +1891,8 @@ msgstr " Separe m
msgid "" msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr "" msgstr ""
"Pulse \"Control\", o \"Command\" en un Mac, para seleccionar más de uno." "Mantenga presionada \"Control\" (\"Command\" en un Mac) para seleccionar más "
"de uno."
#: db/models/fields/related.py:664 #: db/models/fields/related.py:664
#, python-format #, python-format
@ -1873,42 +1906,42 @@ msgstr[1] ""
"Por favor, introduzca IDs de %(self)s válidos. Los valores %(value)r no son " "Por favor, introduzca IDs de %(self)s válidos. Los valores %(value)r no son "
"válidos." "válidos."
#: forms/__init__.py:381 #: forms/__init__.py:382
#, python-format #, python-format
msgid "Ensure your text is less than %s character." msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters." msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Asegúrese de que su texto tiene menos de %s carácter." msgstr[0] "Asegúrese de que su texto tiene menos de %s carácter."
msgstr[1] "Asegúrese de que su texto tiene menos de %s caracteres." msgstr[1] "Asegúrese de que su texto tiene menos de %s caracteres."
#: forms/__init__.py:386 #: forms/__init__.py:387
msgid "Line breaks are not allowed here." msgid "Line breaks are not allowed here."
msgstr "No se permiten saltos de línea." msgstr "No se permiten saltos de línea."
#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599 #: forms/__init__.py:488 forms/__init__.py:561 forms/__init__.py:600
#, python-format #, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s." msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "Seleccione una opción válida; '%(data)s' no está en %(choices)s." msgstr "Seleccione una opción válida; '%(data)s' no está en %(choices)s."
#: forms/__init__.py:661 core/validators.py:151 core/validators.py:379 #: forms/__init__.py:662 core/validators.py:172 core/validators.py:401
msgid "No file was submitted. Check the encoding type on the form." msgid "No file was submitted. Check the encoding type on the form."
msgstr "" msgstr ""
"No se envió un archivo. Verifique el tipo de codificación en el formulario." "No se envió un archivo. Verifique el tipo de codificación en el formulario."
#: forms/__init__.py:663 #: forms/__init__.py:664
msgid "The submitted file is empty." msgid "The submitted file is empty."
msgstr "El archivo enviado está vacío." msgstr "El archivo enviado está vacío."
#: forms/__init__.py:719 #: forms/__init__.py:720
msgid "Enter a whole number between -32,768 and 32,767." msgid "Enter a whole number between -32,768 and 32,767."
msgstr "Introduzca un número entero entre -32,768 y 32,767." msgstr "Introduzca un número entero entre -32.768 y 32.767."
#: forms/__init__.py:729 #: forms/__init__.py:730
msgid "Enter a positive number." msgid "Enter a positive number."
msgstr "Introduzca un número positivo." msgstr "Introduzca un número positivo."
#: forms/__init__.py:739 #: forms/__init__.py:740
msgid "Enter a whole number between 0 and 32,767." msgid "Enter a whole number between 0 and 32,767."
msgstr "Introduzca un número entero entre 0 y 32,767." msgstr "Introduzca un número entero entre 0 y 32.767."
#: core/validators.py:63 #: core/validators.py:63
msgid "This value must contain only letters, numbers and underscores." msgid "This value must contain only letters, numbers and underscores."
@ -1919,8 +1952,13 @@ msgid ""
"This value must contain only letters, numbers, underscores, dashes or " "This value must contain only letters, numbers, underscores, dashes or "
"slashes." "slashes."
msgstr "" msgstr ""
"Este valor debe contener sólo letras, números, guiones bajos, barras (/) o " "Este valor debe contener sólo letras, números, guiones bajos, guiones o "
"slashes." "barras (/)"
#: core/validators.py:71
msgid "This value must contain only letters, numbers, underscores or hyphens."
msgstr ""
"Este valor debe contener sólo letras, números, guiones bajos o guiones."
#: core/validators.py:75 #: core/validators.py:75
msgid "Uppercase letters are not allowed here." msgid "Uppercase letters are not allowed here."
@ -1962,15 +2000,24 @@ msgstr "Introduzca un n
msgid "Only alphabetical characters are allowed here." msgid "Only alphabetical characters are allowed here."
msgstr "Sólo se admiten caracteres alfabéticos." msgstr "Sólo se admiten caracteres alfabéticos."
#: core/validators.py:131 #: core/validators.py:138
msgid "Year must be 1900 or later."
msgstr "El año debe ser 1900 o posterior."
#: core/validators.py:142
#, python-format
msgid "Invalid date: %s."
msgstr "Fecha no válida: %s."
#: core/validators.py:151
msgid "Enter a valid time in HH:MM format." msgid "Enter a valid time in HH:MM format."
msgstr "Introduzca una hora válida en formato HH:MM." msgstr "Introduzca una hora válida en formato HH:MM."
#: core/validators.py:139 #: core/validators.py:160
msgid "Enter a valid e-mail address." msgid "Enter a valid e-mail address."
msgstr "Introduzca una dirección de correo electrónico válida" msgstr "Introduzca una dirección de correo electrónico válida"
#: core/validators.py:155 #: core/validators.py:176
msgid "" msgid ""
"Upload a valid image. The file you uploaded was either not an image or a " "Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image." "corrupted image."
@ -1978,28 +2025,28 @@ msgstr ""
"Envíe una imagen válida. El archivo que ha enviado no era una imagen o se " "Envíe una imagen válida. El archivo que ha enviado no era una imagen o se "
"trataba de una imagen corrupta." "trataba de una imagen corrupta."
#: core/validators.py:162 #: core/validators.py:183
#, python-format #, python-format
msgid "The URL %s does not point to a valid image." msgid "The URL %s does not point to a valid image."
msgstr "La URL %s no apunta a una imagen válida." msgstr "La URL %s no apunta a una imagen válida."
#: core/validators.py:166 #: core/validators.py:187
#, python-format #, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr "" msgstr ""
"Los números de teléfono deben guardar el formato XXX-XXX-XXXX format. \"%s\" " "Los números telefónicos deben respetar el formato XXX-XXX-XXXX. \"%s\" no es "
"no es válido." "válido."
#: core/validators.py:174 #: core/validators.py:195
#, python-format #, python-format
msgid "The URL %s does not point to a valid QuickTime video." msgid "The URL %s does not point to a valid QuickTime video."
msgstr "La URL %s no apunta a un vídeo QuickTime válido." msgstr "La URL %s no apunta a un vídeo QuickTime válido."
#: core/validators.py:178 #: core/validators.py:199
msgid "A valid URL is required." msgid "A valid URL is required."
msgstr "Se precisa una URL válida." msgstr "Se precisa una URL válida."
#: core/validators.py:192 #: core/validators.py:213
#, python-format #, python-format
msgid "" msgid ""
"Valid HTML is required. Specific errors are:\n" "Valid HTML is required. Specific errors are:\n"
@ -2008,69 +2055,69 @@ msgstr ""
"Se precisa HTML válido. Los errores específicos son:\n" "Se precisa HTML válido. Los errores específicos son:\n"
"%s" "%s"
#: core/validators.py:199 #: core/validators.py:220
#, python-format #, python-format
msgid "Badly formed XML: %s" msgid "Badly formed XML: %s"
msgstr "XML mal formado: %s" msgstr "XML mal formado: %s"
#: core/validators.py:209 #: core/validators.py:230
#, python-format #, python-format
msgid "Invalid URL: %s" msgid "Invalid URL: %s"
msgstr "URL no válida: %s" msgstr "URL no válida: %s"
#: core/validators.py:213 core/validators.py:215 #: core/validators.py:234 core/validators.py:236
#, python-format #, python-format
msgid "The URL %s is a broken link." msgid "The URL %s is a broken link."
msgstr "La URL %s es un enlace roto." msgstr "La URL %s es un enlace roto."
#: core/validators.py:221 #: core/validators.py:242
msgid "Enter a valid U.S. state abbreviation." msgid "Enter a valid U.S. state abbreviation."
msgstr "Introduzca una abreviatura válida de estado de los EEUU." msgstr "Introduzca una abreviatura válida de estado de los EEUU."
#: core/validators.py:236 #: core/validators.py:256
#, python-format #, python-format
msgid "Watch your mouth! The word %s is not allowed here." msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "¡Vigila tu boca! Aquí no admitimos la palabra %s." msgstr[0] "¡Vigila tu boca! Aquí no admitimos la palabra %s."
msgstr[1] "¡Vigila tu boca! Aquí no admitimos las palabras %s." msgstr[1] "¡Vigila tu boca! Aquí no admitimos las palabras %s."
#: core/validators.py:243 #: core/validators.py:263
#, python-format #, python-format
msgid "This field must match the '%s' field." msgid "This field must match the '%s' field."
msgstr "Este campo debe concordar con el campo '%s'." msgstr "Este campo debe concordar con el campo '%s'."
#: core/validators.py:262 #: core/validators.py:282
msgid "Please enter something for at least one field." msgid "Please enter something for at least one field."
msgstr "Por favor, introduzca algo en al menos un campo." msgstr "Por favor, introduzca algo en al menos un campo."
#: core/validators.py:271 core/validators.py:282 #: core/validators.py:291 core/validators.py:302
msgid "Please enter both fields or leave them both empty." msgid "Please enter both fields or leave them both empty."
msgstr "Por favor, rellene ambos campos o deje ambos vacíos." msgstr "Por favor, rellene ambos campos o deje ambos vacíos."
#: core/validators.py:289 #: core/validators.py:309
#, python-format #, python-format
msgid "This field must be given if %(field)s is %(value)s" msgid "This field must be given if %(field)s is %(value)s"
msgstr "Se debe proporcionar este campo si %(field)s es %(value)s" msgstr "Se debe proporcionar este campo si %(field)s es %(value)s"
#: core/validators.py:301 #: core/validators.py:321
#, python-format #, python-format
msgid "This field must be given if %(field)s is not %(value)s" msgid "This field must be given if %(field)s is not %(value)s"
msgstr "Se debe proporcionar este campo si %(field)s no es %(value)s" msgstr "Se debe proporcionar este campo si %(field)s no es %(value)s"
#: core/validators.py:320 #: core/validators.py:340
msgid "Duplicate values are not allowed." msgid "Duplicate values are not allowed."
msgstr "No se admiten valores duplicados." msgstr "No se admiten valores duplicados."
#: core/validators.py:343 #: core/validators.py:363
#, python-format #, python-format
msgid "This value must be a power of %s." msgid "This value must be a power of %s."
msgstr "Este valor debe ser una potencia de %s." msgstr "Este valor debe ser una potencia de %s."
#: core/validators.py:354 #: core/validators.py:374
msgid "Please enter a valid decimal number." msgid "Please enter a valid decimal number."
msgstr "Por favor, introduzca un número decimal válido." msgstr "Por favor, introduzca un número decimal válido."
#: core/validators.py:356 #: core/validators.py:378
#, python-format #, python-format
msgid "Please enter a valid decimal number with at most %s total digit." msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural "" msgid_plural ""
@ -2082,7 +2129,7 @@ msgstr[1] ""
"Por favor, introduzca un número decimal válido con un maximo de %s dígitos " "Por favor, introduzca un número decimal válido con un maximo de %s dígitos "
"en total." "en total."
#: core/validators.py:359 #: core/validators.py:381
#, python-format #, python-format
msgid "" msgid ""
"Please enter a valid decimal number with a whole part of at most %s digit." "Please enter a valid decimal number with a whole part of at most %s digit."
@ -2095,7 +2142,7 @@ msgstr[1] ""
"Por favor, introduzca un número decimal válido con un máximo de %s dígitos " "Por favor, introduzca un número decimal válido con un máximo de %s dígitos "
"enteros." "enteros."
#: core/validators.py:362 #: core/validators.py:384
#, python-format #, python-format
msgid "Please enter a valid decimal number with at most %s decimal place." msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural "" msgid_plural ""
@ -2107,30 +2154,30 @@ msgstr[1] ""
"Por favor, introduzca un número decimal válido con un máximo de %s " "Por favor, introduzca un número decimal válido con un máximo de %s "
"posiciones decimales." "posiciones decimales."
#: core/validators.py:372 #: core/validators.py:394
#, python-format #, python-format
msgid "Make sure your uploaded file is at least %s bytes big." msgid "Make sure your uploaded file is at least %s bytes big."
msgstr "Asegúrese de que el archivo que envía tiene al menos %s bytes." msgstr "Asegúrese de que el archivo que envía tiene al menos %s bytes."
#: core/validators.py:373 #: core/validators.py:395
#, python-format #, python-format
msgid "Make sure your uploaded file is at most %s bytes big." msgid "Make sure your uploaded file is at most %s bytes big."
msgstr "Asegúrese de que el archivo que envía tiene como máximo %s bytes." msgstr "Asegúrese de que el archivo que envía tiene como máximo %s bytes."
#: core/validators.py:390 #: core/validators.py:412
msgid "The format for this field is wrong." msgid "The format for this field is wrong."
msgstr "El formato de este campo es incorrecto." msgstr "El formato de este campo es incorrecto."
#: core/validators.py:405 #: core/validators.py:427
msgid "This field is invalid." msgid "This field is invalid."
msgstr "Este campo no es válido." msgstr "Este campo no es válido."
#: core/validators.py:441 #: core/validators.py:463
#, python-format #, python-format
msgid "Could not retrieve anything from %s." msgid "Could not retrieve anything from %s."
msgstr "No pude obtener nada de %s." msgstr "No pude obtener nada de %s."
#: core/validators.py:444 #: core/validators.py:466
#, python-format #, python-format
msgid "" msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
@ -2138,7 +2185,7 @@ msgstr ""
"La URL %(url)s devolvió la cabecera Content-Type '%(contenttype)s', que no " "La URL %(url)s devolvió la cabecera Content-Type '%(contenttype)s', que no "
"es válida." "es válida."
#: core/validators.py:477 #: core/validators.py:499
#, python-format #, python-format
msgid "" msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
@ -2147,7 +2194,7 @@ msgstr ""
"Por favor, cierre la etiqueta %(tag)s de la línea %(line)s. (La línea " "Por favor, cierre la etiqueta %(tag)s de la línea %(line)s. (La línea "
"empieza por \"%(start)s\".)" "empieza por \"%(start)s\".)"
#: core/validators.py:481 #: core/validators.py:503
#, python-format #, python-format
msgid "" msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line " "Some text starting on line %(line)s is not allowed in that context. (Line "
@ -2156,7 +2203,7 @@ msgstr ""
"Parte del texto que comienza en la línea %(line)s no está permitido en ese " "Parte del texto que comienza en la línea %(line)s no está permitido en ese "
"contexto. (La línea empieza por \"%(start)s\".)" "contexto. (La línea empieza por \"%(start)s\".)"
#: core/validators.py:486 #: core/validators.py:508
#, python-format #, python-format
msgid "" msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
@ -2165,7 +2212,7 @@ msgstr ""
"El \"%(attr)s\" de la línea %(line)s no es un atributo válido. (La línea " "El \"%(attr)s\" de la línea %(line)s no es un atributo válido. (La línea "
"empieza por \"%(start)s\".)" "empieza por \"%(start)s\".)"
#: core/validators.py:491 #: core/validators.py:513
#, python-format #, python-format
msgid "" msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
@ -2174,7 +2221,7 @@ msgstr ""
"La \"<%(tag)s>\" de la línea %(line)s no es una etiqueta válida. (La línea " "La \"<%(tag)s>\" de la línea %(line)s no es una etiqueta válida. (La línea "
"empieza por \"%(start)s\".)" "empieza por \"%(start)s\".)"
#: core/validators.py:495 #: core/validators.py:517
#, python-format #, python-format
msgid "" msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line " "A tag on line %(line)s is missing one or more required attributes. (Line "
@ -2183,7 +2230,7 @@ msgstr ""
"A una etiqueta de la línea %(line)s le faltan uno o más atributos " "A una etiqueta de la línea %(line)s le faltan uno o más atributos "
"requeridos. (La línea empieza por \"%(start)s\".)" "requeridos. (La línea empieza por \"%(start)s\".)"
#: core/validators.py:500 #: core/validators.py:522
#, python-format #, python-format
msgid "" msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
@ -2199,17 +2246,20 @@ msgstr "si,no,tal vez"
#: views/generic/create_update.py:43 #: views/generic/create_update.py:43
#, python-format #, python-format
msgid "The %(verbose_name)s was created successfully." msgid "The %(verbose_name)s was created successfully."
msgstr "Se creó con éxito el %(verbose_name)." msgstr "Se creó con éxito %(verbose_name)."
#: views/generic/create_update.py:117 #: views/generic/create_update.py:117
#, python-format #, python-format
msgid "The %(verbose_name)s was updated successfully." msgid "The %(verbose_name)s was updated successfully."
msgstr "Se actualizó con éxito el %(verbose_name)s." msgstr "Se actualizó con éxito %(verbose_name)s."
#: views/generic/create_update.py:184 #: views/generic/create_update.py:184
#, python-format #, python-format
msgid "The %(verbose_name)s was deleted." msgid "The %(verbose_name)s was deleted."
msgstr "Se eliminó el %(verbose_name)s." msgstr "Se eliminó %(verbose_name)s."
#~ msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
#~ msgstr "¿Ha <a href=\"/password_reset/\">olvidado su contraseña</a>?"
#~ msgid "%(content_type_name)s" #~ msgid "%(content_type_name)s"
#~ msgstr "tipos de contenido" #~ msgstr "tipos de contenido"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django JavaScript 1.0\n" "Project-Id-Version: Django JavaScript 1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-06-19 12:15-0300\n" "POT-Creation-Date: 2006-09-25 15:09-0300\n"
"PO-Revision-Date: 2006-05-16 10:20-0300\n" "PO-Revision-Date: 2006-05-16 10:20-0300\n"
"Last-Translator: Ramiro Morales <rm0@gmx.net>\n" "Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -39,7 +39,7 @@ msgstr "%s elegidos"
#: contrib/admin/media/js/SelectFilter2.js:54 #: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click " msgid "Select your choice(s) and click "
msgstr "Haga sus elecciones y haga click en " msgstr "Seleccione los items a agregar y haga click en "
#: contrib/admin/media/js/SelectFilter2.js:59 #: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all" msgid "Clear all"
@ -51,7 +51,7 @@ msgid ""
"January February March April May June July August September October November " "January February March April May June July August September October November "
"December" "December"
msgstr "" msgstr ""
"Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre " "Enero Febrero Marzo Abril Mayo Junio Julio Agosto Setiembre Octubre "
"Noviembre Diciembre" "Noviembre Diciembre"
#: contrib/admin/media/js/dateparse.js:33 #: contrib/admin/media/js/dateparse.js:33
@ -71,49 +71,49 @@ msgstr "Mostrar"
msgid "Hide" msgid "Hide"
msgstr "Ocultar" msgstr "Ocultar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:89 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now" msgid "Now"
msgstr "Ahora" msgstr "Ahora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock" msgid "Clock"
msgstr "Reloj" msgstr "Reloj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:86 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time" msgid "Choose a time"
msgstr "Elija una hora" msgstr "Elija una hora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:90 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight" msgid "Midnight"
msgstr "Medianoche" msgstr "Medianoche"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:91 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m." msgid "6 a.m."
msgstr "6 a.m." msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:92 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon" msgid "Noon"
msgstr "Mediodía" msgstr "Mediodía"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:96 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:187 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:120 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:181 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today" msgid "Today"
msgstr "Hoy" msgstr "Hoy"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:123 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar" msgid "Calendar"
msgstr "Calendario" msgstr "Calendario"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday" msgid "Yesterday"
msgstr "Ayer" msgstr "Ayer"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow" msgid "Tomorrow"
msgstr "Mañana" msgstr "Mañana"

View File

@ -2,7 +2,7 @@ from django.conf.urls.defaults import *
urlpatterns = patterns('', urlpatterns = patterns('',
# Example: # Example:
# (r'^{{ project_name }}/', include('{{ project_name }}.apps.foo.urls.foo')), # (r'^{{ project_name }}/', include('{{ project_name }}.foo.urls')),
# Uncomment this for admin: # Uncomment this for admin:
# (r'^admin/', include('django.contrib.admin.urls')), # (r'^admin/', include('django.contrib.admin.urls')),

View File

@ -44,7 +44,7 @@ var DateTimeShortcuts = {
var shortcuts_span = document.createElement('span'); var shortcuts_span = document.createElement('span');
inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling); inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
var now_link = document.createElement('a'); var now_link = document.createElement('a');
now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinute());"); now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());");
now_link.appendChild(document.createTextNode(gettext('Now'))); now_link.appendChild(document.createTextNode(gettext('Now')));
var clock_link = document.createElement('a'); var clock_link = document.createElement('a');
clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');'); clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
@ -80,10 +80,10 @@ var DateTimeShortcuts = {
quickElement('h2', clock_box, gettext('Choose a time')); quickElement('h2', clock_box, gettext('Choose a time'));
time_list = quickElement('ul', clock_box, ''); time_list = quickElement('ul', clock_box, '');
time_list.className = 'timelist'; time_list.className = 'timelist';
quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinute());") quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().getHourMinuteSecond());")
quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '00:00');") quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '00:00:00');")
quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '06:00');") quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '06:00:00');")
quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '12:00');") quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", '12:00:00');")
cancel_p = quickElement('p', clock_box, ''); cancel_p = quickElement('p', clock_box, '');
cancel_p.className = 'calendar-cancel'; cancel_p.className = 'calendar-cancel';

View File

@ -119,6 +119,10 @@ Date.prototype.getTwoDigitMinute = function() {
return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes(); return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes();
} }
Date.prototype.getTwoDigitSecond = function() {
return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
}
Date.prototype.getISODate = function() { Date.prototype.getISODate = function() {
return this.getCorrectYear() + '-' + this.getTwoDigitMonth() + '-' + this.getTwoDigitDate(); return this.getCorrectYear() + '-' + this.getTwoDigitMonth() + '-' + this.getTwoDigitDate();
} }
@ -127,6 +131,10 @@ Date.prototype.getHourMinute = function() {
return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute(); return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute();
} }
Date.prototype.getHourMinuteSecond = function() {
return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond();
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// String object extensions // String object extensions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -7,7 +7,7 @@
<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query|escape }}" id="searchbar" /> <input type="text" size="40" name="{{ search_var }}" value="{{ cl.query|escape }}" id="searchbar" />
<input type="submit" value="{% trans 'Go' %}" /> <input type="submit" value="{% trans 'Go' %}" />
{% if show_result_count %} {% if show_result_count %}
<span class="small quiet">{% blocktrans count cl.result_count as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?">{% blocktrans with cl.full_result_count as full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span> <span class="small quiet">{% blocktrans count cl.result_count as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}pop=1{% endif %}">{% blocktrans with cl.full_result_count as full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span>
{% endif %} {% endif %}
{% for pair in cl.params.items %} {% for pair in cl.params.items %}
{% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0|escape }}" value="{{ pair.1|escape }}"/>{% endifnotequal %} {% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0|escape }}" value="{{ pair.1|escape }}"/>{% endifnotequal %}

View File

@ -226,7 +226,7 @@ index = staff_member_required(never_cache(index))
def add_stage(request, app_label, model_name, show_delete=False, form_url='', post_url=None, post_url_continue='../%s/', object_id_override=None): def add_stage(request, app_label, model_name, show_delete=False, form_url='', post_url=None, post_url_continue='../%s/', object_id_override=None):
model = models.get_model(app_label, model_name) model = models.get_model(app_label, model_name)
if model is None: if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name) raise Http404("App %r, model %r, not found" % (app_label, model_name))
opts = model._meta opts = model._meta
if not request.user.has_perm(app_label + '.' + opts.get_add_permission()): if not request.user.has_perm(app_label + '.' + opts.get_add_permission()):
@ -302,7 +302,7 @@ def change_stage(request, app_label, model_name, object_id):
model = models.get_model(app_label, model_name) model = models.get_model(app_label, model_name)
object_id = unquote(object_id) object_id = unquote(object_id)
if model is None: if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name) raise Http404("App %r, model %r, not found" % (app_label, model_name))
opts = model._meta opts = model._meta
if not request.user.has_perm(app_label + '.' + opts.get_change_permission()): if not request.user.has_perm(app_label + '.' + opts.get_change_permission()):
@ -313,8 +313,8 @@ def change_stage(request, app_label, model_name, object_id):
try: try:
manipulator = model.ChangeManipulator(object_id) manipulator = model.ChangeManipulator(object_id)
except ObjectDoesNotExist: except model.DoesNotExist:
raise Http404 raise Http404('%s object with primary key %r does not exist' % (model_name, escape(object_id)))
if request.POST: if request.POST:
new_data = request.POST.copy() new_data = request.POST.copy()
@ -490,7 +490,7 @@ def delete_stage(request, app_label, model_name, object_id):
model = models.get_model(app_label, model_name) model = models.get_model(app_label, model_name)
object_id = unquote(object_id) object_id = unquote(object_id)
if model is None: if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name) raise Http404("App %r, model %r, not found" % (app_label, model_name))
opts = model._meta opts = model._meta
if not request.user.has_perm(app_label + '.' + opts.get_delete_permission()): if not request.user.has_perm(app_label + '.' + opts.get_delete_permission()):
raise PermissionDenied raise PermissionDenied
@ -527,7 +527,7 @@ def history(request, app_label, model_name, object_id):
model = models.get_model(app_label, model_name) model = models.get_model(app_label, model_name)
object_id = unquote(object_id) object_id = unquote(object_id)
if model is None: if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name) raise Http404("App %r, model %r, not found" % (app_label, model_name))
action_list = LogEntry.objects.filter(object_id=object_id, action_list = LogEntry.objects.filter(object_id=object_id,
content_type__id__exact=ContentType.objects.get_for_model(model).id).select_related().order_by('action_time') content_type__id__exact=ContentType.objects.get_for_model(model).id).select_related().order_by('action_time')
# If no history was found, see whether this object even exists. # If no history was found, see whether this object even exists.
@ -743,7 +743,7 @@ class ChangeList(object):
def change_list(request, app_label, model_name): def change_list(request, app_label, model_name):
model = models.get_model(app_label, model_name) model = models.get_model(app_label, model_name)
if model is None: if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name) raise Http404("App %r, model %r, not found" % (app_label, model_name))
if not request.user.has_perm(app_label + '.' + model._meta.get_change_permission()): if not request.user.has_perm(app_label + '.' + model._meta.get_change_permission()):
raise PermissionDenied raise PermissionDenied
try: try:

View File

@ -3,9 +3,9 @@ Creates content types for all installed models.
""" """
from django.dispatch import dispatcher from django.dispatch import dispatcher
from django.db.models import get_models, signals from django.db.models import get_apps, get_models, signals
def create_contenttypes(app, created_models, verbosity): def create_contenttypes(app, created_models, verbosity=2):
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
app_models = get_models(app) app_models = get_models(app)
if not app_models: if not app_models:
@ -22,4 +22,11 @@ def create_contenttypes(app, created_models, verbosity):
if verbosity >= 2: if verbosity >= 2:
print "Adding content type '%s | %s'" % (ct.app_label, ct.model) print "Adding content type '%s | %s'" % (ct.app_label, ct.model)
def create_all_contenttypes(verbosity=2):
for app in get_apps():
create_contenttypes(app, None, verbosity)
dispatcher.connect(create_contenttypes, signal=signals.post_syncdb) dispatcher.connect(create_contenttypes, signal=signals.post_syncdb)
if __name__ == "__main__":
create_all_contenttypes()

View File

View File

@ -0,0 +1,160 @@
"""
Formtools Preview application.
This is an abstraction of the following workflow:
"Display an HTML form, force a preview, then do something with the submission."
Given a django.newforms.Form object that you define, this takes care of the
following:
* Displays the form as HTML on a Web page.
* Validates the form data once it's submitted via POST.
* If it's valid, displays a preview page.
* If it's not valid, redisplays the form with error messages.
* At the preview page, if the preview confirmation button is pressed, calls
a hook that you define -- a done() method.
The framework enforces the required preview by passing a shared-secret hash to
the preview page. If somebody tweaks the form parameters on the preview page,
the form submission will fail the hash comparison test.
Usage
=====
Subclass FormPreview and define a done() method:
def done(self, request, clean_data):
# ...
This method takes an HttpRequest object and a dictionary of the form data after
it has been validated and cleaned. It should return an HttpResponseRedirect.
Then, just instantiate your FormPreview subclass by passing it a Form class,
and pass that to your URLconf, like so:
(r'^post/$', MyFormPreview(MyForm)),
The FormPreview class has a few other hooks. See the docstrings in the source
code below.
The framework also uses two templates: 'formtools/preview.html' and
'formtools/form.html'. You can override these by setting 'preview_template' and
'form_template' attributes on your FormPreview subclass. See
django/contrib/formtools/templates for the default templates.
"""
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404
from django.shortcuts import render_to_response
import cPickle as pickle
import md5
AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter.
class FormPreview(object):
preview_template = 'formtools/preview.html'
form_template = 'formtools/form.html'
# METHODS SUBCLASSES SHOULDN'T OVERRIDE ###################################
def __init__(self, form):
# form should be a Form class, not an instance.
self.form, self.state = form, {}
def __call__(self, request, *args, **kwargs):
stage = {'1': 'preview', '2': 'post'}.get(request.POST.get(self.unused_name('stage')), 'preview')
self.parse_params(*args, **kwargs)
try:
method = getattr(self, stage + '_' + request.method.lower())
except AttributeError:
raise Http404
return method(request)
def unused_name(self, name):
"""
Given a first-choice name, adds an underscore to the name until it
reaches a name that isn't claimed by any field in the form.
This is calculated rather than being hard-coded so that no field names
are off-limits for use in the form.
"""
while 1:
try:
f = self.form.fields[name]
except KeyError:
break # This field name isn't being used by the form.
name += '_'
return name
def preview_get(self, request):
"Displays the form"
f = self.form(auto_id=AUTO_ID)
return render_to_response(self.form_template, {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state})
def preview_post(self, request):
"Validates the POST data. If valid, displays the preview page. Else, redisplays form."
f = self.form(request.POST, auto_id=AUTO_ID)
context = {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state}
if f.is_valid():
context['hash_field'] = self.unused_name('hash')
context['hash_value'] = self.security_hash(request, f)
return render_to_response(self.preview_template, context)
else:
return render_to_response(self.form_template, context)
def post_post(self, request):
"Validates the POST data. If valid, calls done(). Else, redisplays form."
f = self.form(request.POST, auto_id=AUTO_ID)
if f.is_valid():
if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
return self.failed_hash(request) # Security hash failed.
return self.done(request, f.clean_data)
else:
return render_to_response(self.form_template, {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state})
# METHODS SUBCLASSES MIGHT OVERRIDE IF APPROPRIATE ########################
def parse_params(self, *args, **kwargs):
"""
Given captured args and kwargs from the URLconf, saves something in
self.state and/or raises Http404 if necessary.
For example, this URLconf captures a user_id variable:
(r'^contact/(?P<user_id>\d{1,6})/$', MyFormPreview(MyForm)),
In this case, the kwargs variable in parse_params would be
{'user_id': 32} for a request to '/contact/32/'. You can use that
user_id to make sure it's a valid user and/or save it for later, for
use in done().
"""
pass
def security_hash(self, request, form):
"""
Calculates the security hash for the given Form instance.
This creates a list of the form field names/values in a deterministic
order, pickles the result with the SECRET_KEY setting and takes an md5
hash of that.
Subclasses may want to take into account request-specific information
such as the IP address.
"""
data = [(bf.name, bf.data) for bf in form] + [settings.SECRET_KEY]
# Use HIGHEST_PROTOCOL because it's the most efficient. It requires
# Python 2.3, but Django requires 2.3 anyway, so that's OK.
pickled = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
return md5.new(pickled).hexdigest()
def failed_hash(self, request):
"Returns an HttpResponse in the case of an invalid security hash."
return self.preview_post(request)
# METHODS SUBCLASSES MUST OVERRIDE ########################################
def done(self, request, clean_data):
"Does something with the clean_data and returns an HttpResponseRedirect."
raise NotImplementedError('You must define a done() method on your %s subclass.' % self.__class__.__name__)

View File

@ -0,0 +1,15 @@
{% extends "base.html" %}
{% block content %}
{% if form.errors %}<h1>Please correct the following errors</h1>{% else %}<h1>Submit</h1>{% endif %}
<form action="" method="post">
<table>
{{ form }}
</table>
<input type="hidden" name="{{ stage_field }}" value="1" />
<p><input type="submit" value="Submit" /></p>
</form>
{% endblock %}

View File

@ -0,0 +1,36 @@
{% extends "base.html" %}
{% block content %}
<h1>Preview your submission</h1>
<table>
{% for field in form %}
<tr>
<th>{{ field.verbose_name }}:</th>
<td>{{ field.data|escape }}</td>
</tr>
{% endfor %}
</table>
<p>Security hash: {{ hash_value }}</p>
<form action="" method="post">
{% for field in form %}{{ field.as_hidden }}
{% endfor %}
<input type="hidden" name="{{ stage_field }}" value="2" />
<input type="hidden" name="{{ hash_field }}" value="{{ hash_value }}" />
<p><input type="submit" value="Submit" /></p>
</form>
<h1>Or edit it again</h1>
<form action="" method="post">
<table>
{{ form }}
</table>
<input type="hidden" name="{{ stage_field }}" value="1" />
<p><input type="submit" value="Submit changes" /></p>
</form>
{% endblock %}

View File

@ -29,7 +29,7 @@ def ping_google(sitemap_url=None, ping_url=PING_URL):
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
current_site = Site.objects.get_current() current_site = Site.objects.get_current()
url = "%s%s" % (current_site.domain, sitemap) url = "%s%s" % (current_site.domain, sitemap_url)
params = urllib.urlencode({'sitemap':url}) params = urllib.urlencode({'sitemap':url})
urllib.urlopen("%s?%s" % (ping_url, params)) urllib.urlopen("%s?%s" % (ping_url, params))

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% spaceless %} {% spaceless %}
{% for url in urlset %} {% for url in urlset %}
<url> <url>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84"> <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% for location in sitemaps %}<sitemap><loc>{{ location|escape }}</loc></sitemap>{% endfor %} {% for location in sitemaps %}<sitemap><loc>{{ location|escape }}</loc></sitemap>{% endfor %}
</sitemapindex> </sitemapindex>

View File

@ -84,7 +84,11 @@ class BaseHandler(object):
# Complain if the view returned None (a common error). # Complain if the view returned None (a common error).
if response is None: if response is None:
raise ValueError, "The view %s.%s didn't return an HttpResponse object." % (callback.__module__, callback.func_name) try:
view_name = callback.func_name # If it's a function
except AttributeError:
view_name = callback.__class__.__name__ + '.__call__' # If it's a class
raise ValueError, "The view %s.%s didn't return an HttpResponse object." % (callback.__module__, view_name)
return response return response
except http.Http404, e: except http.Http404, e:

View File

@ -62,7 +62,7 @@ def safe_copyfileobj(fsrc, fdst, length=16*1024, size=0):
data in the body. data in the body.
""" """
if not size: if not size:
return copyfileobj(fsrc, fdst, length) return
while size > 0: while size > 0:
buf = fsrc.read(min(length, size)) buf = fsrc.read(min(length, size))
if not buf: if not buf:
@ -157,7 +157,11 @@ class WSGIRequest(http.HttpRequest):
return self._raw_post_data return self._raw_post_data
except AttributeError: except AttributeError:
buf = StringIO() buf = StringIO()
content_length = int(self.environ['CONTENT_LENGTH']) try:
# CONTENT_LENGTH might be absent if POST doesn't have content at all (lighttpd)
content_length = int(self.environ.get('CONTENT_LENGTH', 0))
except ValueError: # if CONTENT_LENGTH was empty string or not an integer
content_length = 0
safe_copyfileobj(self.environ['wsgi.input'], buf, size=content_length) safe_copyfileobj(self.environ['wsgi.input'], buf, size=content_length)
self._raw_post_data = buf.getvalue() self._raw_post_data = buf.getvalue()
buf.close() buf.close()

View File

@ -8,6 +8,8 @@ import socket
import time import time
import random import random
DNS_NAME = socket.getfqdn() # Cache the hostname
class BadHeaderError(ValueError): class BadHeaderError(ValueError):
pass pass
@ -53,7 +55,11 @@ def send_mass_mail(datatuple, fail_silently=False, auth_user=settings.EMAIL_HOST
msg['From'] = from_email msg['From'] = from_email
msg['To'] = ', '.join(recipient_list) msg['To'] = ', '.join(recipient_list)
msg['Date'] = rfc822.formatdate() msg['Date'] = rfc822.formatdate()
msg['Message-ID'] = "<%d.%d@%s>" % (time.time(), random.getrandbits(64), socket.getfqdn()) try:
random_bits = str(random.getrandbits(64))
except AttributeError: # Python 2.3 doesn't have random.getrandbits().
random_bits = ''.join([random.choice('1234567890') for i in range(19)])
msg['Message-ID'] = "<%d.%s@%s>" % (time.time(), random_bits, DNS_NAME)
try: try:
server.sendmail(from_email, recipient_list, msg.as_string()) server.sendmail(from_email, recipient_list, msg.as_string())
num_sent += 1 num_sent += 1

View File

@ -118,6 +118,8 @@ def runfastcgi(argset=[], **kwargs):
else: else:
return fastcgi_help("ERROR: Implementation must be one of prefork or thread.") return fastcgi_help("ERROR: Implementation must be one of prefork or thread.")
wsgi_opts['debug'] = False # Turn off flup tracebacks
# Prep up and go # Prep up and go
from django.core.handlers.wsgi import WSGIHandler from django.core.handlers.wsgi import WSGIHandler

View File

@ -17,6 +17,6 @@ def populate_xheaders(request, response, model, object_id):
or if the request is from a logged in staff member. or if the request is from a logged in staff member.
""" """
from django.conf import settings from django.conf import settings
if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or (request.user.is_authenticated() and request.user.is_staff): if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or (hasattr(request, 'user') and request.user.is_authenticated() and request.user.is_staff):
response['X-Object-Type'] = "%s.%s" % (model._meta.app_label, model._meta.object_name.lower()) response['X-Object-Type'] = "%s.%s" % (model._meta.app_label, model._meta.object_name.lower())
response['X-Object-Id'] = str(object_id) response['X-Object-Id'] = str(object_id)

View File

@ -18,7 +18,7 @@ except ImportError, e:
available_backends = [f for f in os.listdir(backend_dir) if not f.startswith('_') and not f.startswith('.') and not f.endswith('.py') and not f.endswith('.pyc')] available_backends = [f for f in os.listdir(backend_dir) if not f.startswith('_') and not f.startswith('.') and not f.endswith('.py') and not f.endswith('.pyc')]
available_backends.sort() available_backends.sort()
if settings.DATABASE_ENGINE not in available_backends: if settings.DATABASE_ENGINE not in available_backends:
raise ImproperlyConfigured, "%r isn't an available database backend. vailable options are: %s" % \ raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s" % \
(settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends))) (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends)))
else: else:
raise # If there's some other error, this must be an error in Django itself. raise # If there's some other error, this must be an error in Django itself.

View File

@ -457,9 +457,7 @@ class DateField(Field):
def get_db_prep_save(self, value): def get_db_prep_save(self, value):
# Casts dates into string format for entry into database. # Casts dates into string format for entry into database.
if isinstance(value, datetime.datetime): if value is not None:
value = value.date().strftime('%Y-%m-%d')
elif isinstance(value, datetime.date):
value = value.strftime('%Y-%m-%d') value = value.strftime('%Y-%m-%d')
return Field.get_db_prep_save(self, value) return Field.get_db_prep_save(self, value)
@ -489,19 +487,12 @@ class DateTimeField(DateField):
def get_db_prep_save(self, value): def get_db_prep_save(self, value):
# Casts dates into string format for entry into database. # Casts dates into string format for entry into database.
if isinstance(value, datetime.datetime): if value is not None:
# MySQL will throw a warning if microseconds are given, because it # MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds. # doesn't support microseconds.
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
value = value.replace(microsecond=0) value = value.replace(microsecond=0)
value = str(value) value = str(value)
elif isinstance(value, datetime.date):
# MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds.
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
value = datetime.datetime(value.year, value.month, value.day, microsecond=0)
value = str(value)
return Field.get_db_prep_save(self, value) return Field.get_db_prep_save(self, value)
def get_db_prep_lookup(self, lookup_type, value): def get_db_prep_lookup(self, lookup_type, value):

View File

@ -208,7 +208,7 @@ class HttpResponse(object):
if path is not None: if path is not None:
self.cookies[key]['path'] = path self.cookies[key]['path'] = path
if domain is not None: if domain is not None:
self.cookies[key]['domain'] = path self.cookies[key]['domain'] = domain
self.cookies[key]['expires'] = 0 self.cookies[key]['expires'] = 0
self.cookies[key]['max-age'] = 0 self.cookies[key]['max-age'] = 0

View File

@ -25,4 +25,5 @@ class GZipMiddleware(object):
response.content = compress_string(response.content) response.content = compress_string(response.content)
response['Content-Encoding'] = 'gzip' response['Content-Encoding'] = 'gzip'
response['Content-Length'] = str(len(response.content))
return response return response

View File

@ -14,15 +14,4 @@ from util import ValidationError
from widgets import * from widgets import *
from fields import * from fields import *
from forms import Form from forms import Form
from models import *
##########################
# DATABASE API SHORTCUTS #
##########################
def form_for_model(model):
"Returns a Form instance for the given Django model class."
raise NotImplementedError
def form_for_fields(field_list):
"Returns a Form instance for the given list of Django database field instances."
raise NotImplementedError

View File

@ -2,7 +2,8 @@
Field classes Field classes
""" """
from util import ValidationError, DEFAULT_ENCODING from django.utils.translation import gettext
from util import ValidationError, smart_unicode
from widgets import TextInput, CheckboxInput, Select, SelectMultiple from widgets import TextInput, CheckboxInput, Select, SelectMultiple
import datetime import datetime
import re import re
@ -28,6 +29,9 @@ except NameError:
class Field(object): class Field(object):
widget = TextInput # Default widget to use when rendering this type of Field. widget = TextInput # Default widget to use when rendering this type of Field.
# Tracks each time a Field instance is created. Used to retain order.
creation_counter = 0
def __init__(self, required=True, widget=None): def __init__(self, required=True, widget=None):
self.required = required self.required = required
widget = widget or self.widget widget = widget or self.widget
@ -35,6 +39,10 @@ class Field(object):
widget = widget() widget = widget()
self.widget = widget self.widget = widget
# Increase the creation counter, and save our local copy.
self.creation_counter = Field.creation_counter
Field.creation_counter += 1
def clean(self, value): def clean(self, value):
""" """
Validates the given value and returns its "cleaned" value as an Validates the given value and returns its "cleaned" value as an
@ -43,7 +51,7 @@ class Field(object):
Raises ValidationError for any errors. Raises ValidationError for any errors.
""" """
if self.required and value in EMPTY_VALUES: if self.required and value in EMPTY_VALUES:
raise ValidationError(u'This field is required.') raise ValidationError(gettext(u'This field is required.'))
return value return value
class CharField(Field): class CharField(Field):
@ -55,14 +63,11 @@ class CharField(Field):
"Validates max_length and min_length. Returns a Unicode object." "Validates max_length and min_length. Returns a Unicode object."
Field.clean(self, value) Field.clean(self, value)
if value in EMPTY_VALUES: value = u'' if value in EMPTY_VALUES: value = u''
if not isinstance(value, basestring): value = smart_unicode(value)
value = unicode(str(value), DEFAULT_ENCODING)
elif not isinstance(value, unicode):
value = unicode(value, DEFAULT_ENCODING)
if self.max_length is not None and len(value) > self.max_length: if self.max_length is not None and len(value) > self.max_length:
raise ValidationError(u'Ensure this value has at most %d characters.' % self.max_length) raise ValidationError(gettext(u'Ensure this value has at most %d characters.') % self.max_length)
if self.min_length is not None and len(value) < self.min_length: if self.min_length is not None and len(value) < self.min_length:
raise ValidationError(u'Ensure this value has at least %d characters.' % self.min_length) raise ValidationError(gettext(u'Ensure this value has at least %d characters.') % self.min_length)
return value return value
class IntegerField(Field): class IntegerField(Field):
@ -72,10 +77,12 @@ class IntegerField(Field):
of int(). of int().
""" """
super(IntegerField, self).clean(value) super(IntegerField, self).clean(value)
if not self.required and value in EMPTY_VALUES:
return u''
try: try:
return int(value) return int(value)
except (ValueError, TypeError): except (ValueError, TypeError):
raise ValidationError(u'Enter a whole number.') raise ValidationError(gettext(u'Enter a whole number.'))
DEFAULT_DATE_INPUT_FORMATS = ( DEFAULT_DATE_INPUT_FORMATS = (
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
@ -107,7 +114,7 @@ class DateField(Field):
return datetime.date(*time.strptime(value, format)[:3]) return datetime.date(*time.strptime(value, format)[:3])
except ValueError: except ValueError:
continue continue
raise ValidationError(u'Enter a valid date.') raise ValidationError(gettext(u'Enter a valid date.'))
DEFAULT_DATETIME_INPUT_FORMATS = ( DEFAULT_DATETIME_INPUT_FORMATS = (
'%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
@ -143,7 +150,7 @@ class DateTimeField(Field):
return datetime.datetime(*time.strptime(value, format)[:6]) return datetime.datetime(*time.strptime(value, format)[:6])
except ValueError: except ValueError:
continue continue
raise ValidationError(u'Enter a valid date/time.') raise ValidationError(gettext(u'Enter a valid date/time.'))
class RegexField(Field): class RegexField(Field):
def __init__(self, regex, error_message=None, required=True, widget=None): def __init__(self, regex, error_message=None, required=True, widget=None):
@ -156,7 +163,7 @@ class RegexField(Field):
if isinstance(regex, basestring): if isinstance(regex, basestring):
regex = re.compile(regex) regex = re.compile(regex)
self.regex = regex self.regex = regex
self.error_message = error_message or u'Enter a valid value.' self.error_message = error_message or gettext(u'Enter a valid value.')
def clean(self, value): def clean(self, value):
""" """
@ -165,10 +172,9 @@ class RegexField(Field):
""" """
Field.clean(self, value) Field.clean(self, value)
if value in EMPTY_VALUES: value = u'' if value in EMPTY_VALUES: value = u''
if not isinstance(value, basestring): value = smart_unicode(value)
value = unicode(str(value), DEFAULT_ENCODING) if not self.required and value == u'':
elif not isinstance(value, unicode): return value
value = unicode(value, DEFAULT_ENCODING)
if not self.regex.search(value): if not self.regex.search(value):
raise ValidationError(self.error_message) raise ValidationError(self.error_message)
return value return value
@ -180,7 +186,7 @@ email_re = re.compile(
class EmailField(RegexField): class EmailField(RegexField):
def __init__(self, required=True, widget=None): def __init__(self, required=True, widget=None):
RegexField.__init__(self, email_re, u'Enter a valid e-mail address.', required, widget) RegexField.__init__(self, email_re, gettext(u'Enter a valid e-mail address.'), required, widget)
url_re = re.compile( url_re = re.compile(
r'^https?://' # http:// or https:// r'^https?://' # http:// or https://
@ -198,7 +204,7 @@ except ImportError:
class URLField(RegexField): class URLField(RegexField):
def __init__(self, required=True, verify_exists=False, widget=None, def __init__(self, required=True, verify_exists=False, widget=None,
validator_user_agent=URL_VALIDATOR_USER_AGENT): validator_user_agent=URL_VALIDATOR_USER_AGENT):
RegexField.__init__(self, url_re, u'Enter a valid URL.', required, widget) RegexField.__init__(self, url_re, gettext(u'Enter a valid URL.'), required, widget)
self.verify_exists = verify_exists self.verify_exists = verify_exists
self.user_agent = validator_user_agent self.user_agent = validator_user_agent
@ -215,12 +221,12 @@ class URLField(RegexField):
"User-Agent": self.user_agent, "User-Agent": self.user_agent,
} }
try: try:
req = urllib2.Request(field_data, None, headers) req = urllib2.Request(value, None, headers)
u = urllib2.urlopen(req) u = urllib2.urlopen(req)
except ValueError: except ValueError:
raise ValidationError(u'Enter a valid URL.') raise ValidationError(gettext(u'Enter a valid URL.'))
except: # urllib2.URLError, httplib.InvalidURL, etc. except: # urllib2.URLError, httplib.InvalidURL, etc.
raise ValidationError(u'This URL appears to be a broken link.') raise ValidationError(gettext(u'This URL appears to be a broken link.'))
return value return value
class BooleanField(Field): class BooleanField(Field):
@ -244,13 +250,12 @@ class ChoiceField(Field):
""" """
value = Field.clean(self, value) value = Field.clean(self, value)
if value in EMPTY_VALUES: value = u'' if value in EMPTY_VALUES: value = u''
if not isinstance(value, basestring): value = smart_unicode(value)
value = unicode(str(value), DEFAULT_ENCODING) if not self.required and value == u'':
elif not isinstance(value, unicode): return value
value = unicode(value, DEFAULT_ENCODING)
valid_values = set([str(k) for k, v in self.choices]) valid_values = set([str(k) for k, v in self.choices])
if value not in valid_values: if value not in valid_values:
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % value) raise ValidationError(gettext(u'Select a valid choice. %s is not one of the available choices.') % value)
return value return value
class MultipleChoiceField(ChoiceField): class MultipleChoiceField(ChoiceField):
@ -261,27 +266,31 @@ class MultipleChoiceField(ChoiceField):
""" """
Validates that the input is a list or tuple. Validates that the input is a list or tuple.
""" """
if not isinstance(value, (list, tuple)):
raise ValidationError(u'Enter a list of values.')
if self.required and not value: if self.required and not value:
raise ValidationError(u'This field is required.') raise ValidationError(gettext(u'This field is required.'))
elif not self.required and not value:
return []
if not isinstance(value, (list, tuple)):
raise ValidationError(gettext(u'Enter a list of values.'))
new_value = [] new_value = []
for val in value: for val in value:
if not isinstance(val, basestring): val = smart_unicode(val)
value = unicode(str(val), DEFAULT_ENCODING) new_value.append(val)
elif not isinstance(val, unicode):
value = unicode(val, DEFAULT_ENCODING)
new_value.append(value)
# Validate that each value in the value list is in self.choices. # Validate that each value in the value list is in self.choices.
valid_values = set([k for k, v in self.choices]) valid_values = set([smart_unicode(k) for k, v in self.choices])
for val in new_value: for val in new_value:
if val not in valid_values: if val not in valid_values:
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % val) raise ValidationError(gettext(u'Select a valid choice. %s is not one of the available choices.') % val)
return new_value return new_value
class ComboField(Field): class ComboField(Field):
def __init__(self, fields=(), required=True, widget=None): def __init__(self, fields=(), required=True, widget=None):
Field.__init__(self, required, widget) Field.__init__(self, required, widget)
# Set 'required' to False on the individual fields, because the
# required validation will be handled by ComboField, not by those
# individual fields.
for f in fields:
f.required = False
self.fields = fields self.fields = fields
def clean(self, value): def clean(self, value):

View File

@ -2,9 +2,11 @@
Form classes Form classes
""" """
from django.utils.datastructures import SortedDict
from django.utils.html import escape
from fields import Field from fields import Field
from widgets import TextInput, Textarea from widgets import TextInput, Textarea, HiddenInput
from util import ErrorDict, ErrorList, ValidationError from util import StrAndUnicode, ErrorDict, ErrorList, ValidationError
NON_FIELD_ERRORS = '__all__' NON_FIELD_ERRORS = '__all__'
@ -13,22 +15,35 @@ def pretty_name(name):
name = name[0].upper() + name[1:] name = name[0].upper() + name[1:]
return name.replace('_', ' ') return name.replace('_', ' ')
class SortedDictFromList(SortedDict):
"A dictionary that keeps its keys in the order in which they're inserted."
# This is different than django.utils.datastructures.SortedDict, because
# this takes a list/tuple as the argument to __init__().
def __init__(self, data=None):
if data is None: data = []
self.keyOrder = [d[0] for d in data]
dict.__init__(self, dict(data))
class DeclarativeFieldsMetaclass(type): class DeclarativeFieldsMetaclass(type):
"Metaclass that converts Field attributes to a dictionary called 'fields'." "Metaclass that converts Field attributes to a dictionary called 'fields'."
def __new__(cls, name, bases, attrs): def __new__(cls, name, bases, attrs):
attrs['fields'] = dict([(name, attrs.pop(name)) for name, obj in attrs.items() if isinstance(obj, Field)]) fields = [(name, attrs.pop(name)) for name, obj in attrs.items() if isinstance(obj, Field)]
fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
attrs['fields'] = SortedDictFromList(fields)
return type.__new__(cls, name, bases, attrs) return type.__new__(cls, name, bases, attrs)
class Form(object): class Form(StrAndUnicode):
"A collection of Fields, plus their associated data." "A collection of Fields, plus their associated data."
__metaclass__ = DeclarativeFieldsMetaclass __metaclass__ = DeclarativeFieldsMetaclass
def __init__(self, data=None): # TODO: prefix stuff def __init__(self, data=None, auto_id=False): # TODO: prefix stuff
self.ignore_errors = data is None
self.data = data or {} self.data = data or {}
self.auto_id = auto_id
self.clean_data = None # Stores the data after clean() has been called. self.clean_data = None # Stores the data after clean() has been called.
self.__errors = None # Stores the errors after clean() has been called. self.__errors = None # Stores the errors after clean() has been called.
def __str__(self): def __unicode__(self):
return self.as_table() return self.as_table()
def __iter__(self): def __iter__(self):
@ -43,62 +58,66 @@ class Form(object):
raise KeyError('Key %r not found in Form' % name) raise KeyError('Key %r not found in Form' % name)
return BoundField(self, field, name) return BoundField(self, field, name)
def clean(self): def _errors(self):
if self.__errors is None:
self.full_clean()
return self.clean_data
def errors(self):
"Returns an ErrorDict for self.data" "Returns an ErrorDict for self.data"
if self.__errors is None: if self.__errors is None:
self.full_clean() self.full_clean()
return self.__errors return self.__errors
errors = property(_errors)
def is_valid(self): def is_valid(self):
""" """
Returns True if the form has no errors. Otherwise, False. This exists Returns True if the form has no errors. Otherwise, False. If errors are
solely for convenience, so client code can use positive logic rather being ignored, returns False.
than confusing negative logic ("if not form.errors()").
""" """
return not bool(self.errors()) return not self.ignore_errors and not bool(self.errors)
def _html_output(self, normal_row, error_row, row_ender, errors_on_separate_row):
"Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
output, hidden_fields = [], []
for name, field in self.fields.items():
bf = BoundField(self, field, name)
bf_errors = bf.errors # Cache in local variable.
if bf.is_hidden:
if bf_errors:
top_errors.extend(['(Hidden field %s) %s' % (name, e) for e in bf_errors])
hidden_fields.append(unicode(bf))
else:
if errors_on_separate_row and bf_errors:
output.append(error_row % bf_errors)
output.append(normal_row % {'errors': bf_errors, 'label': bf.label_tag(escape(bf.verbose_name+':')), 'field': bf})
if top_errors:
output.insert(0, error_row % top_errors)
if hidden_fields: # Insert any hidden fields in the last row.
str_hidden = u''.join(hidden_fields)
if output:
last_row = output[-1]
# Chop off the trailing row_ender (e.g. '</td></tr>') and insert the hidden fields.
output[-1] = last_row[:-len(row_ender)] + str_hidden + row_ender
else: # If there aren't any rows in the output, just append the hidden fields.
output.append(str_hidden)
return u'\n'.join(output)
def as_table(self): def as_table(self):
"Returns this form rendered as an HTML <table>." "Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
output = u'\n'.join(['<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()]) return self._html_output(u'<tr><td>%(label)s</td><td>%(field)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', True)
return '<table>\n%s\n</table>' % output
def as_ul(self): def as_ul(self):
"Returns this form rendered as an HTML <ul>." "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
output = u'\n'.join(['<li>%s: %s</li>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()]) return self._html_output(u'<li>%(errors)s%(label)s %(field)s</li>', u'<li>%s</li>', '</li>', False)
return '<ul>\n%s\n</ul>' % output
def as_table_with_errors(self): def as_p(self):
"Returns this form rendered as an HTML <table>, with errors." "Returns this form rendered as HTML <p>s."
output = [] return self._html_output(u'<p>%(label)s %(field)s</p>', u'<p>%s</p>', '</p>', True)
if self.errors().get(NON_FIELD_ERRORS):
# Errors not corresponding to a particular field are displayed at the top.
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]]))
for name, field in self.fields.items():
bf = BoundField(self, field, name)
if bf.errors:
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors]))
output.append('<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), bf))
return '<table>\n%s\n</table>' % '\n'.join(output)
def as_ul_with_errors(self): def non_field_errors(self):
"Returns this form rendered as an HTML <ul>, with errors." """
output = [] Returns an ErrorList of errors that aren't associated with a particular
if self.errors().get(NON_FIELD_ERRORS): field -- i.e., from Form.clean(). Returns an empty ErrorList if there
# Errors not corresponding to a particular field are displayed at the top. are none.
output.append('<li><ul>%s</ul></li>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]])) """
for name, field in self.fields.items(): return self.errors.get(NON_FIELD_ERRORS, ErrorList())
bf = BoundField(self, field, name)
line = '<li>'
if bf.errors:
line += '<ul>%s</ul>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors])
line += '%s: %s</li>' % (pretty_name(name), bf)
output.append(line)
return '<ul>\n%s\n</ul>' % '\n'.join(output)
def full_clean(self): def full_clean(self):
""" """
@ -106,8 +125,14 @@ class Form(object):
""" """
self.clean_data = {} self.clean_data = {}
errors = ErrorDict() errors = ErrorDict()
if self.ignore_errors: # Stop further processing.
self.__errors = errors
return
for name, field in self.fields.items(): for name, field in self.fields.items():
value = self.data.get(name, None) # value_from_datadict() gets the data from the dictionary.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, name)
try: try:
value = field.clean(value) value = field.clean(value)
self.clean_data[name] = value self.clean_data[name] = value
@ -127,36 +152,45 @@ class Form(object):
def clean(self): def clean(self):
""" """
Hook for doing any extra form-wide cleaning after Field.clean() been Hook for doing any extra form-wide cleaning after Field.clean() been
called on every field. called on every field. Any ValidationError raised by this method will
not be associated with a particular field; it will have a special-case
association with the field named '__all__'.
""" """
return self.clean_data return self.clean_data
class BoundField(object): class BoundField(StrAndUnicode):
"A Field plus data" "A Field plus data"
def __init__(self, form, field, name): def __init__(self, form, field, name):
self._form = form self.form = form
self._field = field self.field = field
self._name = name self.name = name
def __str__(self): def __unicode__(self):
"Renders this field as an HTML widget." "Renders this field as an HTML widget."
# Use the 'widget' attribute on the field to determine which type # Use the 'widget' attribute on the field to determine which type
# of HTML widget to use. # of HTML widget to use.
return self.as_widget(self._field.widget) value = self.as_widget(self.field.widget)
if not isinstance(value, basestring):
# Some Widget render() methods -- notably RadioSelect -- return a
# "special" object rather than a string. Call the __str__() on that
# object to get its rendered value.
value = value.__str__()
return value
def _errors(self): def _errors(self):
""" """
Returns an ErrorList for this field. Returns an empty ErrorList Returns an ErrorList for this field. Returns an empty ErrorList
if there are none. if there are none.
""" """
try: return self.form.errors.get(self.name, ErrorList())
return self._form.errors()[self._name]
except KeyError:
return ErrorList()
errors = property(_errors) errors = property(_errors)
def as_widget(self, widget, attrs=None): def as_widget(self, widget, attrs=None):
return widget.render(self._name, self._form.data.get(self._name, None), attrs=attrs) attrs = attrs or {}
auto_id = self.auto_id
if auto_id and not attrs.has_key('id') and not widget.attrs.has_key('id'):
attrs['id'] = auto_id
return widget.render(self.name, self.data, attrs=attrs)
def as_text(self, attrs=None): def as_text(self, attrs=None):
""" """
@ -167,3 +201,49 @@ class BoundField(object):
def as_textarea(self, attrs=None): def as_textarea(self, attrs=None):
"Returns a string of HTML for representing this as a <textarea>." "Returns a string of HTML for representing this as a <textarea>."
return self.as_widget(Textarea(), attrs) return self.as_widget(Textarea(), attrs)
def as_hidden(self, attrs=None):
"""
Returns a string of HTML for representing this as an <input type="hidden">.
"""
return self.as_widget(HiddenInput(), attrs)
def _data(self):
"Returns the data for this BoundField, or None if it wasn't given."
return self.form.data.get(self.name, None)
data = property(_data)
def _verbose_name(self):
return pretty_name(self.name)
verbose_name = property(_verbose_name)
def label_tag(self, contents=None):
"""
Wraps the given contents in a <label>, if the field has an ID attribute.
Does not HTML-escape the contents. If contents aren't given, uses the
field's HTML-escaped verbose_name.
"""
contents = contents or escape(self.verbose_name)
widget = self.field.widget
id_ = widget.attrs.get('id') or self.auto_id
if id_:
contents = '<label for="%s">%s</label>' % (widget.id_for_label(id_), contents)
return contents
def _is_hidden(self):
"Returns True if this BoundField's widget is hidden."
return self.field.widget.is_hidden
is_hidden = property(_is_hidden)
def _auto_id(self):
"""
Calculates and returns the ID attribute for this BoundField, if the
associated Form has specified auto_id. Returns an empty string otherwise.
"""
auto_id = self.form.auto_id
if auto_id and '%s' in str(auto_id):
return str(auto_id) % self.name
elif auto_id:
return self.name
return ''
auto_id = property(_auto_id)

13
django/newforms/models.py Normal file
View File

@ -0,0 +1,13 @@
"""
Helper functions for creating Forms from Django models and database field objects.
"""
__all__ = ('form_for_model', 'form_for_fields')
def form_for_model(model):
"Returns a Form instance for the given Django model class."
raise NotImplementedError
def form_for_fields(field_list):
"Returns a Form instance for the given list of Django database field instances."
raise NotImplementedError

View File

@ -1,11 +1,22 @@
# Default encoding for input byte strings. from django.conf import settings
DEFAULT_ENCODING = 'utf-8' # TODO: First look at django.conf.settings, then fall back to this.
def smart_unicode(s): def smart_unicode(s):
if not isinstance(s, unicode): if not isinstance(s, basestring):
s = unicode(s, DEFAULT_ENCODING) s = unicode(str(s))
elif not isinstance(s, unicode):
s = unicode(s, settings.DEFAULT_CHARSET)
return s return s
class StrAndUnicode(object):
"""
A class whose __str__ returns its __unicode__ as a bytestring
according to settings.DEFAULT_CHARSET.
Useful as a mix-in.
"""
def __str__(self):
return self.__unicode__().encode(settings.DEFAULT_CHARSET)
class ErrorDict(dict): class ErrorDict(dict):
""" """
A collection of errors that knows how to display itself in various formats. A collection of errors that knows how to display itself in various formats.

View File

@ -5,9 +5,10 @@ HTML Widget classes
__all__ = ( __all__ = (
'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'FileInput', 'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'FileInput',
'Textarea', 'CheckboxInput', 'Textarea', 'CheckboxInput',
'Select', 'SelectMultiple', 'Select', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple',
) )
from util import StrAndUnicode, smart_unicode
from django.utils.html import escape from django.utils.html import escape
from itertools import chain from itertools import chain
@ -16,28 +17,58 @@ try:
except NameError: except NameError:
from sets import Set as set # Python 2.3 fallback from sets import Set as set # Python 2.3 fallback
# Converts a dictionary to a single string with key="value", XML-style. # Converts a dictionary to a single string with key="value", XML-style with
# Assumes keys do not need to be XML-escaped. # a leading space. Assumes keys do not need to be XML-escaped.
flatatt = lambda attrs: ' '.join(['%s="%s"' % (k, escape(v)) for k, v in attrs.items()]) flatatt = lambda attrs: u''.join([u' %s="%s"' % (k, escape(v)) for k, v in attrs.items()])
class Widget(object): class Widget(object):
requires_data_list = False # Determines whether render()'s 'value' argument should be a list. requires_data_list = False # Determines whether render()'s 'value' argument should be a list.
is_hidden = False # Determines whether this corresponds to an <input type="hidden">.
def __init__(self, attrs=None): def __init__(self, attrs=None):
self.attrs = attrs or {} self.attrs = attrs or {}
def render(self, name, value): def render(self, name, value):
raise NotImplementedError raise NotImplementedError
def build_attrs(self, extra_attrs=None, **kwargs):
"Helper function for building an attribute dictionary."
attrs = dict(self.attrs, **kwargs)
if extra_attrs:
attrs.update(extra_attrs)
return attrs
def value_from_datadict(self, data, name):
"""
Given a dictionary of data and this widget's name, returns the value
of this widget. Returns None if it's not provided.
"""
return data.get(name, None)
def id_for_label(self, id_):
"""
Returns the HTML ID attribute of this Widget for use by a <label>,
given the ID of the field. Returns None if no ID is available.
This hook is necessary because some widgets have multiple HTML
elements and, thus, multiple IDs. In that case, this method should
return an ID value that corresponds to the first ID in the widget's
tags.
"""
return id_
id_for_label = classmethod(id_for_label)
class Input(Widget): class Input(Widget):
"Base class for all <input> widgets (except type='checkbox', which is special)" """
Base class for all <input> widgets (except type='checkbox' and
type='radio', which are special).
"""
input_type = None # Subclasses must define this. input_type = None # Subclasses must define this.
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
if value is None: value = '' if value is None: value = ''
final_attrs = dict(self.attrs, type=self.input_type, name=name) final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
if attrs: if value != '': final_attrs['value'] = smart_unicode(value) # Only add the 'value' attribute if a value is non-empty.
final_attrs.update(attrs) return u'<input%s />' % flatatt(final_attrs)
if value != '': final_attrs['value'] = value # Only add the 'value' attribute if a value is non-empty.
return u'<input %s />' % flatatt(final_attrs)
class TextInput(Input): class TextInput(Input):
input_type = 'text' input_type = 'text'
@ -47,6 +78,7 @@ class PasswordInput(Input):
class HiddenInput(Input): class HiddenInput(Input):
input_type = 'hidden' input_type = 'hidden'
is_hidden = True
class FileInput(Input): class FileInput(Input):
input_type = 'file' input_type = 'file'
@ -54,18 +86,28 @@ class FileInput(Input):
class Textarea(Widget): class Textarea(Widget):
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
if value is None: value = '' if value is None: value = ''
final_attrs = dict(self.attrs, name=name) value = smart_unicode(value)
if attrs: final_attrs = self.build_attrs(attrs, name=name)
final_attrs.update(attrs) return u'<textarea%s>%s</textarea>' % (flatatt(final_attrs), escape(value))
return u'<textarea %s>%s</textarea>' % (flatatt(final_attrs), escape(value))
class CheckboxInput(Widget): class CheckboxInput(Widget):
def __init__(self, attrs=None, check_test=bool):
# check_test is a callable that takes a value and returns True
# if the checkbox should be checked for that value.
self.attrs = attrs or {}
self.check_test = check_test
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
final_attrs = dict(self.attrs, type='checkbox', name=name) final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
if attrs: try:
final_attrs.update(attrs) result = self.check_test(value)
if value: final_attrs['checked'] = 'checked' except: # Silently catch exceptions
return u'<input %s />' % flatatt(final_attrs) result = False
if result:
final_attrs['checked'] = 'checked'
if value not in ('', True, False, None):
final_attrs['value'] = smart_unicode(value) # Only add the 'value' attribute if a value is non-empty.
return u'<input%s />' % flatatt(final_attrs)
class Select(Widget): class Select(Widget):
def __init__(self, attrs=None, choices=()): def __init__(self, attrs=None, choices=()):
@ -75,14 +117,13 @@ class Select(Widget):
def render(self, name, value, attrs=None, choices=()): def render(self, name, value, attrs=None, choices=()):
if value is None: value = '' if value is None: value = ''
final_attrs = dict(self.attrs, name=name) final_attrs = self.build_attrs(attrs, name=name)
if attrs: output = [u'<select%s>' % flatatt(final_attrs)]
final_attrs.update(attrs) str_value = smart_unicode(value) # Normalize to string.
output = [u'<select %s>' % flatatt(final_attrs)]
str_value = str(value) # Normalize to string.
for option_value, option_label in chain(self.choices, choices): for option_value, option_label in chain(self.choices, choices):
selected_html = (str(option_value) == str_value) and ' selected="selected"' or '' option_value = smart_unicode(option_value)
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(option_label))) selected_html = (option_value == str_value) and u' selected="selected"' or ''
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(smart_unicode(option_label))))
output.append(u'</select>') output.append(u'</select>')
return u'\n'.join(output) return u'\n'.join(output)
@ -95,19 +136,87 @@ class SelectMultiple(Widget):
def render(self, name, value, attrs=None, choices=()): def render(self, name, value, attrs=None, choices=()):
if value is None: value = [] if value is None: value = []
final_attrs = dict(self.attrs, name=name) final_attrs = self.build_attrs(attrs, name=name)
if attrs: output = [u'<select multiple="multiple"%s>' % flatatt(final_attrs)]
final_attrs.update(attrs) str_values = set([smart_unicode(v) for v in value]) # Normalize to strings.
output = [u'<select multiple="multiple" %s>' % flatatt(final_attrs)]
str_values = set([str(v) for v in value]) # Normalize to strings.
for option_value, option_label in chain(self.choices, choices): for option_value, option_label in chain(self.choices, choices):
selected_html = (str(option_value) in str_values) and ' selected="selected"' or '' option_value = smart_unicode(option_value)
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(option_label))) selected_html = (option_value in str_values) and ' selected="selected"' or ''
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(smart_unicode(option_label))))
output.append(u'</select>') output.append(u'</select>')
return u'\n'.join(output) return u'\n'.join(output)
class RadioSelect(Widget): class RadioInput(StrAndUnicode):
pass "An object used by RadioFieldRenderer that represents a single <input type='radio'>."
def __init__(self, name, value, attrs, choice, index):
self.name, self.value = name, value
self.attrs = attrs
self.choice_value, self.choice_label = choice
self.index = index
class CheckboxSelectMultiple(Widget): def __unicode__(self):
pass return u'<label>%s %s</label>' % (self.tag(), self.choice_label)
def is_checked(self):
return self.value == smart_unicode(self.choice_value)
def tag(self):
if self.attrs.has_key('id'):
self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index)
final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value)
if self.is_checked():
final_attrs['checked'] = 'checked'
return u'<input%s />' % flatatt(final_attrs)
class RadioFieldRenderer(StrAndUnicode):
"An object used by RadioSelect to enable customization of radio widgets."
def __init__(self, name, value, attrs, choices):
self.name, self.value, self.attrs = name, value, attrs
self.choices = choices
def __iter__(self):
for i, choice in enumerate(self.choices):
yield RadioInput(self.name, self.value, self.attrs.copy(), choice, i)
def __unicode__(self):
"Outputs a <ul> for this set of radio fields."
return u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' % w for w in self])
class RadioSelect(Select):
def render(self, name, value, attrs=None, choices=()):
"Returns a RadioFieldRenderer instance rather than a Unicode string."
if value is None: value = ''
str_value = smart_unicode(value) # Normalize to string.
attrs = attrs or {}
return RadioFieldRenderer(name, str_value, attrs, list(chain(self.choices, choices)))
def id_for_label(self, id_):
# RadioSelect is represented by multiple <input type="radio"> fields,
# each of which has a distinct ID. The IDs are made distinct by a "_X"
# suffix, where X is the zero-based index of the radio field. Thus,
# the label for a RadioSelect should reference the first one ('_0').
if id_:
id_ += '_0'
return id_
id_for_label = classmethod(id_for_label)
class CheckboxSelectMultiple(SelectMultiple):
def render(self, name, value, attrs=None, choices=()):
if value is None: value = []
final_attrs = self.build_attrs(attrs, name=name)
output = [u'<ul>']
str_values = set([smart_unicode(v) for v in value]) # Normalize to strings.
cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
for option_value, option_label in chain(self.choices, choices):
option_value = smart_unicode(option_value)
rendered_cb = cb.render(name, option_value)
output.append(u'<li><label>%s %s</label></li>' % (rendered_cb, escape(smart_unicode(option_label))))
output.append(u'</ul>')
return u'\n'.join(output)
def id_for_label(self, id_):
# See the comment for RadioSelect.id_for_label()
if id_:
id_ += '_0'
return id_
id_for_label = classmethod(id_for_label)

View File

@ -742,7 +742,11 @@ class VariableNode(Node):
def encode_output(self, output): def encode_output(self, output):
# Check type so that we don't run str() on a Unicode object # Check type so that we don't run str() on a Unicode object
if not isinstance(output, basestring): if not isinstance(output, basestring):
return str(output) try:
return str(output)
except UnicodeEncodeError:
# If __str__() returns a Unicode object, convert it to bytestring.
return unicode(output).encode(settings.DEFAULT_CHARSET)
elif isinstance(output, unicode): elif isinstance(output, unicode):
return output.encode(settings.DEFAULT_CHARSET) return output.encode(settings.DEFAULT_CHARSET)
else: else:

View File

@ -84,7 +84,7 @@ def object_detail(request, queryset, object_id=None, slug=None,
context_processors=None, template_object_name='object', context_processors=None, template_object_name='object',
mimetype=None): mimetype=None):
""" """
Generic list of objects. Generic detail of an object.
Templates: ``<app_label>/<model_name>_detail.html`` Templates: ``<app_label>/<model_name>_detail.html``
Context: Context:

View File

@ -48,6 +48,23 @@ See the `csrf documentation`_.
.. _csrf documentation: http://www.djangoproject.com/documentation/csrf/ .. _csrf documentation: http://www.djangoproject.com/documentation/csrf/
formtools
=========
**New in Django development version**
A set of high-level abstractions for Django forms (django.newforms).
django.contrib.formtools.preview
--------------------------------
An abstraction of the following workflow:
"Display an HTML form, force a preview, then do something with the submission."
Full documentation for this feature does not yet exist, but you can read the
code and docstrings in ``django/contrib/formtools/preview.py`` for a start.
humanize humanize
======== ========

79
docs/newforms.txt Normal file
View File

@ -0,0 +1,79 @@
====================
The newforms library
====================
``django.newforms`` is a new replacement for ``django.forms``, the old Django
form/manipulator/validation framework. This document explains how to use this
new form library.
Migration plan
==============
``django.newforms`` currently is only available in 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:
* Move the current ``django.forms`` to ``django.oldforms``. This will allow
for an eased migration of form code. You'll just have to change your
import statements::
from django import forms # old
from django import oldforms as forms # new
* Move the current ``django.newforms`` to ``django.forms``.
* 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 ``django.oldforms``.
With this in mind, we recommend you use the following import statement when
using ``django.newforms``::
from django import newforms as forms
This way, your code can refer to the ``forms`` module, and when
``django.newforms`` is renamed to ``django.forms``, you'll only have to change
your ``import`` statements.
If you prefer "``import *``" syntax, you can do the following::
from django.newforms import *
This will import all fields, widgets, form classes and other various utilities
into your local namespace. Some people find this convenient; others find it
too messy. The choice is yours.
Overview
========
As the ``django.forms`` system before it, ``django.newforms`` is intended to
handle HTML form display, validation and redisplay. It's what you use if you
want to perform server-side validation for an HTML form.
The library deals with these concepts:
* **Widget** -- A class that corresponds to an HTML form widget, e.g.
``<input type="text">`` or ``<textarea>``. This handles rendering of the
widget as HTML.
* **Field** -- A class that is responsible for doing validation, e.g.
an ``EmailField`` that makes sure its data is a valid e-mail address.
* **Form** -- A collection of fields that knows how to validate itself and
display itself as HTML.
Using forms with templates
==========================
Using forms in views
====================
More coming soon
================
That's all the documentation for now. For more, see the file
http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/forms/tests.py
-- the unit tests for ``django.newforms``. This can give you a good idea of
what's possible.

View File

@ -141,7 +141,7 @@ Do this after you've verified that the test cookie worked.
Here's a typical usage example:: Here's a typical usage example::
def login(request): def login(request):
if request.POST: if request.method == 'POST':
if request.session.test_cookie_worked(): if request.session.test_cookie_worked():
request.session.delete_test_cookie() request.session.delete_test_cookie()
return HttpResponse("You're logged in.") return HttpResponse("You're logged in.")

View File

@ -830,7 +830,7 @@ Default: ``Django/<version> (http://www.djangoproject.com/)``
The string to use as the ``User-Agent`` header when checking to see if URLs The string to use as the ``User-Agent`` header when checking to see if URLs
exist (see the ``verify_exists`` option on URLField_). exist (see the ``verify_exists`` option on URLField_).
.. URLField: ../model_api/#urlfield .. _URLField: ../model_api/#urlfield
USE_ETAGS USE_ETAGS
--------- ---------

View File

@ -5,9 +5,9 @@ The sitemap framework
**New in Django development version**. **New in Django development version**.
Django comes with a high-level sitemap-generating framework that makes Django comes with a high-level sitemap-generating framework that makes
creating `Google Sitemap`_ XML files easy. creating sitemap_ XML files easy.
.. _Google Sitemap: http://www.google.com/webmasters/sitemaps/docs/en/protocol.html .. _sitemap: http://www.sitemaps.org/
Overview Overview
======== ========
@ -55,11 +55,12 @@ URLconf_:
This tells Django to build a sitemap when a client accesses ``/sitemap.xml``. This tells Django to build a sitemap when a client accesses ``/sitemap.xml``.
The name of the sitemap file is not important, but the location is. Google will The name of the sitemap file is not important, but the location is. Search
only index links in your sitemap for the current URL level and below. For engines will only index links in your sitemap for the current URL level and
instance, if ``sitemap.xml`` lives in your root directory, it may reference any below. For instance, if ``sitemap.xml`` lives in your root directory, it may
URL in your site. However, if your sitemap lives at ``/content/sitemap.xml``, reference any URL in your site. However, if your sitemap lives at
it may only reference URLs that begin with ``/content/``. ``/content/sitemap.xml``, it may only reference URLs that begin with
``/content/``.
The sitemap view takes an extra, required argument: ``{'sitemaps': sitemaps}``. The sitemap view takes an extra, required argument: ``{'sitemaps': sitemaps}``.
``sitemaps`` should be a dictionary that maps a short section label (e.g., ``sitemaps`` should be a dictionary that maps a short section label (e.g.,
@ -199,9 +200,9 @@ If it's an attribute, its value should be either a string or float representing
the priority of *every* object returned by ``items()``. the priority of *every* object returned by ``items()``.
Example values for ``priority``: ``0.4``, ``1.0``. The default priority of a Example values for ``priority``: ``0.4``, ``1.0``. The default priority of a
page is ``0.5``. See Google's documentation for more documentation. page is ``0.5``. See the `sitemaps.org documentation`_ for more.
.. _Google's documentation: http://www.google.com/webmasters/sitemaps/docs/en/protocol.html .. _sitemaps.org documentation: http://www.sitemaps.org/protocol.html#prioritydef
Shortcuts Shortcuts
========= =========

View File

@ -571,7 +571,7 @@ The arguments can be hard-coded strings, so the following is valid::
It is only possible to compare an argument to template variables or strings. It is only possible to compare an argument to template variables or strings.
You cannot check for equality with Python objects such as ``True`` or You cannot check for equality with Python objects such as ``True`` or
``False``. If you need to test if something is true or false, use the ``if`` ``False``. If you need to test if something is true or false, use the ``if``
and ``ifnot`` tags instead. tag instead.
ifnotequal ifnotequal
~~~~~~~~~~ ~~~~~~~~~~

View File

@ -321,7 +321,7 @@ Note::
def some_view(request): def some_view(request):
# ... # ...
return render_to_response('my_template'html', return render_to_response('my_template.html',
my_data_dictionary, my_data_dictionary,
context_instance=RequestContext(request)) context_instance=RequestContext(request))

View File

@ -10,7 +10,7 @@ used to validate that code behaves as expected. When refactoring or
modifying code, tests serve as a guide to ensure that behavior hasn't modifying code, tests serve as a guide to ensure that behavior hasn't
changed unexpectedly as a result of the refactor. changed unexpectedly as a result of the refactor.
Testing an web application is a complex task, as there are many Testing a web application is a complex task, as there are many
components of a web application that must be validated and tested. To components of a web application that must be validated and tested. To
help you test your application, Django provides a test execution help you test your application, Django provides a test execution
framework, and range of utilities that can be used to stimulate and framework, and range of utilities that can be used to stimulate and
@ -133,7 +133,7 @@ together, picking the test system to match the type of tests you need to
write. write.
For developers new to testing, however, this choice can seem For developers new to testing, however, this choice can seem
confusing, so here are a few key differences to help you decide weather confusing, so here are a few key differences to help you decide whether
doctests or unit tests are right for you. doctests or unit tests are right for you.
If you've been using Python for a while, ``doctest`` will probably feel more If you've been using Python for a while, ``doctest`` will probably feel more

View File

@ -11,13 +11,17 @@ for scheme in INSTALL_SCHEMES.values():
# Compile the list of packages available, because distutils doesn't have # Compile the list of packages available, because distutils doesn't have
# an easy way to do this. # an easy way to do this.
packages, data_files = [], [] packages, data_files = [], []
root_dir = os.path.join(os.path.dirname(__file__), 'django') root_dir = os.path.dirname(__file__)
for dirpath, dirnames, filenames in os.walk(root_dir): len_root_dir = len(root_dir)
django_dir = os.path.join(root_dir, 'django')
for dirpath, dirnames, filenames in os.walk(django_dir):
# Ignore dirnames that start with '.' # Ignore dirnames that start with '.'
for i, dirname in enumerate(dirnames): for i, dirname in enumerate(dirnames):
if dirname.startswith('.'): del dirnames[i] if dirname.startswith('.'): del dirnames[i]
if '__init__.py' in filenames: if '__init__.py' in filenames:
packages.append(dirpath.replace('/', '.')) package = dirpath[len_root_dir:].lstrip('/').replace('/', '.')
packages.append(package)
else: else:
data_files.append((dirpath, [os.path.join(dirpath, f) for f in filenames])) data_files.append((dirpath, [os.path.join(dirpath, f) for f in filenames]))

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from django.conf import settings from django.conf import settings
if __name__ == '__main__': if __name__ == '__main__':
@ -62,6 +63,11 @@ class OtherClass:
def method(self): def method(self):
return "OtherClass.method" return "OtherClass.method"
class UnicodeInStrClass:
"Class whose __str__ returns a Unicode object."
def __str__(self):
return u'ŠĐĆŽćžšđ'
class Templates(unittest.TestCase): class Templates(unittest.TestCase):
def test_templates(self): def test_templates(self):
# NOW and NOW_tz are used by timesince tag tests. # NOW and NOW_tz are used by timesince tag tests.
@ -173,6 +179,10 @@ class Templates(unittest.TestCase):
# Empty strings can be passed as arguments to filters # Empty strings can be passed as arguments to filters
'basic-syntax36': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'), 'basic-syntax36': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'),
# If a variable has a __str__() that returns a Unicode object, the value
# will be converted to a bytestring.
'basic-syntax37': (r'{{ var }}', {'var': UnicodeInStrClass()}, '\xc5\xa0\xc4\x90\xc4\x86\xc5\xbd\xc4\x87\xc5\xbe\xc5\xa1\xc4\x91'),
### COMMENT SYNTAX ######################################################## ### COMMENT SYNTAX ########################################################
'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"), 'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),
'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"), 'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"),
@ -328,18 +338,18 @@ class Templates(unittest.TestCase):
'ifchanged05': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'), 'ifchanged05': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'),
'ifchanged06': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'), 'ifchanged06': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'),
'ifchanged07': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'), 'ifchanged07': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'),
# Test one parameter given to ifchanged. # Test one parameter given to ifchanged.
'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'), 'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'),
'ifchanged-param02': ('{% for n in num %}{% for x in numx %}{% ifchanged n %}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}', { 'num': (1,2,3), 'numx': (5,6,7) }, '..567..567..567'), 'ifchanged-param02': ('{% for n in num %}{% for x in numx %}{% ifchanged n %}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}', { 'num': (1,2,3), 'numx': (5,6,7) }, '..567..567..567'),
# Test multiple parameters to ifchanged. # Test multiple parameters to ifchanged.
'ifchanged-param03': ('{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1,1,2), 'numx': (5,6,6) }, '156156256'), 'ifchanged-param03': ('{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1,1,2), 'numx': (5,6,6) }, '156156256'),
# Test a date+hour like construct, where the hour of the last day # Test a date+hour like construct, where the hour of the last day
# is the same but the date had changed, so print the hour anyway. # is the same but the date had changed, so print the hour anyway.
'ifchanged-param04': ('{% for d in days %}{% ifchanged %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'), 'ifchanged-param04': ('{% for d in days %}{% ifchanged %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),
# Logically the same as above, just written with explicit # Logically the same as above, just written with explicit
# ifchanged for the day. # ifchanged for the day.
'ifchanged-param04': ('{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'), 'ifchanged-param04': ('{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),